Skip to content

Fix #94 Return proper status code for large responses and #95 Support decompression#97

Merged
VikramAditya33 merged 1 commit into
mainfrom
e2e/test
May 7, 2026
Merged

Fix #94 Return proper status code for large responses and #95 Support decompression#97
VikramAditya33 merged 1 commit into
mainfrom
e2e/test

Conversation

@VikramAditya33
Copy link
Copy Markdown
Collaborator

@VikramAditya33 VikramAditya33 commented May 7, 2026

  • Request bodies with Content-Encoding: gzip/deflate/br are now automatically decompressed.
  • When request body exceeds maxBodySize, it now returns proper HTTP 413 Payload Too Large response.

Fix #94
Fix #95

Summary by CodeRabbit

  • New Features

    • Added automatic decompression support for compressed request bodies.
  • Bug Fixes

    • Improved error handling for unsupported compression formats and decompression stream failures with appropriate HTTP error responses.
    • Enhanced request body size validation and enforcement for better resource protection.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 63daba99-cd01-4fe6-8966-d1df518fcb48

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch e2e/test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

uWestJS Benchmark Results

Scenario Express req/s Fastify req/s uWestJS req/s Express throughput Fastify throughput uWestJS throughput uWestJS vs Express uWestJS vs Fastify
compression 8.21k 6.79k 10.00k 4.32 MB/s 3.48 MB/s 4.60 MB/s 1.22x 1.47x
headers 29.13k 50.36k 88.15k 5.42 MB/s 9.41 MB/s 13.87 MB/s 3.03x 1.75x
hello-world 28.61k 49.55k 107.73k 4.75 MB/s 8.32 MB/s 10.69 MB/s 3.77x 2.17x
json-response 28.77k 42.51k 83.74k 7.85 MB/s 11.64 MB/s 20.44 MB/s 2.91x 1.97x
mixed-response 29.98k 42.68k 85.95k 6.92 MB/s 9.89 MB/s 17.38 MB/s 2.87x 2.01x
post-json 25.43k 22.36k 46.06k 4.70 MB/s 6.10 MB/s 7.82 MB/s 1.81x 2.06x
query-params 23.34k 41.98k 90.11k 5.14 MB/s 9.29 MB/s 12.12 MB/s 3.86x 2.15x
route-params 27.76k 47.60k 87.18k 6.33 MB/s 10.90 MB/s 17.38 MB/s 3.14x 1.83x
static-file 30.02k 43.52k 77.85k 297.90 MB/s 431.39 MB/s 770.44 MB/s 2.59x 1.79x
streaming-upload 260.68 265.94 273.63 58.04 KB/s 55.58 KB/s 52.91 KB/s 1.05x 1.03x
streaming-with-content-length 531.90 539.74 540.67 2.60 GB/s 2.64 GB/s 2.64 GB/s 1.02x 1.00x
streaming-without-content-length 525.13 538.47 532.58 2.56 GB/s 2.63 GB/s 2.60 GB/s 1.01x 0.99x

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/http/core/request.ts (1)

256-262: ⚡ Quick win

decompressionStream.write() ignores backpressure — unbounded memory growth under load.

Writable.write() returns false when the stream's internal buffer is full and callers should stop writing until 'drain' fires. By ignoring the return value, uWS data is pumped into the decompression stream unconditionally. For large or slowly-consumed compressed bodies this can cause the decompression stream's internal buffer to grow without bound.

♻️ Suggested improvement
 if (this.decompressionStream) {
-  this.decompressionStream.write(buffer);
+  if (!this.decompressionStream.write(buffer)) {
+    // Decompression stream buffer full — pause uWS until it drains
+    this.pause();
+    this.decompressionStream.once('drain', () => this.resume());
+  }
   if (isLast) {
     this.decompressionStream.end();
   }
   return;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/http/core/request.ts` around lines 256 - 262, The current block writing
to this.decompressionStream ignores Writable.write() backpressure; change it to
check the boolean return of this.decompressionStream.write(buffer) and, if it
returns false, stop pushing more uWS data (queue the current chunk or mark
stream as paused), attach a one-time 'drain' listener on
this.decompressionStream to resume writing queued chunks and, if isLast was
true, call this.decompressionStream.end() only after drain/resume; ensure you
don't attach duplicate 'drain' handlers (use a flag or single listener) and
correctly handle the isLast path so the stream is ended after buffered data is
flushed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/http/core/request.ts`:
- Around line 943-946: The decompressor 'end' handler currently only sets
doneReadingData and emits 'received', which leaves streaming consumers hanging
because processDecompressedChunk only calls push(null) when isLast === true and
activateStreaming checks doneReadingData at activation time; update the
decompress.on('end') handler to also signal stream EOF by calling the same code
path that emits push(null) — e.g., mark doneReadingData = true, emit 'received',
and invoke the logic that pushes null to the readable stream (the same
termination behavior used when processDecompressedChunk is called with isLast
=== true) so streaming-mode consumers receive end even when decompression
finishes without a final chunk.
- Around line 948-967: In the decompress 'error' handler add setting
this.aborted = true (same way _onAbort does) so subsequent calls to
handleIncomingChunk will bail out before writing to the destroyed decompression
stream; specifically, inside the decompress.on('error', ...) block (where
this.flushing and this.abortError are set and responseWrapper/uwsRes handling
and this.destroy(...) occur) set this.aborted = true immediately after setting
this.abortError to prevent writes to the destroyed Transform in
handleIncomingChunk().

---

Nitpick comments:
In `@src/http/core/request.ts`:
- Around line 256-262: The current block writing to this.decompressionStream
ignores Writable.write() backpressure; change it to check the boolean return of
this.decompressionStream.write(buffer) and, if it returns false, stop pushing
more uWS data (queue the current chunk or mark stream as paused), attach a
one-time 'drain' listener on this.decompressionStream to resume writing queued
chunks and, if isLast was true, call this.decompressionStream.end() only after
drain/resume; ensure you don't attach duplicate 'drain' handlers (use a flag or
single listener) and correctly handle the isLast path so the stream is ended
after buffered data is flushed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 14bf2ee4-c9f4-4a7a-9f43-7769db5c6b3a

📥 Commits

Reviewing files that changed from the base of the PR and between e8c673e and e73ce65.

📒 Files selected for processing (1)
  • src/http/core/request.ts

Comment thread src/http/core/request.ts
Comment thread src/http/core/request.ts
@VikramAditya33 VikramAditya33 merged commit 4a7b503 into main May 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Content-Encoding Decompression for Request Bodies Return 413 Status Code for Body Size Limit Exceeded

1 participant