add options to ingestBody
authorJustin Wind <justin.wind+git@gmail.com>
Sat, 12 Mar 2022 22:04:17 +0000 (14:04 -0800)
committerJustin Wind <justin.wind+git@gmail.com>
Sat, 12 Mar 2022 22:04:17 +0000 (14:04 -0800)
lib/dingus.js
test/lib/dingus.js

index 1098ea7dc54041f57a6987bfad6b9560a149ae94..51da6fab6b2185680cace1f8d1ad48921283d59d 100644 (file)
@@ -311,21 +311,27 @@ class Dingus {
 
 
   /**
-   * Parse rawBody from ctx as contentType into parsedBody.
-   * @param {string} contentType 
-   * @param {object} ctx 
-   */
-  parseBody(contentType, ctx) {
+   * Parse rawBody as contentType into ctx.parsedBody.
+   * @param {string} contentType
+   * @param {object} ctx
+   * @param {string|buffer}
+  */
+  parseBody(contentType, ctx, rawBody) {
     const _scope = _fileScope('parseBody');
 
+    if (!rawBody) {
+      // 1.2.4 and earlier expected rawBody on context
+      rawBody = ctx.rawBody;
+    }
+
     switch (contentType) {
       case Enum.ContentType.ApplicationForm:
-        ctx.parsedBody = this.querystring.parse(ctx.rawBody);
+        ctx.parsedBody = this.querystring.parse(rawBody);
         break;
 
       case Enum.ContentType.ApplicationJson:
         try {
-          ctx.parsedBody = JSON.parse(ctx.rawBody);
+          ctx.parsedBody = JSON.parse(rawBody);
         } catch (e) {
           this.logger.debug(_scope, 'JSON parse failed', { requestId: ctx.requestId, error: e });
           throw new ResponseError(Enum.ErrorResponse.BadRequest, e.message);
@@ -371,11 +377,19 @@ class Dingus {
    * @param {http.ClientRequest} req
    * @param {http.ServerResponse} res
    * @param {object} ctx
-   */
-  async ingestBody(req, res, ctx) {
-    ctx.rawBody = await this.bodyData(req);
-    const contentType = Dingus.getRequestContentType(req);
-    this.parseBody(contentType, ctx);
+   * @param {object}
+   * @param {Boolean} .parseEmptyBody
+   * @param {Boolean} .persistRawBody
+   */
+  async ingestBody(req, res, ctx, { parseEmptyBody = true, persistRawBody = false, maximumBodySize } = {}) {
+    const rawBody = await this.bodyData(req, maximumBodySize);
+    if (persistRawBody) {
+      ctx.rawBody = rawBody;
+    }
+    if (rawBody || parseEmptyBody) {
+      const contentType = Dingus.getRequestContentType(req);
+      this.parseBody(contentType, ctx, rawBody);
+    }
   }
 
 
index b478a454aa3eb5b4b3ad8027382e4f5f23bd0681..356974fee0f48342dd80cfd710ccbd91bb64b210 100644 (file)
@@ -538,7 +538,7 @@ describe('Dingus', function () {
   }); // bodyData
 
   describe('ingestBody', function () {
-    it('covers', async function () {
+    it('ingests json', async function () {
       const req = {};
       const res = {};
       const ctx = {};
@@ -546,6 +546,30 @@ describe('Dingus', function () {
       sinon.stub(Dingus, 'getRequestContentType').returns(Enum.ContentType.ApplicationJson);
       await dingus.ingestBody(req, res, ctx);
       assert.deepStrictEqual(ctx.parsedBody, { foo: 'bar' });
+      assert.deepStrictEqual(ctx.rawBody, undefined);
+    });
+    it('persists rawBody', async function () {
+      const req = {};
+      const res = {};
+      const ctx = {};
+      const body = '{"foo":"bar"}';
+      sinon.stub(dingus, 'bodyData').resolves(body);
+      sinon.stub(Dingus, 'getRequestContentType').returns(Enum.ContentType.ApplicationJson);
+      await dingus.ingestBody(req, res, ctx, { persistRawBody: true });
+      assert.deepStrictEqual(ctx.parsedBody, { foo: 'bar' });
+      assert.deepStrictEqual(ctx.rawBody, body);
+    });
+    it('skips parsing empty body', async function () {
+      const req = {};
+      const res = {};
+      const ctx = {};
+      const body = '';
+      sinon.stub(dingus, 'bodyData').resolves(body);
+      sinon.stub(Dingus, 'getRequestContentType').returns(Enum.ContentType.ApplicationJson);
+      sinon.spy(dingus, 'parseBody');
+      await dingus.ingestBody(req, res, ctx, { parseEmptyBody: false });
+      assert.deepStrictEqual(ctx.parsedBody, undefined);
+      assert(dingus.parseBody.notCalled);
     });
   }); // ingestBody