Merge branch 'v2.1-dev'
[squeep-api-dingus] / lib / dingus.js
index 0a5f9d8d50badb5dc0ceb3b4a3c4d876a87cc58e..f060c18f00d251f610a97929fdce663c9f01de89 100644 (file)
@@ -35,6 +35,8 @@ const defaultOptions = {
   querystring,
 };
 
+const cookieSplitRE = /; */;
+
 class Dingus {
   /**
    * @param {Object} logger object which implements logging methods
@@ -118,6 +120,9 @@ class Dingus {
   /**
    * Common header tagging for all requests.
    * Add our own identifier, and persist any external transit identifiers.
+   * Sets requestId on ctx to a new uuid.
+   * If X-Request-Id or X-Correlation-Id exist on incoming headers, sets them
+   * on outgoing headers and sets on ctx.
    * @param {http.ClientRequest} req 
    * @param {http.ServerResponse} res 
    * @param {object} ctx 
@@ -164,7 +169,7 @@ class Dingus {
 
 
   /**
-   * 
+   * Sets ctx.clientAddress and ctx.clientProtocol.
    * @param {http.ClientRequest} req 
    * @param {http.ServerResponse} res 
    * @param {object} ctx 
@@ -176,14 +181,40 @@ class Dingus {
 
 
   /**
-   * Called before every request handler.
+   * Sets ctx.cookie from Cookie header.
    * @param {http.ClientRequest} req 
    * @param {http.ServerResponse} res 
    * @param {object} ctx 
    */
+  static ingestCookie(req, res, ctx) {
+    ctx.cookie = {};
+    req.getHeader(Enum.Header.Cookie)?.split(cookieSplitRE).forEach((cookie) => {
+      const [ name, value ] = common.splitFirst(cookie, '=', null).map((x) => {
+        try {
+          return decodeURIComponent(x.trim());
+        } catch (e) {
+          return x;
+        }
+      });
+      if (name && !(name in ctx.cookie)) {
+        const isQuoted = value?.startsWith('"') && value.endsWith('"');
+        ctx.cookie[name] = isQuoted ? value.slice(1, -1) : value; // eslint-disable-line security/detect-object-injection
+      }
+    });
+  }
+
+
+  /**
+   * Called before every request handler.
+   * Sets tracking identifiers and client information on ctx.
+   * @param {http.ClientRequest} req
+   * @param {http.ServerResponse} res
+   * @param {object} ctx
+   */
   async preHandler(req, res, ctx) {
-    Dingus.tagContext(req, res, ctx);
+    this.constructor.tagContext(req, res, ctx);
     this.clientAddressContext(req, res, ctx);
+    this.constructor.ingestCookie(req, res, ctx);
   }
 
 
@@ -411,6 +442,7 @@ class Dingus {
 
   /**
    * Read and parse request body data.
+   * Sets ctx.parsedBody, and optionally ctx.rawBody.
    * @param {http.ClientRequest} req
    * @param {http.ServerResponse} res
    * @param {object} ctx
@@ -454,6 +486,7 @@ class Dingus {
 
   /**
    * Set the best content type for the response.
+   * Sets ctx.responseType, and Content-Type header.
    * @param {string[]} responseTypes default first
    * @param {http.ClientRequest} req 
    * @param {http.ServerResponse} res 
@@ -475,7 +508,7 @@ class Dingus {
 
 
   /**
-   * Inserts an encoding
+   * Inserts an encoding into Content-Encoding header.
    * @param {http.ServerResponse} res
    * @param {string} encoding
    */