support maximum request body size
authorJustin Wind <justin.wind+git@gmail.com>
Sat, 12 Mar 2022 21:08:55 +0000 (13:08 -0800)
committerJustin Wind <justin.wind+git@gmail.com>
Sat, 12 Mar 2022 21:50:39 +0000 (13:50 -0800)
lib/dingus.js
lib/enum.js
test/lib/dingus.js

index 84c1d14b6a38e4d9050e76eaf7095588f501196d..11bdf998373789b9a9a1584ffb71f5b30661be76 100644 (file)
@@ -337,12 +337,21 @@ class Dingus {
   /**
    * Return all body data from a request.
    * @param {http.ClientRequest} req
+   * @param {Number=} maximumBodySize
    */
-  async bodyData(req) {
+  async bodyData(req, maximumBodySize) {
     const _scope = _fileScope('bodyData');
     return new Promise((resolve, reject) => {
       const body = [];
-      req.on('data', (chunk) => body.push(chunk));
+      let length = 0;
+      req.on('data', (chunk) => {
+        body.push(chunk);
+        length += Buffer.byteLength(chunk);
+        if (maximumBodySize && length > maximumBodySize) {
+          this.logger.debug(_scope, 'body data exceeded limit', { length, maximumBodySize });
+          reject(new ResponseError(Enum.ErrorResponse.RequestEntityTooLarge));
+        }
+      });
       req.on('end', () => resolve(Buffer.concat(body).toString()));
       req.on('error', (e) => {
         this.logger.error(_scope, 'failed', { error: e });
index ef8e77342b709d8a7954024f45f9becf2e6e27ce..e24ed6f52a8b85347fbc2e55666fd9d2ae42a13e 100644 (file)
@@ -56,6 +56,10 @@ const ErrorResponse = {
     statusCode: 410,
     errorMessage: 'Gone',
   },
+  RequestEntityTooLarge: {
+    statusCode: 413,
+    errorMessage: 'Request Entity Too Large',
+  },
   UnsupportedMediaType: {
     statusCode: 415,
     errorMessage: 'Unsupported Media Type',
index 519feb0bb27e0ee30fb8d9b50999d21761d60b88..23b7e8c4a834fad503664b0c9bb0d3ab00bee7e4 100644 (file)
@@ -514,6 +514,17 @@ describe('Dingus', function () {
         assert.strictEqual(e, 'foo');
       }
     });
+    it('limits size', async function () {
+      const p = dingus.bodyData(res, 8);
+      resEvents['data'](Buffer.from('foobar'));
+      resEvents['data'](Buffer.from('bazquux'));
+      try {
+        await p;
+        assert.fail(noExpectedException);
+      } catch (e) {
+        assert.strictEqual(e.statusCode, 413);
+      }
+    });
   }); // bodyData
 
   describe('ingestBody', function () {