cdk-nextjs 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2467 -2714
- package/.jsii.tabl.json +1 -1
- package/API.md +1725 -1909
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +687 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +1548 -185
- package/lib/adapter/adapter.test.js +106 -0
- package/lib/adapter/aws-cache-store.d.ts +489 -0
- package/lib/adapter/aws-cache-store.js +1004 -0
- package/lib/adapter/aws-cache-store.test.d.ts +1 -0
- package/lib/adapter/aws-cache-store.test.js +361 -0
- package/lib/adapter/build-outputs.d.ts +80 -0
- package/lib/adapter/build-outputs.js +852 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +861 -0
- package/lib/adapter/cache-handler.d.ts +9 -2
- package/lib/adapter/cache-handler.js +72 -96
- package/lib/adapter/cache-handler.mjs +18956 -17774
- package/lib/adapter/cache-handler.test.js +263 -31
- package/lib/adapter/cache-kinds.d.ts +32 -0
- package/lib/adapter/cache-kinds.js +35 -0
- package/lib/adapter/cache-kinds.test.d.ts +1 -0
- package/lib/adapter/cache-kinds.test.js +69 -0
- package/lib/adapter/cache-utils.d.ts +90 -0
- package/lib/adapter/cache-utils.js +199 -4
- package/lib/adapter/cache-utils.test.d.ts +1 -0
- package/lib/adapter/cache-utils.test.js +179 -0
- package/lib/adapter/function-groups.d.ts +215 -0
- package/lib/adapter/function-groups.js +1099 -0
- package/lib/adapter/function-groups.test.d.ts +1 -0
- package/lib/adapter/function-groups.test.js +743 -0
- package/lib/adapter/init-cache.d.ts +6 -0
- package/lib/adapter/init-cache.js +245 -0
- package/lib/adapter/init-cache.test.d.ts +1 -0
- package/lib/adapter/init-cache.test.js +137 -0
- package/lib/adapter/local-file-cache-handler.d.ts +23 -0
- package/lib/adapter/local-file-cache-handler.js +52 -1
- package/lib/adapter/memory-cache-handler.d.ts +26 -17
- package/lib/adapter/memory-cache-handler.js +32 -50
- package/lib/adapter/memory-cache-handler.test.js +105 -85
- package/lib/adapter/s3-cache-handler.d.ts +179 -40
- package/lib/adapter/s3-cache-handler.js +807 -277
- package/lib/adapter/s3-cache-handler.test.js +1186 -31
- package/lib/adapter/use-cache-common.d.ts +90 -0
- package/lib/adapter/use-cache-common.js +250 -0
- package/lib/adapter/use-cache-common.test.d.ts +1 -0
- package/lib/adapter/use-cache-common.test.js +646 -0
- package/lib/adapter/use-cache-default-handler.d.ts +24 -0
- package/lib/adapter/use-cache-default-handler.js +90 -0
- package/lib/adapter/use-cache-default-handler.mjs +38645 -0
- package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
- package/lib/adapter/use-cache-handlers.test.js +349 -0
- package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
- package/lib/adapter/use-cache-remote-handler.js +186 -0
- package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
- package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
- package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
- package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
- package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
- package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
- package/lib/lambdas/post-deploy/prune-s3.js +54 -15
- package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +107 -18
- package/lib/nextjs-api.js +349 -39
- package/lib/nextjs-api.test.js +582 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +23 -3
- package/lib/nextjs-post-deploy.js +14 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +23 -4
- package/lib/nextjs-static-assets.js +29 -6
- package/lib/nextjs-static-assets.test.js +20 -1
- package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
- package/lib/root-constructs/nextjs-base-construct.js +144 -34
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -70
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -69
- package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
- package/lib/root-constructs/nextjs-regional-containers.js +17 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -25
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +1213 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1678 -0
- package/lib/runtime/deployment-root.d.ts +13 -0
- package/lib/runtime/deployment-root.js +29 -0
- package/lib/runtime/dispatch.d.ts +331 -0
- package/lib/runtime/dispatch.js +751 -0
- package/lib/runtime/dispatch.test.d.ts +1 -0
- package/lib/runtime/dispatch.test.js +853 -0
- package/lib/runtime/entrypoints.d.ts +57 -0
- package/lib/runtime/entrypoints.js +115 -0
- package/lib/runtime/http/abort-signal.d.ts +6 -0
- package/lib/runtime/http/abort-signal.js +19 -0
- package/lib/runtime/http/abort-signal.test.d.ts +1 -0
- package/lib/runtime/http/abort-signal.test.js +49 -0
- package/lib/runtime/http/node-server.d.ts +38 -0
- package/lib/runtime/http/node-server.js +99 -0
- package/lib/runtime/http/node-server.test.d.ts +1 -0
- package/lib/runtime/http/node-server.test.js +96 -0
- package/lib/runtime/http/node-sink.d.ts +16 -0
- package/lib/runtime/http/node-sink.js +48 -0
- package/lib/runtime/http/node-sink.test.d.ts +1 -0
- package/lib/runtime/http/node-sink.test.js +66 -0
- package/lib/runtime/http/request.d.ts +62 -0
- package/lib/runtime/http/request.js +134 -0
- package/lib/runtime/http/request.test.d.ts +1 -0
- package/lib/runtime/http/request.test.js +103 -0
- package/lib/runtime/http/response.d.ts +77 -0
- package/lib/runtime/http/response.js +229 -0
- package/lib/runtime/http/response.test.d.ts +1 -0
- package/lib/runtime/http/response.test.js +178 -0
- package/lib/runtime/http/sink.d.ts +73 -0
- package/lib/runtime/http/sink.js +188 -0
- package/lib/runtime/http/sink.test.d.ts +1 -0
- package/lib/runtime/http/sink.test.js +257 -0
- package/lib/runtime/image-utils.d.ts +78 -0
- package/lib/runtime/image-utils.js +129 -0
- package/lib/runtime/image-utils.test.d.ts +1 -0
- package/lib/runtime/image-utils.test.js +237 -0
- package/lib/runtime/image.d.ts +76 -0
- package/lib/runtime/image.js +296 -0
- package/lib/runtime/image.test.d.ts +1 -0
- package/lib/runtime/image.test.js +405 -0
- package/lib/runtime/lambda-event.d.ts +4 -0
- package/lib/runtime/lambda-event.js +113 -0
- package/lib/runtime/lambda-event.test.d.ts +1 -0
- package/lib/runtime/lambda-event.test.js +119 -0
- package/lib/runtime/lambda.mjs +41595 -0
- package/lib/runtime/load-module.d.ts +8 -0
- package/lib/runtime/load-module.js +35 -0
- package/lib/runtime/manifest.d.ts +215 -0
- package/lib/runtime/manifest.js +118 -0
- package/lib/runtime/middleware.d.ts +43 -0
- package/lib/runtime/middleware.js +113 -0
- package/lib/runtime/middleware.test.d.ts +1 -0
- package/lib/runtime/middleware.test.js +259 -0
- package/lib/runtime/next-modules.d.ts +55 -0
- package/lib/runtime/next-modules.js +124 -0
- package/lib/runtime/next-modules.test.d.ts +1 -0
- package/lib/runtime/next-modules.test.js +34 -0
- package/lib/runtime/public-files.d.ts +32 -0
- package/lib/runtime/public-files.js +117 -0
- package/lib/runtime/public-files.test.d.ts +1 -0
- package/lib/runtime/public-files.test.js +97 -0
- package/lib/runtime/server.mjs +41588 -0
- package/lib/runtime/static-files.d.ts +50 -0
- package/lib/runtime/static-files.js +266 -0
- package/lib/runtime/static-files.test.d.ts +1 -0
- package/lib/runtime/static-files.test.js +118 -0
- package/lib/runtime/util.d.ts +28 -0
- package/lib/runtime/util.js +79 -0
- package/lib/utils/base-path.d.ts +123 -11
- package/lib/utils/base-path.js +276 -39
- package/lib/utils/base-path.test.js +275 -50
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NodeResponseSink = void 0;
|
|
4
|
+
class NodeResponseSink {
|
|
5
|
+
res;
|
|
6
|
+
constructor(res) {
|
|
7
|
+
this.res = res;
|
|
8
|
+
}
|
|
9
|
+
begin(head) {
|
|
10
|
+
try {
|
|
11
|
+
this.res.writeHead(head.statusCode, head.statusMessage, {
|
|
12
|
+
...head.headers,
|
|
13
|
+
// The one header Node models as an array, which is exactly why
|
|
14
|
+
// `ResponseHead` carries cookies separately.
|
|
15
|
+
...(head.cookies.length > 0 ? { "set-cookie": head.cookies } : {}),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
// `writeHead` rejects a header value Node will not put on the wire — a
|
|
20
|
+
// non-latin1 `Content-Disposition` filename, a CR/LF. `pipeToSink` tears
|
|
21
|
+
// down the render when this rethrows, but nothing ever answered the real
|
|
22
|
+
// response: the connection sat open until the ALB's idle timeout and the
|
|
23
|
+
// client got a 502/504. `sendError`'s 500 cannot help, since the head it
|
|
24
|
+
// would send never gets this far either.
|
|
25
|
+
failHead(this.res);
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
return this.res;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.NodeResponseSink = NodeResponseSink;
|
|
32
|
+
/** Answer a plain 500 in place of a head `writeHead` refused. */
|
|
33
|
+
function failHead(res) {
|
|
34
|
+
if (res.headersSent) {
|
|
35
|
+
res.destroy();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// The refused call may have set some of its headers before it threw.
|
|
39
|
+
for (const name of res.getHeaderNames()) {
|
|
40
|
+
res.removeHeader(name);
|
|
41
|
+
}
|
|
42
|
+
res.writeHead(500, {
|
|
43
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
44
|
+
"Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate",
|
|
45
|
+
});
|
|
46
|
+
res.end("Internal Server Error");
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1zaW5rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bnRpbWUvaHR0cC9ub2RlLXNpbmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBWUEsTUFBYSxnQkFBZ0I7SUFDUztJQUFwQyxZQUFvQyxHQUFtQjtRQUFuQixRQUFHLEdBQUgsR0FBRyxDQUFnQjtJQUFHLENBQUM7SUFFcEQsS0FBSyxDQUFDLElBQWtCO1FBQzdCLElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDdEQsR0FBRyxJQUFJLENBQUMsT0FBTztnQkFDZiwrREFBK0Q7Z0JBQy9ELDZDQUE2QztnQkFDN0MsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDbkUsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZix1RUFBdUU7WUFDdkUseUVBQXlFO1lBQ3pFLHlFQUF5RTtZQUN6RSx5RUFBeUU7WUFDekUseUVBQXlFO1lBQ3pFLHlDQUF5QztZQUN6QyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQixDQUFDO0NBQ0Y7QUF2QkQsNENBdUJDO0FBRUQsaUVBQWlFO0FBQ2pFLFNBQVMsUUFBUSxDQUFDLEdBQW1CO0lBQ25DLElBQUksR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3BCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNkLE9BQU87SUFDVCxDQUFDO0lBQ0QscUVBQXFFO0lBQ3JFLEtBQUssTUFBTSxJQUFJLElBQUksR0FBRyxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7UUFDeEMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBQ0QsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7UUFDakIsY0FBYyxFQUFFLDJCQUEyQjtRQUMzQyxlQUFlLEVBQUUseURBQXlEO0tBQzNFLENBQUMsQ0FBQztJQUNILEdBQUcsQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUNuQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgY29udGFpbmVyIHNoZWxsJ3Mge0BsaW5rIFJlc3BvbnNlU2lua306IHRoZSBoZWFkIGdvZXMgdG8gYSByZWFsXG4gKiBgbm9kZTpodHRwYCBgU2VydmVyUmVzcG9uc2VgLCB3aGljaCBpcyB0aGVuIHRoZSBzdHJlYW0gdGhlIGJvZHkgaXMgcGlwZWQgaW50by5cbiAqXG4gKiBJdHMgb3duIG1vZHVsZSByYXRoZXIgdGhhbiBpbmxpbmUgaW4gYHNlcnZlci5tdHNgIHNvIGl0IGNhbiBiZSB0ZXN0ZWQgd2l0aG91dFxuICogc3RhcnRpbmcgdGhlIHNlcnZlciB0aGF0IG1vZHVsZSBzdGFydHMgb24gaW1wb3J0LlxuICovXG5pbXBvcnQgdHlwZSB7IFNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHR5cGUgeyBXcml0YWJsZSB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuaW1wb3J0IHR5cGUgeyBSZXNwb25zZUhlYWQgfSBmcm9tIFwiLi9yZXNwb25zZVwiO1xuaW1wb3J0IHR5cGUgeyBSZXNwb25zZVNpbmsgfSBmcm9tIFwiLi9zaW5rXCI7XG5cbmV4cG9ydCBjbGFzcyBOb2RlUmVzcG9uc2VTaW5rIGltcGxlbWVudHMgUmVzcG9uc2VTaW5rIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcmVzOiBTZXJ2ZXJSZXNwb25zZSkge31cblxuICBwdWJsaWMgYmVnaW4oaGVhZDogUmVzcG9uc2VIZWFkKTogV3JpdGFibGUge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnJlcy53cml0ZUhlYWQoaGVhZC5zdGF0dXNDb2RlLCBoZWFkLnN0YXR1c01lc3NhZ2UsIHtcbiAgICAgICAgLi4uaGVhZC5oZWFkZXJzLFxuICAgICAgICAvLyBUaGUgb25lIGhlYWRlciBOb2RlIG1vZGVscyBhcyBhbiBhcnJheSwgd2hpY2ggaXMgZXhhY3RseSB3aHlcbiAgICAgICAgLy8gYFJlc3BvbnNlSGVhZGAgY2FycmllcyBjb29raWVzIHNlcGFyYXRlbHkuXG4gICAgICAgIC4uLihoZWFkLmNvb2tpZXMubGVuZ3RoID4gMCA/IHsgXCJzZXQtY29va2llXCI6IGhlYWQuY29va2llcyB9IDoge30pLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIGB3cml0ZUhlYWRgIHJlamVjdHMgYSBoZWFkZXIgdmFsdWUgTm9kZSB3aWxsIG5vdCBwdXQgb24gdGhlIHdpcmUg4oCUIGFcbiAgICAgIC8vIG5vbi1sYXRpbjEgYENvbnRlbnQtRGlzcG9zaXRpb25gIGZpbGVuYW1lLCBhIENSL0xGLiBgcGlwZVRvU2lua2AgdGVhcnNcbiAgICAgIC8vIGRvd24gdGhlIHJlbmRlciB3aGVuIHRoaXMgcmV0aHJvd3MsIGJ1dCBub3RoaW5nIGV2ZXIgYW5zd2VyZWQgdGhlIHJlYWxcbiAgICAgIC8vIHJlc3BvbnNlOiB0aGUgY29ubmVjdGlvbiBzYXQgb3BlbiB1bnRpbCB0aGUgQUxCJ3MgaWRsZSB0aW1lb3V0IGFuZCB0aGVcbiAgICAgIC8vIGNsaWVudCBnb3QgYSA1MDIvNTA0LiBgc2VuZEVycm9yYCdzIDUwMCBjYW5ub3QgaGVscCwgc2luY2UgdGhlIGhlYWQgaXRcbiAgICAgIC8vIHdvdWxkIHNlbmQgbmV2ZXIgZ2V0cyB0aGlzIGZhciBlaXRoZXIuXG4gICAgICBmYWlsSGVhZCh0aGlzLnJlcyk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucmVzO1xuICB9XG59XG5cbi8qKiBBbnN3ZXIgYSBwbGFpbiA1MDAgaW4gcGxhY2Ugb2YgYSBoZWFkIGB3cml0ZUhlYWRgIHJlZnVzZWQuICovXG5mdW5jdGlvbiBmYWlsSGVhZChyZXM6IFNlcnZlclJlc3BvbnNlKTogdm9pZCB7XG4gIGlmIChyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICByZXMuZGVzdHJveSgpO1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBUaGUgcmVmdXNlZCBjYWxsIG1heSBoYXZlIHNldCBzb21lIG9mIGl0cyBoZWFkZXJzIGJlZm9yZSBpdCB0aHJldy5cbiAgZm9yIChjb25zdCBuYW1lIG9mIHJlcy5nZXRIZWFkZXJOYW1lcygpKSB7XG4gICAgcmVzLnJlbW92ZUhlYWRlcihuYW1lKTtcbiAgfVxuICByZXMud3JpdGVIZWFkKDUwMCwge1xuICAgIFwiQ29udGVudC1UeXBlXCI6IFwidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOFwiLFxuICAgIFwiQ2FjaGUtQ29udHJvbFwiOiBcInByaXZhdGUsIG5vLWNhY2hlLCBuby1zdG9yZSwgbWF4LWFnZT0wLCBtdXN0LXJldmFsaWRhdGVcIixcbiAgfSk7XG4gIHJlcy5lbmQoXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIik7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_http_1 = require("node:http");
|
|
4
|
+
const node_sink_1 = require("./node-sink");
|
|
5
|
+
/**
|
|
6
|
+
* A real `node:http` server, because what is under test is how Node's own
|
|
7
|
+
* `writeHead` validation interacts with the sink: a stub `ServerResponse` would
|
|
8
|
+
* not reject the header values that hung the container shell.
|
|
9
|
+
*/
|
|
10
|
+
async function respondWith(head) {
|
|
11
|
+
let thrown;
|
|
12
|
+
const server = (0, node_http_1.createServer)((_req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
new node_sink_1.NodeResponseSink(res).begin(head).end("the body");
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
thrown = error;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
21
|
+
const { port } = server.address();
|
|
22
|
+
try {
|
|
23
|
+
return await new Promise((resolve, reject) => {
|
|
24
|
+
const req = (0, node_http_1.request)({ port, host: "127.0.0.1", path: "/" }, (res) => {
|
|
25
|
+
let body = "";
|
|
26
|
+
res.setEncoding("utf-8");
|
|
27
|
+
res.on("data", (chunk) => (body += chunk));
|
|
28
|
+
res.on("end", () => resolve({ status: res.statusCode, body, thrown }));
|
|
29
|
+
});
|
|
30
|
+
// What the ALB did: wait for an answer that never came.
|
|
31
|
+
req.setTimeout(2_000, () => reject(new Error("the response hung")));
|
|
32
|
+
req.on("error", reject);
|
|
33
|
+
req.end();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
server.close();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
describe("NodeResponseSink", () => {
|
|
41
|
+
it("writes the head, cookies included, and hands back the response", async () => {
|
|
42
|
+
const result = await respondWith({
|
|
43
|
+
statusCode: 201,
|
|
44
|
+
headers: { "content-type": "text/plain" },
|
|
45
|
+
cookies: ["a=1", "b=2"],
|
|
46
|
+
});
|
|
47
|
+
expect(result).toMatchObject({ status: 201, body: "the body" });
|
|
48
|
+
expect(result.thrown).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
it.each([
|
|
51
|
+
["a non-latin1 value", 'attachment; filename="résumé—final.pdf"'],
|
|
52
|
+
["a CR/LF", "one\r\nx-injected: yes"],
|
|
53
|
+
])("answers 500 rather than hanging when writeHead rejects %s", async (_name, value) => {
|
|
54
|
+
const result = await respondWith({
|
|
55
|
+
statusCode: 200,
|
|
56
|
+
headers: { "content-disposition": value },
|
|
57
|
+
cookies: [],
|
|
58
|
+
});
|
|
59
|
+
expect(result.status).toBe(500);
|
|
60
|
+
expect(result.body).toBe("Internal Server Error");
|
|
61
|
+
// Rethrown, so `pipeToSink` tears the render down. (Node's own error
|
|
62
|
+
// class, from outside Jest's realm, hence not `toBeInstanceOf`.)
|
|
63
|
+
expect(result.thrown).toMatchObject({ code: "ERR_INVALID_CHAR" });
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1zaW5rLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVudGltZS9odHRwL25vZGUtc2luay50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEseUNBQWlFO0FBRWpFLDJDQUErQztBQUcvQzs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLFdBQVcsQ0FDeEIsSUFBa0I7SUFFbEIsSUFBSSxNQUFlLENBQUM7SUFDcEIsTUFBTSxNQUFNLEdBQUcsSUFBQSx3QkFBWSxFQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ3hDLElBQUksQ0FBQztZQUNILElBQUksNEJBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDakIsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDN0UsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQWlCLENBQUM7SUFDakQsSUFBSSxDQUFDO1FBQ0gsT0FBTyxNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzNDLE1BQU0sR0FBRyxHQUFHLElBQUEsbUJBQVcsRUFBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUN0RSxJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ2QsR0FBRyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDekIsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQzNDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekUsQ0FBQyxDQUFDLENBQUM7WUFDSCx3REFBd0Q7WUFDeEQsR0FBRyxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BFLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3hCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDakIsQ0FBQztBQUNILENBQUM7QUFFRCxRQUFRLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO0lBQ2hDLEVBQUUsQ0FBQyxnRUFBZ0UsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM5RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQztZQUMvQixVQUFVLEVBQUUsR0FBRztZQUNmLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUU7WUFDekMsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQztTQUN4QixDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNoRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3hDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLElBQUksQ0FBQztRQUNOLENBQUMsb0JBQW9CLEVBQUUseUNBQXlDLENBQUM7UUFDakUsQ0FBQyxTQUFTLEVBQUUsd0JBQXdCLENBQUM7S0FDdEMsQ0FBQyxDQUNBLDJEQUEyRCxFQUMzRCxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQ3JCLE1BQU0sTUFBTSxHQUFHLE1BQU0sV0FBVyxDQUFDO1lBQy9CLFVBQVUsRUFBRSxHQUFHO1lBQ2YsT0FBTyxFQUFFLEVBQUUscUJBQXFCLEVBQUUsS0FBSyxFQUFFO1lBQ3pDLE9BQU8sRUFBRSxFQUFFO1NBQ1osQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUNsRCxxRUFBcUU7UUFDckUsaUVBQWlFO1FBQ2pFLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztJQUNwRSxDQUFDLENBQ0YsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlU2VydmVyLCByZXF1ZXN0IGFzIGh0dHBSZXF1ZXN0IH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHR5cGUgeyBBZGRyZXNzSW5mbyB9IGZyb20gXCJub2RlOm5ldFwiO1xuaW1wb3J0IHsgTm9kZVJlc3BvbnNlU2luayB9IGZyb20gXCIuL25vZGUtc2lua1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VIZWFkIH0gZnJvbSBcIi4vcmVzcG9uc2VcIjtcblxuLyoqXG4gKiBBIHJlYWwgYG5vZGU6aHR0cGAgc2VydmVyLCBiZWNhdXNlIHdoYXQgaXMgdW5kZXIgdGVzdCBpcyBob3cgTm9kZSdzIG93blxuICogYHdyaXRlSGVhZGAgdmFsaWRhdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgc2luazogYSBzdHViIGBTZXJ2ZXJSZXNwb25zZWAgd291bGRcbiAqIG5vdCByZWplY3QgdGhlIGhlYWRlciB2YWx1ZXMgdGhhdCBodW5nIHRoZSBjb250YWluZXIgc2hlbGwuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc3BvbmRXaXRoKFxuICBoZWFkOiBSZXNwb25zZUhlYWQsXG4pOiBQcm9taXNlPHsgc3RhdHVzPzogbnVtYmVyOyBib2R5OiBzdHJpbmc7IHRocm93bjogdW5rbm93biB9PiB7XG4gIGxldCB0aHJvd246IHVua25vd247XG4gIGNvbnN0IHNlcnZlciA9IGNyZWF0ZVNlcnZlcigoX3JlcSwgcmVzKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIG5ldyBOb2RlUmVzcG9uc2VTaW5rKHJlcykuYmVnaW4oaGVhZCkuZW5kKFwidGhlIGJvZHlcIik7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93biA9IGVycm9yO1xuICAgIH1cbiAgfSk7XG4gIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXJ2ZXIubGlzdGVuKDAsIFwiMTI3LjAuMC4xXCIsIHJlc29sdmUpKTtcbiAgY29uc3QgeyBwb3J0IH0gPSBzZXJ2ZXIuYWRkcmVzcygpIGFzIEFkZHJlc3NJbmZvO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXEgPSBodHRwUmVxdWVzdCh7IHBvcnQsIGhvc3Q6IFwiMTI3LjAuMC4xXCIsIHBhdGg6IFwiL1wiIH0sIChyZXMpID0+IHtcbiAgICAgICAgbGV0IGJvZHkgPSBcIlwiO1xuICAgICAgICByZXMuc2V0RW5jb2RpbmcoXCJ1dGYtOFwiKTtcbiAgICAgICAgcmVzLm9uKFwiZGF0YVwiLCAoY2h1bmspID0+IChib2R5ICs9IGNodW5rKSk7XG4gICAgICAgIHJlcy5vbihcImVuZFwiLCAoKSA9PiByZXNvbHZlKHsgc3RhdHVzOiByZXMuc3RhdHVzQ29kZSwgYm9keSwgdGhyb3duIH0pKTtcbiAgICAgIH0pO1xuICAgICAgLy8gV2hhdCB0aGUgQUxCIGRpZDogd2FpdCBmb3IgYW4gYW5zd2VyIHRoYXQgbmV2ZXIgY2FtZS5cbiAgICAgIHJlcS5zZXRUaW1lb3V0KDJfMDAwLCAoKSA9PiByZWplY3QobmV3IEVycm9yKFwidGhlIHJlc3BvbnNlIGh1bmdcIikpKTtcbiAgICAgIHJlcS5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICByZXEuZW5kKCk7XG4gICAgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgc2VydmVyLmNsb3NlKCk7XG4gIH1cbn1cblxuZGVzY3JpYmUoXCJOb2RlUmVzcG9uc2VTaW5rXCIsICgpID0+IHtcbiAgaXQoXCJ3cml0ZXMgdGhlIGhlYWQsIGNvb2tpZXMgaW5jbHVkZWQsIGFuZCBoYW5kcyBiYWNrIHRoZSByZXNwb25zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVzcG9uZFdpdGgoe1xuICAgICAgc3RhdHVzQ29kZTogMjAxLFxuICAgICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvcGxhaW5cIiB9LFxuICAgICAgY29va2llczogW1wiYT0xXCIsIFwiYj0yXCJdLFxuICAgIH0pO1xuICAgIGV4cGVjdChyZXN1bHQpLnRvTWF0Y2hPYmplY3QoeyBzdGF0dXM6IDIwMSwgYm9keTogXCJ0aGUgYm9keVwiIH0pO1xuICAgIGV4cGVjdChyZXN1bHQudGhyb3duKS50b0JlVW5kZWZpbmVkKCk7XG4gIH0pO1xuXG4gIGl0LmVhY2goW1xuICAgIFtcImEgbm9uLWxhdGluMSB2YWx1ZVwiLCAnYXR0YWNobWVudDsgZmlsZW5hbWU9XCJyw6lzdW3DqeKAlGZpbmFsLnBkZlwiJ10sXG4gICAgW1wiYSBDUi9MRlwiLCBcIm9uZVxcclxcbngtaW5qZWN0ZWQ6IHllc1wiXSxcbiAgXSkoXG4gICAgXCJhbnN3ZXJzIDUwMCByYXRoZXIgdGhhbiBoYW5naW5nIHdoZW4gd3JpdGVIZWFkIHJlamVjdHMgJXNcIixcbiAgICBhc3luYyAoX25hbWUsIHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXNwb25kV2l0aCh7XG4gICAgICAgIHN0YXR1c0NvZGU6IDIwMCxcbiAgICAgICAgaGVhZGVyczogeyBcImNvbnRlbnQtZGlzcG9zaXRpb25cIjogdmFsdWUgfSxcbiAgICAgICAgY29va2llczogW10sXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChyZXN1bHQuc3RhdHVzKS50b0JlKDUwMCk7XG4gICAgICBleHBlY3QocmVzdWx0LmJvZHkpLnRvQmUoXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIik7XG4gICAgICAvLyBSZXRocm93biwgc28gYHBpcGVUb1NpbmtgIHRlYXJzIHRoZSByZW5kZXIgZG93bi4gKE5vZGUncyBvd24gZXJyb3JcbiAgICAgIC8vIGNsYXNzLCBmcm9tIG91dHNpZGUgSmVzdCdzIHJlYWxtLCBoZW5jZSBub3QgYHRvQmVJbnN0YW5jZU9mYC4pXG4gICAgICBleHBlY3QocmVzdWx0LnRocm93bikudG9NYXRjaE9iamVjdCh7IGNvZGU6IFwiRVJSX0lOVkFMSURfQ0hBUlwiIH0pO1xuICAgIH0sXG4gICk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A synthesized `http.IncomingMessage`.
|
|
3
|
+
*
|
|
4
|
+
* Both shells use this — the Lambda shell because it has an event rather than a
|
|
5
|
+
* socket, and the container shell so that the code paths Next.js exercises are
|
|
6
|
+
* the ones the Lambda e2e suite covers. Handing Containers a real
|
|
7
|
+
* `IncomingMessage` would mean the container suite proves nothing about Lambda.
|
|
8
|
+
*
|
|
9
|
+
* Derived from `serverless-http`'s `lib/request.js` (MIT, © Doug Moscrop) — the
|
|
10
|
+
* fake-socket shape and the `_read` push are its work:
|
|
11
|
+
* https://github.com/dougmoscrop/serverless-http/blob/master/lib/request.js
|
|
12
|
+
*
|
|
13
|
+
* What Next.js actually reads off `req` (`next/dist/server/base-http/node.js`,
|
|
14
|
+
* `NodeNextRequest`): `method`, `url` (which it *reassigns* during
|
|
15
|
+
* normalization), `headers`, `cookies` (which it *assigns*), the
|
|
16
|
+
* `NEXT_REQUEST_META` symbol, `fetchMetrics`, and `on("data"|"end"|"error")`.
|
|
17
|
+
* Nothing else, so nothing else needs to be faithful.
|
|
18
|
+
*/
|
|
19
|
+
import { IncomingMessage } from "node:http";
|
|
20
|
+
import type { IncomingHttpHeaders } from "node:http";
|
|
21
|
+
import { Readable } from "node:stream";
|
|
22
|
+
export interface IncomingMessageInit {
|
|
23
|
+
readonly method: string;
|
|
24
|
+
/**
|
|
25
|
+
* Origin-form target: path + query, never absolute. This is what Next.js
|
|
26
|
+
* parses and rewrites, so it must be exactly what the route resolved to.
|
|
27
|
+
*/
|
|
28
|
+
readonly url: string;
|
|
29
|
+
readonly headers: IncomingHttpHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* `undefined` for bodyless requests. A `Readable` is piped through with
|
|
32
|
+
* backpressure; a `Buffer` is pushed in one go.
|
|
33
|
+
*/
|
|
34
|
+
readonly body?: Readable | Buffer;
|
|
35
|
+
/** Fills `req.socket.remoteAddress`, which `x-forwarded-for` handling reads. */
|
|
36
|
+
readonly remoteAddress?: string;
|
|
37
|
+
/** `false` for the container shell behind an ALB terminating TLS. */
|
|
38
|
+
readonly encrypted?: boolean;
|
|
39
|
+
/** `RuntimeRequest.trustForwardedHost`, kept for the requests made on its behalf. */
|
|
40
|
+
readonly trustForwardedHost?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class ShimIncomingMessage extends IncomingMessage {
|
|
43
|
+
/** Set by Next.js's `NodeNextRequest.originalRequest` getter. */
|
|
44
|
+
cookies?: unknown;
|
|
45
|
+
fetchMetrics?: unknown;
|
|
46
|
+
/** See {@link IncomingMessageInit.trustForwardedHost}. */
|
|
47
|
+
readonly trustForwardedHost: boolean;
|
|
48
|
+
private source?;
|
|
49
|
+
private pumping;
|
|
50
|
+
constructor(init: IncomingMessageInit);
|
|
51
|
+
_read(size?: number): void;
|
|
52
|
+
/**
|
|
53
|
+
* `IncomingMessage.prototype._destroy` reaches for the socket — it calls
|
|
54
|
+
* `stream.finished()` on it to wait for the connection to close — and throws
|
|
55
|
+
* `ERR_INVALID_ARG_TYPE` on the synthesized one. There is no connection to tear
|
|
56
|
+
* down here, so the destroy is just completed, after the `"aborted"` that
|
|
57
|
+
* signals a truncated request.
|
|
58
|
+
*/
|
|
59
|
+
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
|
|
60
|
+
}
|
|
61
|
+
/** Lowercases and flattens a `Headers` into `IncomingHttpHeaders`. */
|
|
62
|
+
export declare function toIncomingHttpHeaders(headers: Headers): IncomingHttpHeaders;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShimIncomingMessage = void 0;
|
|
4
|
+
exports.toIncomingHttpHeaders = toIncomingHttpHeaders;
|
|
5
|
+
/**
|
|
6
|
+
* A synthesized `http.IncomingMessage`.
|
|
7
|
+
*
|
|
8
|
+
* Both shells use this — the Lambda shell because it has an event rather than a
|
|
9
|
+
* socket, and the container shell so that the code paths Next.js exercises are
|
|
10
|
+
* the ones the Lambda e2e suite covers. Handing Containers a real
|
|
11
|
+
* `IncomingMessage` would mean the container suite proves nothing about Lambda.
|
|
12
|
+
*
|
|
13
|
+
* Derived from `serverless-http`'s `lib/request.js` (MIT, © Doug Moscrop) — the
|
|
14
|
+
* fake-socket shape and the `_read` push are its work:
|
|
15
|
+
* https://github.com/dougmoscrop/serverless-http/blob/master/lib/request.js
|
|
16
|
+
*
|
|
17
|
+
* What Next.js actually reads off `req` (`next/dist/server/base-http/node.js`,
|
|
18
|
+
* `NodeNextRequest`): `method`, `url` (which it *reassigns* during
|
|
19
|
+
* normalization), `headers`, `cookies` (which it *assigns*), the
|
|
20
|
+
* `NEXT_REQUEST_META` symbol, `fetchMetrics`, and `on("data"|"end"|"error")`.
|
|
21
|
+
* Nothing else, so nothing else needs to be faithful.
|
|
22
|
+
*/
|
|
23
|
+
const node_http_1 = require("node:http");
|
|
24
|
+
/**
|
|
25
|
+
* The subset of `net.Socket` that `IncomingMessage`'s constructor and Next.js
|
|
26
|
+
* touch. A real socket cannot be synthesized, and nothing needs one.
|
|
27
|
+
*/
|
|
28
|
+
function fakeSocket(init) {
|
|
29
|
+
return {
|
|
30
|
+
encrypted: init.encrypted ?? true,
|
|
31
|
+
readable: false,
|
|
32
|
+
remoteAddress: init.remoteAddress,
|
|
33
|
+
address: () => ({ port: init.encrypted === false ? 80 : 443 }),
|
|
34
|
+
end: () => { },
|
|
35
|
+
destroy: () => { },
|
|
36
|
+
// `send` (used by `serveStatic`) checks this before streaming a file.
|
|
37
|
+
writable: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
class ShimIncomingMessage extends node_http_1.IncomingMessage {
|
|
41
|
+
/** Set by Next.js's `NodeNextRequest.originalRequest` getter. */
|
|
42
|
+
cookies;
|
|
43
|
+
fetchMetrics;
|
|
44
|
+
/** See {@link IncomingMessageInit.trustForwardedHost}. */
|
|
45
|
+
trustForwardedHost;
|
|
46
|
+
source;
|
|
47
|
+
pumping = false;
|
|
48
|
+
constructor(init) {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
super(fakeSocket(init));
|
|
51
|
+
const headers = { ...init.headers };
|
|
52
|
+
const body = init.body;
|
|
53
|
+
if (Buffer.isBuffer(body) &&
|
|
54
|
+
headers["content-length"] === undefined &&
|
|
55
|
+
headers["transfer-encoding"] === undefined) {
|
|
56
|
+
// RFC 9110: a body without a length is unframed. Next.js's body parsing
|
|
57
|
+
// for Pages API routes reads `content-length`, and API Gateway / Function
|
|
58
|
+
// URL events do not always carry one.
|
|
59
|
+
headers["content-length"] = String(Buffer.byteLength(body));
|
|
60
|
+
}
|
|
61
|
+
this.trustForwardedHost = init.trustForwardedHost ?? false;
|
|
62
|
+
this.method = init.method.toUpperCase();
|
|
63
|
+
this.url = init.url;
|
|
64
|
+
this.headers = headers;
|
|
65
|
+
this.httpVersion = "1.1";
|
|
66
|
+
this.httpVersionMajor = 1;
|
|
67
|
+
this.httpVersionMinor = 1;
|
|
68
|
+
if (body === undefined) {
|
|
69
|
+
this.complete = true;
|
|
70
|
+
this.push(null);
|
|
71
|
+
}
|
|
72
|
+
else if (Buffer.isBuffer(body)) {
|
|
73
|
+
this.complete = true;
|
|
74
|
+
this.push(body);
|
|
75
|
+
this.push(null);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.source = body;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
_read(size) {
|
|
82
|
+
const source = this.source;
|
|
83
|
+
if (!source) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (this.pumping) {
|
|
87
|
+
source.resume();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.pumping = true;
|
|
91
|
+
source.on("data", (chunk) => {
|
|
92
|
+
if (!this.push(chunk)) {
|
|
93
|
+
source.pause();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
source.on("end", () => {
|
|
97
|
+
this.complete = true;
|
|
98
|
+
this.push(null);
|
|
99
|
+
});
|
|
100
|
+
source.on("error", (error) => {
|
|
101
|
+
this.destroy(error);
|
|
102
|
+
});
|
|
103
|
+
void size;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* `IncomingMessage.prototype._destroy` reaches for the socket — it calls
|
|
107
|
+
* `stream.finished()` on it to wait for the connection to close — and throws
|
|
108
|
+
* `ERR_INVALID_ARG_TYPE` on the synthesized one. There is no connection to tear
|
|
109
|
+
* down here, so the destroy is just completed, after the `"aborted"` that
|
|
110
|
+
* signals a truncated request.
|
|
111
|
+
*/
|
|
112
|
+
_destroy(error, callback) {
|
|
113
|
+
if (!this.readableEnded || !this.complete) {
|
|
114
|
+
this.aborted = true;
|
|
115
|
+
this.emit("aborted");
|
|
116
|
+
}
|
|
117
|
+
callback(error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.ShimIncomingMessage = ShimIncomingMessage;
|
|
121
|
+
/** Lowercases and flattens a `Headers` into `IncomingHttpHeaders`. */
|
|
122
|
+
function toIncomingHttpHeaders(headers) {
|
|
123
|
+
const result = {};
|
|
124
|
+
headers.forEach((value, name) => {
|
|
125
|
+
if (name === "set-cookie") {
|
|
126
|
+
// The only request header Node models as an array.
|
|
127
|
+
result["set-cookie"] = headers.getSetCookie();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
result[name] = value;
|
|
131
|
+
});
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydW50aW1lL2h0dHAvcmVxdWVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUF3SkEsc0RBV0M7QUFuS0Q7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gseUNBQTRDO0FBeUI1Qzs7O0dBR0c7QUFDSCxTQUFTLFVBQVUsQ0FBQyxJQUF5QjtJQUMzQyxPQUFPO1FBQ0wsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSTtRQUNqQyxRQUFRLEVBQUUsS0FBSztRQUNmLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtRQUNqQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM5RCxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUUsQ0FBQztRQUNiLE9BQU8sRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO1FBQ2pCLHNFQUFzRTtRQUN0RSxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBYSxtQkFBb0IsU0FBUSwyQkFBZTtJQUN0RCxpRUFBaUU7SUFDMUQsT0FBTyxDQUFXO0lBQ2xCLFlBQVksQ0FBVztJQUM5QiwwREFBMEQ7SUFDMUMsa0JBQWtCLENBQVU7SUFFcEMsTUFBTSxDQUFZO0lBQ2xCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFeEIsWUFBbUIsSUFBeUI7UUFDMUMsOERBQThEO1FBQzlELEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFRLENBQUMsQ0FBQztRQUUvQixNQUFNLE9BQU8sR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDdkIsSUFDRSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztZQUNyQixPQUFPLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxTQUFTO1lBQ3ZDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLFNBQVMsRUFDMUMsQ0FBQztZQUNELHdFQUF3RTtZQUN4RSwwRUFBMEU7WUFDMUUsc0NBQXNDO1lBQ3RDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDOUQsQ0FBQztRQUVELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLElBQUksS0FBSyxDQUFDO1FBQzNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDcEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFDekIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO1FBRTFCLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEIsQ0FBQzthQUFNLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBRWUsS0FBSyxDQUFDLElBQWE7UUFDakMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMzQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBYSxFQUFFLEVBQUU7WUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDdEIsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2pCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxJQUFJLENBQUM7SUFDWixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ2EsUUFBUSxDQUN0QixLQUFtQixFQUNuQixRQUF3QztRQUV4QyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7UUFDRCxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbEIsQ0FBQztDQUNGO0FBekZELGtEQXlGQztBQUVELHNFQUFzRTtBQUN0RSxTQUFnQixxQkFBcUIsQ0FBQyxPQUFnQjtJQUNwRCxNQUFNLE1BQU0sR0FBd0IsRUFBRSxDQUFDO0lBQ3ZDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDOUIsSUFBSSxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDMUIsbURBQW1EO1lBQ25ELE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDOUMsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSBzeW50aGVzaXplZCBgaHR0cC5JbmNvbWluZ01lc3NhZ2VgLlxuICpcbiAqIEJvdGggc2hlbGxzIHVzZSB0aGlzIOKAlCB0aGUgTGFtYmRhIHNoZWxsIGJlY2F1c2UgaXQgaGFzIGFuIGV2ZW50IHJhdGhlciB0aGFuIGFcbiAqIHNvY2tldCwgYW5kIHRoZSBjb250YWluZXIgc2hlbGwgc28gdGhhdCB0aGUgY29kZSBwYXRocyBOZXh0LmpzIGV4ZXJjaXNlcyBhcmVcbiAqIHRoZSBvbmVzIHRoZSBMYW1iZGEgZTJlIHN1aXRlIGNvdmVycy4gSGFuZGluZyBDb250YWluZXJzIGEgcmVhbFxuICogYEluY29taW5nTWVzc2FnZWAgd291bGQgbWVhbiB0aGUgY29udGFpbmVyIHN1aXRlIHByb3ZlcyBub3RoaW5nIGFib3V0IExhbWJkYS5cbiAqXG4gKiBEZXJpdmVkIGZyb20gYHNlcnZlcmxlc3MtaHR0cGAncyBgbGliL3JlcXVlc3QuanNgIChNSVQsIMKpIERvdWcgTW9zY3JvcCkg4oCUIHRoZVxuICogZmFrZS1zb2NrZXQgc2hhcGUgYW5kIHRoZSBgX3JlYWRgIHB1c2ggYXJlIGl0cyB3b3JrOlxuICogaHR0cHM6Ly9naXRodWIuY29tL2RvdWdtb3Njcm9wL3NlcnZlcmxlc3MtaHR0cC9ibG9iL21hc3Rlci9saWIvcmVxdWVzdC5qc1xuICpcbiAqIFdoYXQgTmV4dC5qcyBhY3R1YWxseSByZWFkcyBvZmYgYHJlcWAgKGBuZXh0L2Rpc3Qvc2VydmVyL2Jhc2UtaHR0cC9ub2RlLmpzYCxcbiAqIGBOb2RlTmV4dFJlcXVlc3RgKTogYG1ldGhvZGAsIGB1cmxgICh3aGljaCBpdCAqcmVhc3NpZ25zKiBkdXJpbmdcbiAqIG5vcm1hbGl6YXRpb24pLCBgaGVhZGVyc2AsIGBjb29raWVzYCAod2hpY2ggaXQgKmFzc2lnbnMqKSwgdGhlXG4gKiBgTkVYVF9SRVFVRVNUX01FVEFgIHN5bWJvbCwgYGZldGNoTWV0cmljc2AsIGFuZCBgb24oXCJkYXRhXCJ8XCJlbmRcInxcImVycm9yXCIpYC5cbiAqIE5vdGhpbmcgZWxzZSwgc28gbm90aGluZyBlbHNlIG5lZWRzIHRvIGJlIGZhaXRoZnVsLlxuICovXG5pbXBvcnQgeyBJbmNvbWluZ01lc3NhZ2UgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgdHlwZSB7IEluY29taW5nSHR0cEhlYWRlcnMgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluY29taW5nTWVzc2FnZUluaXQge1xuICByZWFkb25seSBtZXRob2Q6IHN0cmluZztcbiAgLyoqXG4gICAqIE9yaWdpbi1mb3JtIHRhcmdldDogcGF0aCArIHF1ZXJ5LCBuZXZlciBhYnNvbHV0ZS4gVGhpcyBpcyB3aGF0IE5leHQuanNcbiAgICogcGFyc2VzIGFuZCByZXdyaXRlcywgc28gaXQgbXVzdCBiZSBleGFjdGx5IHdoYXQgdGhlIHJvdXRlIHJlc29sdmVkIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgdXJsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGhlYWRlcnM6IEluY29taW5nSHR0cEhlYWRlcnM7XG4gIC8qKlxuICAgKiBgdW5kZWZpbmVkYCBmb3IgYm9keWxlc3MgcmVxdWVzdHMuIEEgYFJlYWRhYmxlYCBpcyBwaXBlZCB0aHJvdWdoIHdpdGhcbiAgICogYmFja3ByZXNzdXJlOyBhIGBCdWZmZXJgIGlzIHB1c2hlZCBpbiBvbmUgZ28uXG4gICAqL1xuICByZWFkb25seSBib2R5PzogUmVhZGFibGUgfCBCdWZmZXI7XG4gIC8qKiBGaWxscyBgcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzYCwgd2hpY2ggYHgtZm9yd2FyZGVkLWZvcmAgaGFuZGxpbmcgcmVhZHMuICovXG4gIHJlYWRvbmx5IHJlbW90ZUFkZHJlc3M/OiBzdHJpbmc7XG4gIC8qKiBgZmFsc2VgIGZvciB0aGUgY29udGFpbmVyIHNoZWxsIGJlaGluZCBhbiBBTEIgdGVybWluYXRpbmcgVExTLiAqL1xuICByZWFkb25seSBlbmNyeXB0ZWQ/OiBib29sZWFuO1xuICAvKiogYFJ1bnRpbWVSZXF1ZXN0LnRydXN0Rm9yd2FyZGVkSG9zdGAsIGtlcHQgZm9yIHRoZSByZXF1ZXN0cyBtYWRlIG9uIGl0cyBiZWhhbGYuICovXG4gIHJlYWRvbmx5IHRydXN0Rm9yd2FyZGVkSG9zdD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBgbmV0LlNvY2tldGAgdGhhdCBgSW5jb21pbmdNZXNzYWdlYCdzIGNvbnN0cnVjdG9yIGFuZCBOZXh0LmpzXG4gKiB0b3VjaC4gQSByZWFsIHNvY2tldCBjYW5ub3QgYmUgc3ludGhlc2l6ZWQsIGFuZCBub3RoaW5nIG5lZWRzIG9uZS5cbiAqL1xuZnVuY3Rpb24gZmFrZVNvY2tldChpbml0OiBJbmNvbWluZ01lc3NhZ2VJbml0KSB7XG4gIHJldHVybiB7XG4gICAgZW5jcnlwdGVkOiBpbml0LmVuY3J5cHRlZCA/PyB0cnVlLFxuICAgIHJlYWRhYmxlOiBmYWxzZSxcbiAgICByZW1vdGVBZGRyZXNzOiBpbml0LnJlbW90ZUFkZHJlc3MsXG4gICAgYWRkcmVzczogKCkgPT4gKHsgcG9ydDogaW5pdC5lbmNyeXB0ZWQgPT09IGZhbHNlID8gODAgOiA0NDMgfSksXG4gICAgZW5kOiAoKSA9PiB7fSxcbiAgICBkZXN0cm95OiAoKSA9PiB7fSxcbiAgICAvLyBgc2VuZGAgKHVzZWQgYnkgYHNlcnZlU3RhdGljYCkgY2hlY2tzIHRoaXMgYmVmb3JlIHN0cmVhbWluZyBhIGZpbGUuXG4gICAgd3JpdGFibGU6IHRydWUsXG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBTaGltSW5jb21pbmdNZXNzYWdlIGV4dGVuZHMgSW5jb21pbmdNZXNzYWdlIHtcbiAgLyoqIFNldCBieSBOZXh0LmpzJ3MgYE5vZGVOZXh0UmVxdWVzdC5vcmlnaW5hbFJlcXVlc3RgIGdldHRlci4gKi9cbiAgcHVibGljIGNvb2tpZXM/OiB1bmtub3duO1xuICBwdWJsaWMgZmV0Y2hNZXRyaWNzPzogdW5rbm93bjtcbiAgLyoqIFNlZSB7QGxpbmsgSW5jb21pbmdNZXNzYWdlSW5pdC50cnVzdEZvcndhcmRlZEhvc3R9LiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdHJ1c3RGb3J3YXJkZWRIb3N0OiBib29sZWFuO1xuXG4gIHByaXZhdGUgc291cmNlPzogUmVhZGFibGU7XG4gIHByaXZhdGUgcHVtcGluZyA9IGZhbHNlO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihpbml0OiBJbmNvbWluZ01lc3NhZ2VJbml0KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBzdXBlcihmYWtlU29ja2V0KGluaXQpIGFzIGFueSk7XG5cbiAgICBjb25zdCBoZWFkZXJzID0geyAuLi5pbml0LmhlYWRlcnMgfTtcbiAgICBjb25zdCBib2R5ID0gaW5pdC5ib2R5O1xuICAgIGlmIChcbiAgICAgIEJ1ZmZlci5pc0J1ZmZlcihib2R5KSAmJlxuICAgICAgaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdID09PSB1bmRlZmluZWQgJiZcbiAgICAgIGhlYWRlcnNbXCJ0cmFuc2Zlci1lbmNvZGluZ1wiXSA9PT0gdW5kZWZpbmVkXG4gICAgKSB7XG4gICAgICAvLyBSRkMgOTExMDogYSBib2R5IHdpdGhvdXQgYSBsZW5ndGggaXMgdW5mcmFtZWQuIE5leHQuanMncyBib2R5IHBhcnNpbmdcbiAgICAgIC8vIGZvciBQYWdlcyBBUEkgcm91dGVzIHJlYWRzIGBjb250ZW50LWxlbmd0aGAsIGFuZCBBUEkgR2F0ZXdheSAvIEZ1bmN0aW9uXG4gICAgICAvLyBVUkwgZXZlbnRzIGRvIG5vdCBhbHdheXMgY2Fycnkgb25lLlxuICAgICAgaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdID0gU3RyaW5nKEJ1ZmZlci5ieXRlTGVuZ3RoKGJvZHkpKTtcbiAgICB9XG5cbiAgICB0aGlzLnRydXN0Rm9yd2FyZGVkSG9zdCA9IGluaXQudHJ1c3RGb3J3YXJkZWRIb3N0ID8/IGZhbHNlO1xuICAgIHRoaXMubWV0aG9kID0gaW5pdC5tZXRob2QudG9VcHBlckNhc2UoKTtcbiAgICB0aGlzLnVybCA9IGluaXQudXJsO1xuICAgIHRoaXMuaGVhZGVycyA9IGhlYWRlcnM7XG4gICAgdGhpcy5odHRwVmVyc2lvbiA9IFwiMS4xXCI7XG4gICAgdGhpcy5odHRwVmVyc2lvbk1ham9yID0gMTtcbiAgICB0aGlzLmh0dHBWZXJzaW9uTWlub3IgPSAxO1xuXG4gICAgaWYgKGJvZHkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5jb21wbGV0ZSA9IHRydWU7XG4gICAgICB0aGlzLnB1c2gobnVsbCk7XG4gICAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoYm9keSkpIHtcbiAgICAgIHRoaXMuY29tcGxldGUgPSB0cnVlO1xuICAgICAgdGhpcy5wdXNoKGJvZHkpO1xuICAgICAgdGhpcy5wdXNoKG51bGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNvdXJjZSA9IGJvZHk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF9yZWFkKHNpemU/OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBzb3VyY2UgPSB0aGlzLnNvdXJjZTtcbiAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5wdW1waW5nKSB7XG4gICAgICBzb3VyY2UucmVzdW1lKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMucHVtcGluZyA9IHRydWU7XG4gICAgc291cmNlLm9uKFwiZGF0YVwiLCAoY2h1bms6IEJ1ZmZlcikgPT4ge1xuICAgICAgaWYgKCF0aGlzLnB1c2goY2h1bmspKSB7XG4gICAgICAgIHNvdXJjZS5wYXVzZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHNvdXJjZS5vbihcImVuZFwiLCAoKSA9PiB7XG4gICAgICB0aGlzLmNvbXBsZXRlID0gdHJ1ZTtcbiAgICAgIHRoaXMucHVzaChudWxsKTtcbiAgICB9KTtcbiAgICBzb3VyY2Uub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcbiAgICAgIHRoaXMuZGVzdHJveShlcnJvcik7XG4gICAgfSk7XG4gICAgdm9pZCBzaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIGBJbmNvbWluZ01lc3NhZ2UucHJvdG90eXBlLl9kZXN0cm95YCByZWFjaGVzIGZvciB0aGUgc29ja2V0IOKAlCBpdCBjYWxsc1xuICAgKiBgc3RyZWFtLmZpbmlzaGVkKClgIG9uIGl0IHRvIHdhaXQgZm9yIHRoZSBjb25uZWN0aW9uIHRvIGNsb3NlIOKAlCBhbmQgdGhyb3dzXG4gICAqIGBFUlJfSU5WQUxJRF9BUkdfVFlQRWAgb24gdGhlIHN5bnRoZXNpemVkIG9uZS4gVGhlcmUgaXMgbm8gY29ubmVjdGlvbiB0byB0ZWFyXG4gICAqIGRvd24gaGVyZSwgc28gdGhlIGRlc3Ryb3kgaXMganVzdCBjb21wbGV0ZWQsIGFmdGVyIHRoZSBgXCJhYm9ydGVkXCJgIHRoYXRcbiAgICogc2lnbmFscyBhIHRydW5jYXRlZCByZXF1ZXN0LlxuICAgKi9cbiAgcHVibGljIG92ZXJyaWRlIF9kZXN0cm95KFxuICAgIGVycm9yOiBFcnJvciB8IG51bGwsXG4gICAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCkgPT4gdm9pZCxcbiAgKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnJlYWRhYmxlRW5kZWQgfHwgIXRoaXMuY29tcGxldGUpIHtcbiAgICAgIHRoaXMuYWJvcnRlZCA9IHRydWU7XG4gICAgICB0aGlzLmVtaXQoXCJhYm9ydGVkXCIpO1xuICAgIH1cbiAgICBjYWxsYmFjayhlcnJvcik7XG4gIH1cbn1cblxuLyoqIExvd2VyY2FzZXMgYW5kIGZsYXR0ZW5zIGEgYEhlYWRlcnNgIGludG8gYEluY29taW5nSHR0cEhlYWRlcnNgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvSW5jb21pbmdIdHRwSGVhZGVycyhoZWFkZXJzOiBIZWFkZXJzKTogSW5jb21pbmdIdHRwSGVhZGVycyB7XG4gIGNvbnN0IHJlc3VsdDogSW5jb21pbmdIdHRwSGVhZGVycyA9IHt9O1xuICBoZWFkZXJzLmZvckVhY2goKHZhbHVlLCBuYW1lKSA9PiB7XG4gICAgaWYgKG5hbWUgPT09IFwic2V0LWNvb2tpZVwiKSB7XG4gICAgICAvLyBUaGUgb25seSByZXF1ZXN0IGhlYWRlciBOb2RlIG1vZGVscyBhcyBhbiBhcnJheS5cbiAgICAgIHJlc3VsdFtcInNldC1jb29raWVcIl0gPSBoZWFkZXJzLmdldFNldENvb2tpZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICByZXN1bHRbbmFtZV0gPSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_stream_1 = require("node:stream");
|
|
4
|
+
const request_1 = require("./request");
|
|
5
|
+
async function readAll(stream) {
|
|
6
|
+
const chunks = [];
|
|
7
|
+
for await (const chunk of stream) {
|
|
8
|
+
chunks.push(chunk);
|
|
9
|
+
}
|
|
10
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
11
|
+
}
|
|
12
|
+
describe("ShimIncomingMessage", () => {
|
|
13
|
+
it("exposes the request line and headers Next.js reads", () => {
|
|
14
|
+
const req = new request_1.ShimIncomingMessage({
|
|
15
|
+
method: "get",
|
|
16
|
+
url: "/a?b=c",
|
|
17
|
+
headers: { host: "example.test" },
|
|
18
|
+
});
|
|
19
|
+
// Uppercased: Next.js compares `req.method === "POST"` in several places.
|
|
20
|
+
expect(req.method).toBe("GET");
|
|
21
|
+
expect(req.url).toBe("/a?b=c");
|
|
22
|
+
expect(req.headers.host).toBe("example.test");
|
|
23
|
+
expect(req.httpVersion).toBe("1.1");
|
|
24
|
+
});
|
|
25
|
+
it("ends the stream immediately when there is no body", async () => {
|
|
26
|
+
const req = new request_1.ShimIncomingMessage({
|
|
27
|
+
method: "GET",
|
|
28
|
+
url: "/",
|
|
29
|
+
headers: {},
|
|
30
|
+
});
|
|
31
|
+
expect(req.complete).toBe(true);
|
|
32
|
+
await expect(readAll(req)).resolves.toBe("");
|
|
33
|
+
});
|
|
34
|
+
it("frames a Buffer body with a content-length", async () => {
|
|
35
|
+
const req = new request_1.ShimIncomingMessage({
|
|
36
|
+
method: "POST",
|
|
37
|
+
url: "/api",
|
|
38
|
+
headers: { "content-type": "application/json" },
|
|
39
|
+
body: Buffer.from('{"a":1}'),
|
|
40
|
+
});
|
|
41
|
+
// Pages API body parsing reads `content-length`, and neither Function URL
|
|
42
|
+
// nor API Gateway events reliably carry one.
|
|
43
|
+
expect(req.headers["content-length"]).toBe("7");
|
|
44
|
+
await expect(readAll(req)).resolves.toBe('{"a":1}');
|
|
45
|
+
});
|
|
46
|
+
it("leaves an existing content-length alone", () => {
|
|
47
|
+
const req = new request_1.ShimIncomingMessage({
|
|
48
|
+
method: "POST",
|
|
49
|
+
url: "/api",
|
|
50
|
+
headers: { "content-length": "99" },
|
|
51
|
+
body: Buffer.from("ab"),
|
|
52
|
+
});
|
|
53
|
+
expect(req.headers["content-length"]).toBe("99");
|
|
54
|
+
});
|
|
55
|
+
it("pipes a streamed body through", async () => {
|
|
56
|
+
const req = new request_1.ShimIncomingMessage({
|
|
57
|
+
method: "PUT",
|
|
58
|
+
url: "/upload",
|
|
59
|
+
headers: { "transfer-encoding": "chunked" },
|
|
60
|
+
body: node_stream_1.Readable.from([Buffer.from("one "), Buffer.from("two")]),
|
|
61
|
+
});
|
|
62
|
+
await expect(readAll(req)).resolves.toBe("one two");
|
|
63
|
+
expect(req.complete).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it("destroys itself when the source stream errors", async () => {
|
|
66
|
+
const source = new node_stream_1.Readable({
|
|
67
|
+
read() {
|
|
68
|
+
this.destroy(new Error("upstream gone"));
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
const req = new request_1.ShimIncomingMessage({
|
|
72
|
+
method: "POST",
|
|
73
|
+
url: "/",
|
|
74
|
+
headers: {},
|
|
75
|
+
body: source,
|
|
76
|
+
});
|
|
77
|
+
await expect(readAll(req)).rejects.toThrow("upstream gone");
|
|
78
|
+
});
|
|
79
|
+
it("fills the socket fields that `send` and x-forwarded-for handling read", () => {
|
|
80
|
+
const req = new request_1.ShimIncomingMessage({
|
|
81
|
+
method: "GET",
|
|
82
|
+
url: "/",
|
|
83
|
+
headers: {},
|
|
84
|
+
remoteAddress: "203.0.113.7",
|
|
85
|
+
encrypted: false,
|
|
86
|
+
});
|
|
87
|
+
expect(req.socket.remoteAddress).toBe("203.0.113.7");
|
|
88
|
+
// `serveStatic` checks `res.socket.writable` before streaming a file.
|
|
89
|
+
expect(req.socket.writable).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("toIncomingHttpHeaders", () => {
|
|
93
|
+
it("flattens a Headers, keeping set-cookie as an array", () => {
|
|
94
|
+
const headers = new Headers({ "x-a": "1" });
|
|
95
|
+
headers.append("set-cookie", "a=1");
|
|
96
|
+
headers.append("set-cookie", "b=2");
|
|
97
|
+
expect((0, request_1.toIncomingHttpHeaders)(headers)).toEqual({
|
|
98
|
+
"x-a": "1",
|
|
99
|
+
"set-cookie": ["a=1", "b=2"],
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bnRpbWUvaHR0cC9yZXF1ZXN0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2Q0FBdUM7QUFDdkMsdUNBQXVFO0FBRXZFLEtBQUssVUFBVSxPQUFPLENBQUMsTUFBZ0I7SUFDckMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQzVCLElBQUksS0FBSyxFQUFFLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBZSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDakQsQ0FBQztBQUVELFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDbkMsRUFBRSxDQUFDLG9EQUFvRCxFQUFFLEdBQUcsRUFBRTtRQUM1RCxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFtQixDQUFDO1lBQ2xDLE1BQU0sRUFBRSxLQUFLO1lBQ2IsR0FBRyxFQUFFLFFBQVE7WUFDYixPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFO1NBQ2xDLENBQUMsQ0FBQztRQUNILDBFQUEwRTtRQUMxRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQixNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENB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QU8sQ0FBQztZQUM3QyxLQUFLLEVBQUUsR0FBRztZQUNWLFlBQVksRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUM7U0FDN0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlYWRhYmxlIH0gZnJvbSBcIm5vZGU6c3RyZWFtXCI7XG5pbXBvcnQgeyBTaGltSW5jb21pbmdNZXNzYWdlLCB0b0luY29taW5nSHR0cEhlYWRlcnMgfSBmcm9tIFwiLi9yZXF1ZXN0XCI7XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRBbGwoc3RyZWFtOiBSZWFkYWJsZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGNodW5rczogQnVmZmVyW10gPSBbXTtcbiAgZm9yIGF3YWl0IChjb25zdCBjaHVuayBvZiBzdHJlYW0pIHtcbiAgICBjaHVua3MucHVzaChjaHVuayBhcyBCdWZmZXIpO1xuICB9XG4gIHJldHVybiBCdWZmZXIuY29uY2F0KGNodW5rcykudG9TdHJpbmcoXCJ1dGYtOFwiKTtcbn1cblxuZGVzY3JpYmUoXCJTaGltSW5jb21pbmdNZXNzYWdlXCIsICgpID0+IHtcbiAgaXQoXCJleHBvc2VzIHRoZSByZXF1ZXN0IGxpbmUgYW5kIGhlYWRlcnMgTmV4dC5qcyByZWFkc1wiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gbmV3IFNoaW1JbmNvbWluZ01lc3NhZ2Uoe1xuICAgICAgbWV0aG9kOiBcImdldFwiLFxuICAgICAgdXJsOiBcIi9hP2I9Y1wiLFxuICAgICAgaGVhZGVyczogeyBob3N0OiBcImV4YW1wbGUudGVzdFwiIH0sXG4gICAgfSk7XG4gICAgLy8gVXBwZXJjYXNlZDogTmV4dC5qcyBjb21wYXJlcyBgcmVxLm1ldGhvZCA9PT0gXCJQT1NUXCJgIGluIHNldmVyYWwgcGxhY2VzLlxuICAgIGV4cGVjdChyZXEubWV0aG9kKS50b0JlKFwiR0VUXCIpO1xuICAgIGV4cGVjdChyZXEudXJsKS50b0JlKFwiL2E/Yj1jXCIpO1xuICAgIGV4cGVjdChyZXEuaGVhZGVycy5ob3N0KS50b0JlKFwiZXhhbXBsZS50ZXN0XCIpO1xuICAgIGV4cGVjdChyZXEuaHR0cFZlcnNpb24pLnRvQmUoXCIxLjFcIik7XG4gIH0pO1xuXG4gIGl0KFwiZW5kcyB0aGUgc3RyZWFtIGltbWVkaWF0ZWx5IHdoZW4gdGhlcmUgaXMgbm8gYm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gbmV3IFNoaW1JbmNvbWluZ01lc3NhZ2Uoe1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgdXJsOiBcIi9cIixcbiAgICAgIGhlYWRlcnM6IHt9LFxuICAgIH0pO1xuICAgIGV4cGVjdChyZXEuY29tcGxldGUpLnRvQmUodHJ1ZSk7XG4gICAgYXdhaXQgZXhwZWN0KHJlYWRBbGwocmVxKSkucmVzb2x2ZXMudG9CZShcIlwiKTtcbiAgfSk7XG5cbiAgaXQoXCJmcmFtZXMgYSBCdWZmZXIgYm9keSB3aXRoIGEgY29udGVudC1sZW5ndGhcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlcSA9IG5ldyBTaGltSW5jb21pbmdNZXNzYWdlKHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICB1cmw6IFwiL2FwaVwiLFxuICAgICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgYm9keTogQnVmZmVyLmZyb20oJ3tcImFcIjoxfScpLFxuICAgIH0pO1xuICAgIC8vIFBhZ2VzIEFQSSBib2R5IHBhcnNpbmcgcmVhZHMgYGNvbnRlbnQtbGVuZ3RoYCwgYW5kIG5laXRoZXIgRnVuY3Rpb24gVVJMXG4gICAgLy8gbm9yIEFQSSBHYXRld2F5IGV2ZW50cyByZWxpYWJseSBjYXJyeSBvbmUuXG4gICAgZXhwZWN0KHJlcS5oZWFkZXJzW1wiY29udGVudC1sZW5ndGhcIl0pLnRvQmUoXCI3XCIpO1xuICAgIGF3YWl0IGV4cGVjdChyZWFkQWxsKHJlcSkpLnJlc29sdmVzLnRvQmUoJ3tcImFcIjoxfScpO1xuICB9KTtcblxuICBpdChcImxlYXZlcyBhbiBleGlzdGluZyBjb250ZW50LWxlbmd0aCBhbG9uZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gbmV3IFNoaW1JbmNvbWluZ01lc3NhZ2Uoe1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIHVybDogXCIvYXBpXCIsXG4gICAgICBoZWFkZXJzOiB7IFwiY29udGVudC1sZW5ndGhcIjogXCI5OVwiIH0sXG4gICAgICBib2R5OiBCdWZmZXIuZnJvbShcImFiXCIpLFxuICAgIH0pO1xuICAgIGV4cGVjdChyZXEuaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdKS50b0JlKFwiOTlcIik7XG4gIH0pO1xuXG4gIGl0KFwicGlwZXMgYSBzdHJlYW1lZCBib2R5IHRocm91Z2hcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlcSA9IG5ldyBTaGltSW5jb21pbmdNZXNzYWdlKHtcbiAgICAgIG1ldGhvZDogXCJQVVRcIixcbiAgICAgIHVybDogXCIvdXBsb2FkXCIsXG4gICAgICBoZWFkZXJzOiB7IFwidHJhbnNmZXItZW5jb2RpbmdcIjogXCJjaHVua2VkXCIgfSxcbiAgICAgIGJvZHk6IFJlYWRhYmxlLmZyb20oW0J1ZmZlci5mcm9tKFwib25lIFwiKSwgQnVmZmVyLmZyb20oXCJ0d29cIildKSxcbiAgICB9KTtcbiAgICBhd2FpdCBleHBlY3QocmVhZEFsbChyZXEpKS5yZXNvbHZlcy50b0JlKFwib25lIHR3b1wiKTtcbiAgICBleHBlY3QocmVxLmNvbXBsZXRlKS50b0JlKHRydWUpO1xuICB9KTtcblxuICBpdChcImRlc3Ryb3lzIGl0c2VsZiB3aGVuIHRoZSBzb3VyY2Ugc3RyZWFtIGVycm9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc291cmNlID0gbmV3IFJlYWRhYmxlKHtcbiAgICAgIHJlYWQoKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveShuZXcgRXJyb3IoXCJ1cHN0cmVhbSBnb25lXCIpKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVxID0gbmV3IFNoaW1JbmNvbWluZ01lc3NhZ2Uoe1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIHVybDogXCIvXCIsXG4gICAgICBoZWFkZXJzOiB7fSxcbiAgICAgIGJvZHk6IHNvdXJjZSxcbiAgICB9KTtcbiAgICBhd2FpdCBleHBlY3QocmVhZEFsbChyZXEpKS5yZWplY3RzLnRvVGhyb3coXCJ1cHN0cmVhbSBnb25lXCIpO1xuICB9KTtcblxuICBpdChcImZpbGxzIHRoZSBzb2NrZXQgZmllbGRzIHRoYXQgYHNlbmRgIGFuZCB4LWZvcndhcmRlZC1mb3IgaGFuZGxpbmcgcmVhZFwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gbmV3IFNoaW1JbmNvbWluZ01lc3NhZ2Uoe1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgdXJsOiBcIi9cIixcbiAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgcmVtb3RlQWRkcmVzczogXCIyMDMuMC4xMTMuN1wiLFxuICAgICAgZW5jcnlwdGVkOiBmYWxzZSxcbiAgICB9KTtcbiAgICBleHBlY3QocmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzKS50b0JlKFwiMjAzLjAuMTEzLjdcIik7XG4gICAgLy8gYHNlcnZlU3RhdGljYCBjaGVja3MgYHJlcy5zb2NrZXQud3JpdGFibGVgIGJlZm9yZSBzdHJlYW1pbmcgYSBmaWxlLlxuICAgIGV4cGVjdChyZXEuc29ja2V0LndyaXRhYmxlKS50b0JlKHRydWUpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcInRvSW5jb21pbmdIdHRwSGVhZGVyc1wiLCAoKSA9PiB7XG4gIGl0KFwiZmxhdHRlbnMgYSBIZWFkZXJzLCBrZWVwaW5nIHNldC1jb29raWUgYXMgYW4gYXJyYXlcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyh7IFwieC1hXCI6IFwiMVwiIH0pO1xuICAgIGhlYWRlcnMuYXBwZW5kKFwic2V0LWNvb2tpZVwiLCBcImE9MVwiKTtcbiAgICBoZWFkZXJzLmFwcGVuZChcInNldC1jb29raWVcIiwgXCJiPTJcIik7XG4gICAgZXhwZWN0KHRvSW5jb21pbmdIdHRwSGVhZGVycyhoZWFkZXJzKSkudG9FcXVhbCh7XG4gICAgICBcIngtYVwiOiBcIjFcIixcbiAgICAgIFwic2V0LWNvb2tpZVwiOiBbXCJhPTFcIiwgXCJiPTJcIl0sXG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { OutgoingHttpHeaders, ServerResponse } from "node:http";
|
|
2
|
+
import { Transform } from "node:stream";
|
|
3
|
+
import type { TransformCallback } from "node:stream";
|
|
4
|
+
export interface ResponseHead {
|
|
5
|
+
readonly statusCode: number;
|
|
6
|
+
readonly statusMessage?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Flat header map with `set-cookie` removed — a `Record<string, string>`
|
|
9
|
+
* cannot represent it, and both sinks take cookies separately.
|
|
10
|
+
*/
|
|
11
|
+
readonly headers: Record<string, string>;
|
|
12
|
+
readonly cookies: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* One entry per `Set-Cookie` line, the way Node's `ServerResponse` emits them:
|
|
16
|
+
* each array element is a whole cookie and a string is exactly one. Nothing here
|
|
17
|
+
* splits on commas — `Expires=` dates contain one in every format (`Wed, 21 Oct`,
|
|
18
|
+
* `Wednesday, 21-Oct-26`), and a heuristic split turns one cookie into a session
|
|
19
|
+
* cookie on the wrong path plus a junk one.
|
|
20
|
+
*/
|
|
21
|
+
export declare function setCookieList(value: string | string[] | number): string[];
|
|
22
|
+
type HeaderValue = string | number | string[];
|
|
23
|
+
export declare class ShimServerResponse extends Transform {
|
|
24
|
+
statusCode: number;
|
|
25
|
+
statusMessage?: string;
|
|
26
|
+
headersSent: boolean;
|
|
27
|
+
/** Accepted and ignored: there is no socket to schedule a `Date` header on. */
|
|
28
|
+
sendDate: boolean;
|
|
29
|
+
strictContentLength: boolean;
|
|
30
|
+
chunkedEncoding: boolean;
|
|
31
|
+
shouldKeepAlive: boolean;
|
|
32
|
+
useChunkedEncodingByDefault: boolean;
|
|
33
|
+
/** Set by Next.js in a few places; never read by us. */
|
|
34
|
+
req?: unknown;
|
|
35
|
+
/**
|
|
36
|
+
* Installed by the runtime core when it inserts gzip, so that Next.js's
|
|
37
|
+
* per-chunk `if ("flush" in res) res.flush()` actually reaches the
|
|
38
|
+
* compressor. Without it, streamed HTML sits in zlib's buffer.
|
|
39
|
+
*/
|
|
40
|
+
flush?: () => void;
|
|
41
|
+
/** Lowercased name → original casing + value, mirroring Node's own store. */
|
|
42
|
+
private readonly headerStore;
|
|
43
|
+
constructor();
|
|
44
|
+
setHeader(name: string, value: HeaderValue): this;
|
|
45
|
+
appendHeader(name: string, value: string | string[]): this;
|
|
46
|
+
getHeader(name: string): HeaderValue | undefined;
|
|
47
|
+
getHeaders(): OutgoingHttpHeaders;
|
|
48
|
+
getHeaderNames(): string[];
|
|
49
|
+
hasHeader(name: string): boolean;
|
|
50
|
+
removeHeader(name: string): void;
|
|
51
|
+
writeHead(statusCode: number, statusMessageOrHeaders?: string | OutgoingHttpHeaders | HeaderValue[], maybeHeaders?: OutgoingHttpHeaders | HeaderValue[]): this;
|
|
52
|
+
/**
|
|
53
|
+
* Freezes status + headers and emits them as the `"head"` event. Called
|
|
54
|
+
* explicitly by Next.js before it streams, and lazily by this class on the
|
|
55
|
+
* first byte or on `end()` when it isn't.
|
|
56
|
+
*/
|
|
57
|
+
flushHeaders(): void;
|
|
58
|
+
/** Deprecated on `ServerResponse`, but `NodeNextResponse.sent` reads it. */
|
|
59
|
+
get finished(): boolean;
|
|
60
|
+
private buildHead;
|
|
61
|
+
_transform(chunk: unknown, _encoding: BufferEncoding, callback: TransformCallback): void;
|
|
62
|
+
_flush(callback: TransformCallback): void;
|
|
63
|
+
addTrailers(): never;
|
|
64
|
+
assignSocket(): never;
|
|
65
|
+
detachSocket(): never;
|
|
66
|
+
writeContinue(): never;
|
|
67
|
+
writeEarlyHints(): never;
|
|
68
|
+
writeProcessing(): never;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `ShimServerResponse` is structurally a `ServerResponse` for everything Next.js
|
|
72
|
+
* touches, but not nominally one (no socket, no trailers). The entrypoint
|
|
73
|
+
* signature wants the real type, so the cast is centralized here with the
|
|
74
|
+
* reasoning attached rather than repeated at each call site.
|
|
75
|
+
*/
|
|
76
|
+
export declare function asServerResponse(res: ShimServerResponse): ServerResponse;
|
|
77
|
+
export {};
|