Skip to content

fix(aws-lambda): always send the metadata prelude - #101

Merged
dinwwwh merged 1 commit into
mainfrom
claude/lambda-response-prelude-fix-a6b15e
Sep 25, 2026
Merged

dinwwwh merged 1 commit into
mainfrom
claude/lambda-response-prelude-fix-a6b15e

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 25, 2026

Copy link
Copy Markdown
Member

On AWS Lambda, sendStandardResponse could send a response without its metadata prelude, so the status, headers, and cookies were lost. HttpResponseStream.from() only sets the prelude up, and the runtime sends it just before the first write() call. end(chunk) skips that, and empty bodies never call write(). The fix makes one empty write right after from() so every response sends its prelude.

Fixes

  • JSON, URLSearchParams, undefined, empty-Blob, and empty-stream responses now send their status, headers, and cookies. Before, they reached the wire as just the body, or as zero bytes.
  • Non-empty streamed responses are unaffected, apart from sending their status and headers right away instead of waiting for the first chunk.

Testing

  • Checked against the stream code in aws-lambda-ric 4.0.2 (3.3.0 uses the same prelude logic). The bytes were captured by a local HTTP server standing in for the Lambda API. Every body type now carries the prelude and delimiter exactly once. Not tested on a real Lambda deployment.
  • The unit-test mock used to write the prelude itself, which hid the bug. It now waits for the first write() like the runtime. Without the fix, 3 tests fail: buffered (empty), buffered (json), and the new chunked (empty).

The Lambda runtime only sends the prelude armed by
`HttpResponseStream.from()` ahead of the first `write` call.
`end(chunk)` bypasses it and empty bodies never write, so buffered,
empty, and empty-stream responses lost their status, headers, and
cookies. Trigger the prelude with an empty write right after `from()`.

The test mock now defers the prelude to the first `write` like the
runtime does, so it no longer hides this.
@pkg-pr-new

pkg-pr-new Bot commented Sep 25, 2026

Copy link
Copy Markdown
@standard-server/aws-lambda

npm i https://pkg.pr.new/@standard-server/aws-lambda@101

@standard-server/core

npm i https://pkg.pr.new/@standard-server/core@101

@standard-server/fastify

npm i https://pkg.pr.new/@standard-server/fastify@101

@standard-server/fetch

npm i https://pkg.pr.new/@standard-server/fetch@101

@standard-server/node

npm i https://pkg.pr.new/@standard-server/node@101

@standard-server/peer

npm i https://pkg.pr.new/@standard-server/peer@101

@standard-server/shared

npm i https://pkg.pr.new/@standard-server/shared@101

commit: e4a8cb1

@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed

codspeed Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 108 skipped benchmarks1


Comparing claude/lambda-response-prelude-fix-a6b15e (e4a8cb1) with main (a6c90ca)

Open in CodSpeed

Footnotes

  1. 108 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • res.write('') forces the prelude — sendStandardResponse now writes an empty chunk right after HttpResponseStream.from(), so status/headers/cookies are flushed even when the body is undefined, an empty Blob/stream, or a string sent via end(chunk).
  • Test mock now matches the runtime — fromSpy arms the prelude on the first write only (restoring the original write first) instead of emitting the prelude itself, which is what hid the bug.
  • New chunked (empty) test — covers an empty Blob body, the case where pipe() never calls write.
  • JSDoc wording — from() now documented as arming the prelude, sent only ahead of the first write.

I verified the fix against the aws-lambda-ric source and with a local reproduction: HttpResponseStream.from() only sets _onBeforeFirstWrite, the patched request.write emits the prelude when status is still ready, and Node's Writable.end(chunk) bypasses the overridden public write (so end(chunk) indeed skipped the prelude). Replicating the RIC logic against a raw TCP server shows the prelude + 8-byte delimiter emitted exactly once for empty, JSON, and streamed bodies, with no spurious empty HTTP chunk. Reverting res.write('') makes exactly the three named tests fail, so the new coverage is real. Tests, type:check, and eslint on the changed files all pass.

Pullfrog  | View workflow run | Using DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

@dinwwwh
dinwwwh merged commit c8338a6 into main Sep 25, 2026
11 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.

1 participant