feat: add aws-apigw-streaming wrapper for API Gateway response streaming#1181
Merged
conico974 merged 3 commits intoJun 19, 2026
Merged
Conversation
OpenNext's only streaming wrapper (aws-lambda-streaming) targets the Lambda Function URL wire format: it sets the application/vnd.awslambda.http-integration-response content type and gzips/ brotlis the body. Neither is valid for an API Gateway proxy integration in ResponseTransferMode: STREAM — API Gateway forwards the content-type marker onto the wire (breaking framing) and does not support content encoding. Add a dedicated aws-apigw-streaming wrapper that emits the same JSON-prelude + 8-null-byte framing (which API Gateway STREAM shares with Function URLs) but omits the FURL content-type marker and forces identity encoding. Pair it with aws-apigw-v1 and aws-apigw-v2 in the compatibility matrix. Refs opennextjs#1090
canStream() hard-coded the aws-lambda-streaming name, so a function using the new aws-apigw-streaming wrapper was written to open-next.output.json with streaming:false. Recognize both built-in streaming wrappers.
🦋 Changeset detectedLatest commit: efc4e9d The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
conico974
approved these changes
Jun 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
OpenNext's only streaming wrapper,
aws-lambda-streaming, targets the Lambda Function URL streaming wire format. There was no streaming wrapper for API Gateway, even though:API Gateway REST APIs now support response streaming (announced Nov 2025): https://aws.amazon.com/about-aws/whats-new/2025/11/api-gateway-response-streaming-rest-apis/ — via
ResponseTransferMode: STREAMon a Lambda proxy integration (InvokeWithResponseStreaming).Lambda Function URLs are unusable behind CloudFront + OAC for
POST/PUT. OAC signs the request with SigV4 (including a body hash); the Function URL re-hashes the received body and the two diverge, returning403 InvalidSignatureExceptionon every non-empty body: https://repost.aws/questions/QUbHCI9AfyRdaUPCCo_3XKMQ/lambda-function-url-behind-cloudfront-invalidsignatureexception-only-on-post . API Gateway REST useslambda:InvokeFunction(no body re-hash), soPOST/PUTbodies — including binary uploads — pass through intact.So the natural transport for a CloudFront-fronted SSR Lambda that must accept
POSTbodies and stream responses is API Gateway REST in STREAM mode. But the existing streaming wrapper can't be used there: it emits a Function-URL-only content-type marker and compresses the body, both of which break API Gateway streaming.This is also what #1090 ("Clarify streaming support with apigateway-v2") is about — the wrapper/converter compatibility matrix implies streaming pairs with API Gateway, but the only streaming wrapper actually 500s behind a gateway. This PR adds the missing piece and addresses #1090.
Related: #1127 — origin-level compression in
aws-lambda-streamingcauses periodic 502s behind a Function URL, and the proposed fix is to fall back toidentity. This new wrapper sidesteps that class of issue entirely: it never compresses and always emitsidentity, consistent with AWS's note that API Gateway streaming does not support content encoding (CloudFront compresses downstream).What this PR changes
A new built-in wrapper,
aws-apigw-streaming— 4 files, +118 lines. It keeps the framing that API Gateway STREAM shares with Function URLs (a JSON metadata prelude + 8-null-byte delimiter, then the body) but omits the two things that break API Gateway:application/vnd.awslambda.http-integration-responsecontent type. That marker is Function-URL-specific metadata for the Lambda runtime; API Gateway forwards it onto the wire and corrupts HTTP framing.identity. Compression, if desired, is handled by the CDN in front (e.g. CloudFront).src/overrides/wrappers/aws-apigw-streaming.tsstreamifyResponse, omits the FURL content-type marker, forcesidentityencoding. Works with either API Gateway payload format via its paired converter.src/types/open-next.ts"aws-apigw-streaming"to theIncludedWrapperunion.src/build/validateConfig.ts"aws-apigw-streaming": ["aws-apigw-v1", "aws-apigw-v2"].src/build/generateOutput.tscanStream()recognizes the new wrapper soopen-next.output.jsonreportsstreaming: true.It does not alter
aws-lambda-streamingor any existing behavior — it's purely additive, following the existing precedent of transport-specific wrapper variants (cloudflare-edge,cloudflare-node,aws-lambda-compressed).Usage:
Verification
Deployed a Next.js app built with this wrapper behind API Gateway REST in
ResponseTransferMode: STREAMusing hand-written AWS CDK (no SST, no framework), to prove the wrapper stands on its own.Live demo: https://d376d74ff6kodo.cloudfront.net/streaming-demo
Source (sample app + CDK stack, public): https://github.com/osama-rizk/opennext-apigw-streaming-demo
Verified end to end on the live deployment:
GET /streaming<Suspense>)POSTwith a 1 MB binary bodyhttp-integration-responsemarkers;open-next.output.jsonreportsstreaming: true