cdk-nextjs 0.6.2 → 0.7.1
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 +2404 -2723
- package/.jsii.tabl.json +1 -1
- package/API.md +1681 -1930
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +667 -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 +1551 -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 +857 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +863 -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 +8 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
- 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/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 +14 -5
- package/lib/lambdas/post-deploy/prune-s3.js +41 -12
- package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
- 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 +102 -18
- package/lib/nextjs-api.js +338 -38
- package/lib/nextjs-api.test.js +537 -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 +13 -5
- package/lib/nextjs-post-deploy.js +13 -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 +17 -4
- package/lib/nextjs-static-assets.js +22 -5
- package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
- package/lib/root-constructs/nextjs-base-construct.js +139 -47
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -71
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -70
- package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
- package/lib/root-constructs/nextjs-regional-containers.js +8 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -26
- 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 +1216 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1686 -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 +41600 -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 +71 -0
- package/lib/runtime/next-modules.js +144 -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 +41593 -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 +106 -13
- package/lib/utils/base-path.js +254 -41
- package/lib/utils/base-path.test.js +219 -51
- 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,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShimServerResponse = void 0;
|
|
4
|
+
exports.setCookieList = setCookieList;
|
|
5
|
+
exports.asServerResponse = asServerResponse;
|
|
6
|
+
/**
|
|
7
|
+
* A synthesized, streaming `http.ServerResponse`.
|
|
8
|
+
*
|
|
9
|
+
* The response *is* the stream: this is a `Transform` that Next.js writes into,
|
|
10
|
+
* and the shell pipes into its own byte sink (`awslambda.HttpResponseStream` for
|
|
11
|
+
* Functions, the real `ServerResponse` for Containers). Status and headers are
|
|
12
|
+
* emitted once as a {@link ResponseHead} on the `"head"` event, because Lambda's
|
|
13
|
+
* response stream needs them in a prelude *before* any body byte.
|
|
14
|
+
*
|
|
15
|
+
* Modeled on OpenNext's `OpenNextNodeResponse` (MIT, © 2022 SST):
|
|
16
|
+
* https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/http/openNextResponse.ts
|
|
17
|
+
*
|
|
18
|
+
* Deliberately much smaller than that file. OpenNext's shim doubles as a
|
|
19
|
+
* `BaseNextResponse` and re-implements the middleware header merge, because
|
|
20
|
+
* OpenNext reimplements routing. We hand this object to `handler(req, res, ctx)`,
|
|
21
|
+
* which wraps it in Next.js's own `NodeNextResponse`
|
|
22
|
+
* (`next/dist/server/base-http/node.js`) — so the contract is just "be a
|
|
23
|
+
* `ServerResponse`", and the header-merge logic belongs to `@next/routing`.
|
|
24
|
+
*/
|
|
25
|
+
const node_http_1 = require("node:http");
|
|
26
|
+
const node_stream_1 = require("node:stream");
|
|
27
|
+
/**
|
|
28
|
+
* One entry per `Set-Cookie` line, the way Node's `ServerResponse` emits them:
|
|
29
|
+
* each array element is a whole cookie and a string is exactly one. Nothing here
|
|
30
|
+
* splits on commas — `Expires=` dates contain one in every format (`Wed, 21 Oct`,
|
|
31
|
+
* `Wednesday, 21-Oct-26`), and a heuristic split turns one cookie into a session
|
|
32
|
+
* cookie on the wrong path plus a junk one.
|
|
33
|
+
*/
|
|
34
|
+
function setCookieList(value) {
|
|
35
|
+
return (Array.isArray(value) ? value : [value])
|
|
36
|
+
.map((cookie) => String(cookie).trim())
|
|
37
|
+
.filter(Boolean);
|
|
38
|
+
}
|
|
39
|
+
/** Node never calls these, and Next.js never calls them either. */
|
|
40
|
+
function unsupported(method) {
|
|
41
|
+
throw new Error(`res.${method}() is not supported by the cdk-nextjs runtime. Next.js does ` +
|
|
42
|
+
`not call it, so reaching this means something else is writing the ` +
|
|
43
|
+
`response.`);
|
|
44
|
+
}
|
|
45
|
+
class ShimServerResponse extends node_stream_1.Transform {
|
|
46
|
+
statusCode = 200;
|
|
47
|
+
statusMessage;
|
|
48
|
+
headersSent = false;
|
|
49
|
+
/** Accepted and ignored: there is no socket to schedule a `Date` header on. */
|
|
50
|
+
sendDate = false;
|
|
51
|
+
strictContentLength = false;
|
|
52
|
+
chunkedEncoding = false;
|
|
53
|
+
shouldKeepAlive = false;
|
|
54
|
+
useChunkedEncodingByDefault = false;
|
|
55
|
+
/** Set by Next.js in a few places; never read by us. */
|
|
56
|
+
req;
|
|
57
|
+
/**
|
|
58
|
+
* Installed by the runtime core when it inserts gzip, so that Next.js's
|
|
59
|
+
* per-chunk `if ("flush" in res) res.flush()` actually reaches the
|
|
60
|
+
* compressor. Without it, streamed HTML sits in zlib's buffer.
|
|
61
|
+
*/
|
|
62
|
+
flush;
|
|
63
|
+
/** Lowercased name → original casing + value, mirroring Node's own store. */
|
|
64
|
+
headerStore = new Map();
|
|
65
|
+
constructor() {
|
|
66
|
+
super();
|
|
67
|
+
}
|
|
68
|
+
// --- header API -----------------------------------------------------------
|
|
69
|
+
setHeader(name, value) {
|
|
70
|
+
this.headerStore.set(name.toLowerCase(), { name, value });
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
appendHeader(name, value) {
|
|
74
|
+
const key = name.toLowerCase();
|
|
75
|
+
const current = this.headerStore.get(key);
|
|
76
|
+
if (current === undefined) {
|
|
77
|
+
return this.setHeader(name, value);
|
|
78
|
+
}
|
|
79
|
+
const values = Array.isArray(current.value)
|
|
80
|
+
? current.value
|
|
81
|
+
: [String(current.value)];
|
|
82
|
+
this.headerStore.set(key, {
|
|
83
|
+
name: current.name,
|
|
84
|
+
value: values.concat(value),
|
|
85
|
+
});
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
getHeader(name) {
|
|
89
|
+
return this.headerStore.get(name.toLowerCase())?.value;
|
|
90
|
+
}
|
|
91
|
+
getHeaders() {
|
|
92
|
+
const headers = {};
|
|
93
|
+
for (const { name, value } of this.headerStore.values()) {
|
|
94
|
+
headers[name.toLowerCase()] = value;
|
|
95
|
+
}
|
|
96
|
+
return headers;
|
|
97
|
+
}
|
|
98
|
+
getHeaderNames() {
|
|
99
|
+
return [...this.headerStore.keys()];
|
|
100
|
+
}
|
|
101
|
+
hasHeader(name) {
|
|
102
|
+
return this.headerStore.has(name.toLowerCase());
|
|
103
|
+
}
|
|
104
|
+
removeHeader(name) {
|
|
105
|
+
this.headerStore.delete(name.toLowerCase());
|
|
106
|
+
}
|
|
107
|
+
writeHead(statusCode, statusMessageOrHeaders, maybeHeaders) {
|
|
108
|
+
this.statusCode = statusCode;
|
|
109
|
+
let headers = maybeHeaders;
|
|
110
|
+
if (typeof statusMessageOrHeaders === "string") {
|
|
111
|
+
this.statusMessage = statusMessageOrHeaders;
|
|
112
|
+
}
|
|
113
|
+
else if (statusMessageOrHeaders !== undefined) {
|
|
114
|
+
headers = statusMessageOrHeaders;
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(headers)) {
|
|
117
|
+
// Node's flat even/odd `[name, value, name, value]` form, where a name
|
|
118
|
+
// may repeat (one `Set-Cookie` per cookie), so, as Node does, each name
|
|
119
|
+
// replaces what was set before but its values add up. Tuples are
|
|
120
|
+
// flattened into the same form.
|
|
121
|
+
const flat = Array.isArray(headers[0]) ? headers.flat() : headers;
|
|
122
|
+
for (let i = 0; i < flat.length; i += 2) {
|
|
123
|
+
this.removeHeader(String(flat[i]));
|
|
124
|
+
}
|
|
125
|
+
for (let i = 0; i < flat.length; i += 2) {
|
|
126
|
+
const value = flat[i + 1];
|
|
127
|
+
this.appendHeader(String(flat[i]), typeof value === "number" ? String(value) : value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (headers) {
|
|
131
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
132
|
+
if (value !== undefined) {
|
|
133
|
+
this.setHeader(name, value);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.flushHeaders();
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Freezes status + headers and emits them as the `"head"` event. Called
|
|
142
|
+
* explicitly by Next.js before it streams, and lazily by this class on the
|
|
143
|
+
* first byte or on `end()` when it isn't.
|
|
144
|
+
*/
|
|
145
|
+
flushHeaders() {
|
|
146
|
+
if (this.headersSent) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.headersSent = true;
|
|
150
|
+
this.emit("head", this.buildHead());
|
|
151
|
+
}
|
|
152
|
+
/** Deprecated on `ServerResponse`, but `NodeNextResponse.sent` reads it. */
|
|
153
|
+
get finished() {
|
|
154
|
+
return this.writableEnded;
|
|
155
|
+
}
|
|
156
|
+
buildHead() {
|
|
157
|
+
const headers = {};
|
|
158
|
+
let cookies = [];
|
|
159
|
+
for (const { name, value } of this.headerStore.values()) {
|
|
160
|
+
const key = name.toLowerCase();
|
|
161
|
+
if (key === "set-cookie") {
|
|
162
|
+
cookies = setCookieList(value);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (Array.isArray(value)) {
|
|
166
|
+
if (key === "location") {
|
|
167
|
+
// Next.js sends an array `Location` when a cacheHandler `get` returns
|
|
168
|
+
// null for a page that calls `redirect()`. Comma-joining produces a
|
|
169
|
+
// URL that resolves to nothing, so take the last write.
|
|
170
|
+
console.warn(`[cdk-nextjs] Next.js set ${value.length} Location headers ` +
|
|
171
|
+
`(${value.join(" | ")}); using the last one.`);
|
|
172
|
+
headers[key] = String(value[value.length - 1]);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
headers[key] = value.join(", ");
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
headers[key] = String(value);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
statusCode: this.statusCode,
|
|
182
|
+
statusMessage: this.statusMessage ?? node_http_1.STATUS_CODES[this.statusCode],
|
|
183
|
+
headers,
|
|
184
|
+
cookies,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// --- stream ---------------------------------------------------------------
|
|
188
|
+
_transform(chunk, _encoding, callback) {
|
|
189
|
+
// Lazily, because Next.js only calls `flushHeaders()` on the paths that
|
|
190
|
+
// stream. `sendPayload` just writes and ends.
|
|
191
|
+
this.flushHeaders();
|
|
192
|
+
callback(null, chunk);
|
|
193
|
+
}
|
|
194
|
+
_flush(callback) {
|
|
195
|
+
// An empty body still needs a status line.
|
|
196
|
+
this.flushHeaders();
|
|
197
|
+
callback();
|
|
198
|
+
}
|
|
199
|
+
// --- the rest of the ServerResponse surface -------------------------------
|
|
200
|
+
addTrailers() {
|
|
201
|
+
return unsupported("addTrailers");
|
|
202
|
+
}
|
|
203
|
+
assignSocket() {
|
|
204
|
+
return unsupported("assignSocket");
|
|
205
|
+
}
|
|
206
|
+
detachSocket() {
|
|
207
|
+
return unsupported("detachSocket");
|
|
208
|
+
}
|
|
209
|
+
writeContinue() {
|
|
210
|
+
return unsupported("writeContinue");
|
|
211
|
+
}
|
|
212
|
+
writeEarlyHints() {
|
|
213
|
+
return unsupported("writeEarlyHints");
|
|
214
|
+
}
|
|
215
|
+
writeProcessing() {
|
|
216
|
+
return unsupported("writeProcessing");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
exports.ShimServerResponse = ShimServerResponse;
|
|
220
|
+
/**
|
|
221
|
+
* `ShimServerResponse` is structurally a `ServerResponse` for everything Next.js
|
|
222
|
+
* touches, but not nominally one (no socket, no trailers). The entrypoint
|
|
223
|
+
* signature wants the real type, so the cast is centralized here with the
|
|
224
|
+
* reasoning attached rather than repeated at each call site.
|
|
225
|
+
*/
|
|
226
|
+
function asServerResponse(res) {
|
|
227
|
+
return res;
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVudGltZS9odHRwL3Jlc3BvbnNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTBDQSxzQ0FJQztBQXFPRCw0Q0FFQztBQXJSRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gseUNBQXlDO0FBRXpDLDZDQUF3QztBQWN4Qzs7Ozs7O0dBTUc7QUFDSCxTQUFnQixhQUFhLENBQUMsS0FBaUM7SUFDN0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUM1QyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUN0QyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDckIsQ0FBQztBQUlELG1FQUFtRTtBQUNuRSxTQUFTLFdBQVcsQ0FBQyxNQUFjO0lBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQ2IsT0FBTyxNQUFNLDhEQUE4RDtRQUN6RSxvRUFBb0U7UUFDcEUsV0FBVyxDQUNkLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBYSxrQkFBbUIsU0FBUSx1QkFBUztJQUN4QyxVQUFVLEdBQUcsR0FBRyxDQUFDO0lBQ2pCLGFBQWEsQ0FBVTtJQUN2QixXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQzNCLCtFQUErRTtJQUN4RSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLG1CQUFtQixHQUFHLEtBQUssQ0FBQztJQUM1QixlQUFlLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFDeEIsMkJBQTJCLEdBQUcsS0FBSyxDQUFDO0lBQzNDLHdEQUF3RDtJQUNqRCxHQUFHLENBQVc7SUFDckI7Ozs7T0FJRztJQUNJLEtBQUssQ0FBYztJ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QUFpQixDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUNNLGVBQWU7UUFDcEIsT0FBTyxXQUFXLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUN4QyxDQUFDO0NBQ0Y7QUFoTkQsZ0RBZ05DO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxHQUF1QjtJQUN0RCxPQUFPLEdBQWdDLENBQUM7QUFDMUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSBzeW50aGVzaXplZCwgc3RyZWFtaW5nIGBodHRwLlNlcnZlclJlc3BvbnNlYC5cbiAqXG4gKiBUaGUgcmVzcG9uc2UgKmlzKiB0aGUgc3RyZWFtOiB0aGlzIGlzIGEgYFRyYW5zZm9ybWAgdGhhdCBOZXh0LmpzIHdyaXRlcyBpbnRvLFxuICogYW5kIHRoZSBzaGVsbCBwaXBlcyBpbnRvIGl0cyBvd24gYnl0ZSBzaW5rIChgYXdzbGFtYmRhLkh0dHBSZXNwb25zZVN0cmVhbWAgZm9yXG4gKiBGdW5jdGlvbnMsIHRoZSByZWFsIGBTZXJ2ZXJSZXNwb25zZWAgZm9yIENvbnRhaW5lcnMpLiBTdGF0dXMgYW5kIGhlYWRlcnMgYXJlXG4gKiBlbWl0dGVkIG9uY2UgYXMgYSB7QGxpbmsgUmVzcG9uc2VIZWFkfSBvbiB0aGUgYFwiaGVhZFwiYCBldmVudCwgYmVjYXVzZSBMYW1iZGEnc1xuICogcmVzcG9uc2Ugc3RyZWFtIG5lZWRzIHRoZW0gaW4gYSBwcmVsdWRlICpiZWZvcmUqIGFueSBib2R5IGJ5dGUuXG4gKlxuICogTW9kZWxlZCBvbiBPcGVuTmV4dCdzIGBPcGVuTmV4dE5vZGVSZXNwb25zZWAgKE1JVCwgwqkgMjAyMiBTU1QpOlxuICogaHR0cHM6Ly9naXRodWIuY29tL29wZW5uZXh0anMvb3Blbm5leHRqcy1hd3MvYmxvYi9tYWluL3BhY2thZ2VzL29wZW4tbmV4dC9zcmMvaHR0cC9vcGVuTmV4dFJlc3BvbnNlLnRzXG4gKlxuICogRGVsaWJlcmF0ZWx5IG11Y2ggc21hbGxlciB0aGFuIHRoYXQgZmlsZS4gT3Blbk5leHQncyBzaGltIGRvdWJsZXMgYXMgYVxuICogYEJhc2VOZXh0UmVzcG9uc2VgIGFuZCByZS1pbXBsZW1lbnRzIHRoZSBtaWRkbGV3YXJlIGhlYWRlciBtZXJnZSwgYmVjYXVzZVxuICogT3Blbk5leHQgcmVpbXBsZW1lbnRzIHJvdXRpbmcuIFdlIGhhbmQgdGhpcyBvYmplY3QgdG8gYGhhbmRsZXIocmVxLCByZXMsIGN0eClgLFxuICogd2hpY2ggd3JhcHMgaXQgaW4gTmV4dC5qcydzIG93biBgTm9kZU5leHRSZXNwb25zZWBcbiAqIChgbmV4dC9kaXN0L3NlcnZlci9iYXNlLWh0dHAvbm9kZS5qc2ApIOKAlCBzbyB0aGUgY29udHJhY3QgaXMganVzdCBcImJlIGFcbiAqIGBTZXJ2ZXJSZXNwb25zZWBcIiwgYW5kIHRoZSBoZWFkZXItbWVyZ2UgbG9naWMgYmVsb25ncyB0byBgQG5leHQvcm91dGluZ2AuXG4gKi9cbmltcG9ydCB7IFNUQVRVU19DT0RFUyB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB0eXBlIHsgT3V0Z29pbmdIdHRwSGVhZGVycywgU2VydmVyUmVzcG9uc2UgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgeyBUcmFuc2Zvcm0gfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtQ2FsbGJhY2sgfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcblxuZXhwb3J0IGludGVyZmFjZSBSZXNwb25zZUhlYWQge1xuICByZWFkb25seSBzdGF0dXNDb2RlOiBudW1iZXI7XG4gIHJlYWRvbmx5IHN0YXR1c01lc3NhZ2U/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBGbGF0IGhlYWRlciBtYXAgd2l0aCBgc2V0LWNvb2tpZWAgcmVtb3ZlZCDigJQgYSBgUmVjb3JkPHN0cmluZywgc3RyaW5nPmBcbiAgICogY2Fubm90IHJlcHJlc2VudCBpdCwgYW5kIGJvdGggc2lua3MgdGFrZSBjb29raWVzIHNlcGFyYXRlbHkuXG4gICAqL1xuICByZWFkb25seSBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICByZWFkb25seSBjb29raWVzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBPbmUgZW50cnkgcGVyIGBTZXQtQ29va2llYCBsaW5lLCB0aGUgd2F5IE5vZGUncyBgU2VydmVyUmVzcG9uc2VgIGVtaXRzIHRoZW06XG4gKiBlYWNoIGFycmF5IGVsZW1lbnQgaXMgYSB3aG9sZSBjb29raWUgYW5kIGEgc3RyaW5nIGlzIGV4YWN0bHkgb25lLiBOb3RoaW5nIGhlcmVcbiAqIHNwbGl0cyBvbiBjb21tYXMg4oCUIGBFeHBpcmVzPWAgZGF0ZXMgY29udGFpbiBvbmUgaW4gZXZlcnkgZm9ybWF0IChgV2VkLCAyMSBPY3RgLFxuICogYFdlZG5lc2RheSwgMjEtT2N0LTI2YCksIGFuZCBhIGhldXJpc3RpYyBzcGxpdCB0dXJucyBvbmUgY29va2llIGludG8gYSBzZXNzaW9uXG4gKiBjb29raWUgb24gdGhlIHdyb25nIHBhdGggcGx1cyBhIGp1bmsgb25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Q29va2llTGlzdCh2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10gfCBudW1iZXIpOiBzdHJpbmdbXSB7XG4gIHJldHVybiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV0pXG4gICAgLm1hcCgoY29va2llKSA9PiBTdHJpbmcoY29va2llKS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbn1cblxudHlwZSBIZWFkZXJWYWx1ZSA9IHN0cmluZyB8IG51bWJlciB8IHN0cmluZ1tdO1xuXG4vKiogTm9kZSBuZXZlciBjYWxscyB0aGVzZSwgYW5kIE5leHQuanMgbmV2ZXIgY2FsbHMgdGhlbSBlaXRoZXIuICovXG5mdW5jdGlvbiB1bnN1cHBvcnRlZChtZXRob2Q6IHN0cmluZyk6IG5ldmVyIHtcbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGByZXMuJHttZXRob2R9KCkgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY2RrLW5leHRqcyBydW50aW1lLiBOZXh0LmpzIGRvZXMgYCArXG4gICAgICBgbm90IGNhbGwgaXQsIHNvIHJlYWNoaW5nIHRoaXMgbWVhbnMgc29tZXRoaW5nIGVsc2UgaXMgd3JpdGluZyB0aGUgYCArXG4gICAgICBgcmVzcG9uc2UuYCxcbiAgKTtcbn1cblxuZXhwb3J0IGNsYXNzIFNoaW1TZXJ2ZXJSZXNwb25zZSBleHRlbmRzIFRyYW5zZm9ybSB7XG4gIHB1YmxpYyBzdGF0dXNDb2RlID0gMjAwO1xuICBwdWJsaWMgc3RhdHVzTWVzc2FnZT86IHN0cmluZztcbiAgcHVibGljIGhlYWRlcnNTZW50ID0gZmFsc2U7XG4gIC8qKiBBY2NlcHRlZCBhbmQgaWdub3JlZDogdGhlcmUgaXMgbm8gc29ja2V0IHRvIHNjaGVkdWxlIGEgYERhdGVgIGhlYWRlciBvbi4gKi9cbiAgcHVibGljIHNlbmREYXRlID0gZmFsc2U7XG4gIHB1YmxpYyBzdHJpY3RDb250ZW50TGVuZ3RoID0gZmFsc2U7XG4gIHB1YmxpYyBjaHVua2VkRW5jb2RpbmcgPSBmYWxzZTtcbiAgcHVibGljIHNob3VsZEtlZXBBbGl2ZSA9IGZhbHNlO1xuICBwdWJsaWMgdXNlQ2h1bmtlZEVuY29kaW5nQnlEZWZhdWx0ID0gZmFsc2U7XG4gIC8qKiBTZXQgYnkgTmV4dC5qcyBpbiBhIGZldyBwbGFjZXM7IG5ldmVyIHJlYWQgYnkgdXMuICovXG4gIHB1YmxpYyByZXE/OiB1bmtub3duO1xuICAvKipcbiAgICogSW5zdGFsbGVkIGJ5IHRoZSBydW50aW1lIGNvcmUgd2hlbiBpdCBpbnNlcnRzIGd6aXAsIHNvIHRoYXQgTmV4dC5qcydzXG4gICAqIHBlci1jaHVuayBgaWYgKFwiZmx1c2hcIiBpbiByZXMpIHJlcy5mbHVzaCgpYCBhY3R1YWxseSByZWFjaGVzIHRoZVxuICAgKiBjb21wcmVzc29yLiBXaXRob3V0IGl0LCBzdHJlYW1lZCBIVE1MIHNpdHMgaW4gemxpYidzIGJ1ZmZlci5cbiAgICovXG4gIHB1YmxpYyBmbHVzaD86ICgpID0+IHZvaWQ7XG5cbiAgLyoqIExvd2VyY2FzZWQgbmFtZSDihpIgb3JpZ2luYWwgY2FzaW5nICsgdmFsdWUsIG1pcnJvcmluZyBOb2RlJ3Mgb3duIHN0b3JlLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGhlYWRlclN0b3JlID0gbmV3IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgeyBuYW1lOiBzdHJpbmc7IHZhbHVlOiBIZWFkZXJWYWx1ZSB9XG4gID4oKTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8vIC0tLSBoZWFkZXIgQVBJIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgcHVibGljIHNldEhlYWRlcihuYW1lOiBzdHJpbmcsIHZhbHVlOiBIZWFkZXJWYWx1ZSk6IHRoaXMge1xuICAgIHRoaXMuaGVhZGVyU3RvcmUuc2V0KG5hbWUudG9Mb3dlckNhc2UoKSwgeyBuYW1lLCB2YWx1ZSB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBhcHBlbmRIZWFkZXIobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10pOiB0aGlzIHtcbiAgICBjb25zdCBrZXkgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuaGVhZGVyU3RvcmUuZ2V0KGtleSk7XG4gICAgaWYgKGN1cnJlbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuc2V0SGVhZGVyKG5hbWUsIHZhbHVlKTtcbiAgICB9XG4gICAgY29uc3QgdmFsdWVzID0gQXJyYXkuaXNBcnJheShjdXJyZW50LnZhbHVlKVxuICAgICAgPyBjdXJyZW50LnZhbHVlXG4gICAgICA6IFtTdHJpbmcoY3VycmVudC52YWx1ZSldO1xuICAgIHRoaXMuaGVhZGVyU3RvcmUuc2V0KGtleSwge1xuICAgICAgbmFtZTogY3VycmVudC5uYW1lLFxuICAgICAgdmFsdWU6IHZhbHVlcy5jb25jYXQodmFsdWUpLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGdldEhlYWRlcihuYW1lOiBzdHJpbmcpOiBIZWFkZXJWYWx1ZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuaGVhZGVyU3RvcmUuZ2V0KG5hbWUudG9Mb3dlckNhc2UoKSk/LnZhbHVlO1xuICB9XG5cbiAgcHVibGljIGdldEhlYWRlcnMoKTogT3V0Z29pbmdIdHRwSGVhZGVycyB7XG4gICAgY29uc3QgaGVhZGVyczogT3V0Z29pbmdIdHRwSGVhZGVycyA9IHt9O1xuICAgIGZvciAoY29uc3QgeyBuYW1lLCB2YWx1ZSB9IG9mIHRoaXMuaGVhZGVyU3RvcmUudmFsdWVzKCkpIHtcbiAgICAgIGhlYWRlcnNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gaGVhZGVycztcbiAgfVxuXG4gIHB1YmxpYyBnZXRIZWFkZXJOYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLmhlYWRlclN0b3JlLmtleXMoKV07XG4gIH1cblxuICBwdWJsaWMgaGFzSGVhZGVyKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhlYWRlclN0b3JlLmhhcyhuYW1lLnRvTG93ZXJDYXNlKCkpO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUhlYWRlcihuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmhlYWRlclN0b3JlLmRlbGV0ZShuYW1lLnRvTG93ZXJDYXNlKCkpO1xuICB9XG5cbiAgcHVibGljIHdyaXRlSGVhZChcbiAgICBzdGF0dXNDb2RlOiBudW1iZXIsXG4gICAgc3RhdHVzTWVzc2FnZU9ySGVhZGVycz86IHN0cmluZyB8IE91dGdvaW5nSHR0cEhlYWRlcnMgfCBIZWFkZXJWYWx1ZVtdLFxuICAgIG1heWJlSGVhZGVycz86IE91dGdvaW5nSHR0cEhlYWRlcnMgfCBIZWFkZXJWYWx1ZVtdLFxuICApOiB0aGlzIHtcbiAgICB0aGlzLnN0YXR1c0NvZGUgPSBzdGF0dXNDb2RlO1xuICAgIGxldCBoZWFkZXJzID0gbWF5YmVIZWFkZXJzO1xuICAgIGlmICh0eXBlb2Ygc3RhdHVzTWVzc2FnZU9ySGVhZGVycyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgdGhpcy5zdGF0dXNNZXNzYWdlID0gc3RhdHVzTWVzc2FnZU9ySGVhZGVycztcbiAgICB9IGVsc2UgaWYgKHN0YXR1c01lc3NhZ2VPckhlYWRlcnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGVhZGVycyA9IHN0YXR1c01lc3NhZ2VPckhlYWRlcnM7XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaGVhZGVycykpIHtcbiAgICAgIC8vIE5vZGUncyBmbGF0IGV2ZW4vb2RkIGBbbmFtZSwgdmFsdWUsIG5hbWUsIHZhbHVlXWAgZm9ybSwgd2hlcmUgYSBuYW1lXG4gICAgICAvLyBtYXkgcmVwZWF0IChvbmUgYFNldC1Db29raWVgIHBlciBjb29raWUpLCBzbywgYXMgTm9kZSBkb2VzLCBlYWNoIG5hbWVcbiAgICAgIC8vIHJlcGxhY2VzIHdoYXQgd2FzIHNldCBiZWZvcmUgYnV0IGl0cyB2YWx1ZXMgYWRkIHVwLiBUdXBsZXMgYXJlXG4gICAgICAvLyBmbGF0dGVuZWQgaW50byB0aGUgc2FtZSBmb3JtLlxuICAgICAgY29uc3QgZmxhdCA9IEFycmF5LmlzQXJyYXkoaGVhZGVyc1swXSkgPyBoZWFkZXJzLmZsYXQoKSA6IGhlYWRlcnM7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZsYXQubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVIZWFkZXIoU3RyaW5nKGZsYXRbaV0pKTtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmxhdC5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGZsYXRbaSArIDFdIGFzIEhlYWRlclZhbHVlO1xuICAgICAgICB0aGlzLmFwcGVuZEhlYWRlcihcbiAgICAgICAgICBTdHJpbmcoZmxhdFtpXSksXG4gICAgICAgICAgdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiID8gU3RyaW5nKHZhbHVlKSA6IHZhbHVlLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoaGVhZGVycykge1xuICAgICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGhlYWRlcnMpKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5zZXRIZWFkZXIobmFtZSwgdmFsdWUgYXMgSGVhZGVyVmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5mbHVzaEhlYWRlcnMoKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGcmVlemVzIHN0YXR1cyArIGhlYWRlcnMgYW5kIGVtaXRzIHRoZW0gYXMgdGhlIGBcImhlYWRcImAgZXZlbnQuIENhbGxlZFxuICAgKiBleHBsaWNpdGx5IGJ5IE5leHQuanMgYmVmb3JlIGl0IHN0cmVhbXMsIGFuZCBsYXppbHkgYnkgdGhpcyBjbGFzcyBvbiB0aGVcbiAgICogZmlyc3QgYnl0ZSBvciBvbiBgZW5kKClgIHdoZW4gaXQgaXNuJ3QuXG4gICAqL1xuICBwdWJsaWMgZmx1c2hIZWFkZXJzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmhlYWRlcnNTZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuaGVhZGVyc1NlbnQgPSB0cnVlO1xuICAgIHRoaXMuZW1pdChcImhlYWRcIiwgdGhpcy5idWlsZEhlYWQoKSk7XG4gIH1cblxuICAvKiogRGVwcmVjYXRlZCBvbiBgU2VydmVyUmVzcG9uc2VgLCBidXQgYE5vZGVOZXh0UmVzcG9uc2Uuc2VudGAgcmVhZHMgaXQuICovXG4gIHB1YmxpYyBnZXQgZmluaXNoZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMud3JpdGFibGVFbmRlZDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRIZWFkKCk6IFJlc3BvbnNlSGVhZCB7XG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIGxldCBjb29raWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgeyBuYW1lLCB2YWx1ZSB9IG9mIHRoaXMuaGVhZGVyU3RvcmUudmFsdWVzKCkpIHtcbiAgICAgIGNvbnN0IGtleSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChrZXkgPT09IFwic2V0LWNvb2tpZVwiKSB7XG4gICAgICAgIGNvb2tpZXMgPSBzZXRDb29raWVMaXN0KHZhbHVlKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgaWYgKGtleSA9PT0gXCJsb2NhdGlvblwiKSB7XG4gICAgICAgICAgLy8gTmV4dC5qcyBzZW5kcyBhbiBhcnJheSBgTG9jYXRpb25gIHdoZW4gYSBjYWNoZUhhbmRsZXIgYGdldGAgcmV0dXJuc1xuICAgICAgICAgIC8vIG51bGwgZm9yIGEgcGFnZSB0aGF0IGNhbGxzIGByZWRpcmVjdCgpYC4gQ29tbWEtam9pbmluZyBwcm9kdWNlcyBhXG4gICAgICAgICAgLy8gVVJMIHRoYXQgcmVzb2x2ZXMgdG8gbm90aGluZywgc28gdGFrZSB0aGUgbGFzdCB3cml0ZS5cbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgW2Nkay1uZXh0anNdIE5leHQuanMgc2V0ICR7dmFsdWUubGVuZ3RofSBMb2NhdGlvbiBoZWFkZXJzIGAgK1xuICAgICAgICAgICAgICBgKCR7dmFsdWUuam9pbihcIiB8IFwiKX0pOyB1c2luZyB0aGUgbGFzdCBvbmUuYCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGhlYWRlcnNba2V5XSA9IFN0cmluZyh2YWx1ZVt2YWx1ZS5sZW5ndGggLSAxXSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaGVhZGVyc1trZXldID0gdmFsdWUuam9pbihcIiwgXCIpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGhlYWRlcnNba2V5XSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXNDb2RlOiB0aGlzLnN0YXR1c0NvZGUsXG4gICAgICBzdGF0dXNNZXNzYWdlOiB0aGlzLnN0YXR1c01lc3NhZ2UgPz8gU1RBVFVTX0NPREVTW3RoaXMuc3RhdHVzQ29kZV0sXG4gICAgICBoZWFkZXJzLFxuICAgICAgY29va2llcyxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tIHN0cmVhbSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwdWJsaWMgb3ZlcnJpZGUgX3RyYW5zZm9ybShcbiAgICBjaHVuazogdW5rbm93bixcbiAgICBfZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICAgIGNhbGxiYWNrOiBUcmFuc2Zvcm1DYWxsYmFjayxcbiAgKTogdm9pZCB7XG4gICAgLy8gTGF6aWx5LCBiZWNhdXNlIE5leHQuanMgb25seSBjYWxscyBgZmx1c2hIZWFkZXJzKClgIG9uIHRoZSBwYXRocyB0aGF0XG4gICAgLy8gc3RyZWFtLiBgc2VuZFBheWxvYWRgIGp1c3Qgd3JpdGVzIGFuZCBlbmRzLlxuICAgIHRoaXMuZmx1c2hIZWFkZXJzKCk7XG4gICAgY2FsbGJhY2sobnVsbCwgY2h1bmspO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF9mbHVzaChjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2spOiB2b2lkIHtcbiAgICAvLyBBbiBlbXB0eSBib2R5IHN0aWxsIG5lZWRzIGEgc3RhdHVzIGxpbmUuXG4gICAgdGhpcy5mbHVzaEhlYWRlcnMoKTtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgLy8gLS0tIHRoZSByZXN0IG9mIHRoZSBTZXJ2ZXJSZXNwb25zZSBzdXJmYWNlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwdWJsaWMgYWRkVHJhaWxlcnMoKTogbmV2ZXIge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZChcImFkZFRyYWlsZXJzXCIpO1xuICB9XG4gIHB1YmxpYyBhc3NpZ25Tb2NrZXQoKTogbmV2ZXIge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZChcImFzc2lnblNvY2tldFwiKTtcbiAgfVxuICBwdWJsaWMgZGV0YWNoU29ja2V0KCk6IG5ldmVyIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWQoXCJkZXRhY2hTb2NrZXRcIik7XG4gIH1cbiAgcHVibGljIHdyaXRlQ29udGludWUoKTogbmV2ZXIge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZChcIndyaXRlQ29udGludWVcIik7XG4gIH1cbiAgcHVibGljIHdyaXRlRWFybHlIaW50cygpOiBuZXZlciB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkKFwid3JpdGVFYXJseUhpbnRzXCIpO1xuICB9XG4gIHB1YmxpYyB3cml0ZVByb2Nlc3NpbmcoKTogbmV2ZXIge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZChcIndyaXRlUHJvY2Vzc2luZ1wiKTtcbiAgfVxufVxuXG4vKipcbiAqIGBTaGltU2VydmVyUmVzcG9uc2VgIGlzIHN0cnVjdHVyYWxseSBhIGBTZXJ2ZXJSZXNwb25zZWAgZm9yIGV2ZXJ5dGhpbmcgTmV4dC5qc1xuICogdG91Y2hlcywgYnV0IG5vdCBub21pbmFsbHkgb25lIChubyBzb2NrZXQsIG5vIHRyYWlsZXJzKS4gVGhlIGVudHJ5cG9pbnRcbiAqIHNpZ25hdHVyZSB3YW50cyB0aGUgcmVhbCB0eXBlLCBzbyB0aGUgY2FzdCBpcyBjZW50cmFsaXplZCBoZXJlIHdpdGggdGhlXG4gKiByZWFzb25pbmcgYXR0YWNoZWQgcmF0aGVyIHRoYW4gcmVwZWF0ZWQgYXQgZWFjaCBjYWxsIHNpdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc1NlcnZlclJlc3BvbnNlKHJlczogU2hpbVNlcnZlclJlc3BvbnNlKTogU2VydmVyUmVzcG9uc2Uge1xuICByZXR1cm4gcmVzIGFzIHVua25vd24gYXMgU2VydmVyUmVzcG9uc2U7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const response_1 = require("./response");
|
|
4
|
+
/** Collects the head and the body bytes the way a sink would. */
|
|
5
|
+
function collect(res) {
|
|
6
|
+
let head;
|
|
7
|
+
const chunks = [];
|
|
8
|
+
res.once("head", (value) => {
|
|
9
|
+
head = value;
|
|
10
|
+
});
|
|
11
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
12
|
+
return {
|
|
13
|
+
head: () => head,
|
|
14
|
+
body: () => Buffer.concat(chunks).toString("utf-8"),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function finished(res) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
res.once("end", resolve);
|
|
20
|
+
res.once("error", reject);
|
|
21
|
+
res.resume();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
describe("ShimServerResponse head", () => {
|
|
25
|
+
it("emits status and headers once, on the first body byte", async () => {
|
|
26
|
+
const res = new response_1.ShimServerResponse();
|
|
27
|
+
const sink = collect(res);
|
|
28
|
+
res.setHeader("Content-Type", "text/html");
|
|
29
|
+
expect(sink.head()).toBeUndefined();
|
|
30
|
+
res.write("<p>hi</p>");
|
|
31
|
+
expect(sink.head()).toEqual({
|
|
32
|
+
statusCode: 200,
|
|
33
|
+
statusMessage: "OK",
|
|
34
|
+
headers: { "content-type": "text/html" },
|
|
35
|
+
cookies: [],
|
|
36
|
+
});
|
|
37
|
+
res.end();
|
|
38
|
+
await finished(res);
|
|
39
|
+
expect(sink.body()).toBe("<p>hi</p>");
|
|
40
|
+
});
|
|
41
|
+
it("still emits a head for an empty body", async () => {
|
|
42
|
+
const res = new response_1.ShimServerResponse();
|
|
43
|
+
const sink = collect(res);
|
|
44
|
+
res.statusCode = 204;
|
|
45
|
+
res.end();
|
|
46
|
+
await finished(res);
|
|
47
|
+
expect(sink.head()?.statusCode).toBe(204);
|
|
48
|
+
});
|
|
49
|
+
it("is idempotent, so an explicit flushHeaders() plus a write emits once", () => {
|
|
50
|
+
const res = new response_1.ShimServerResponse();
|
|
51
|
+
const heads = [];
|
|
52
|
+
res.on("head", (head) => heads.push(head));
|
|
53
|
+
res.flushHeaders();
|
|
54
|
+
res.write("a");
|
|
55
|
+
res.flushHeaders();
|
|
56
|
+
expect(heads).toHaveLength(1);
|
|
57
|
+
expect(res.headersSent).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
it("reports `finished` once ended, which NodeNextResponse.sent reads", async () => {
|
|
60
|
+
const res = new response_1.ShimServerResponse();
|
|
61
|
+
collect(res);
|
|
62
|
+
expect(res.finished).toBe(false);
|
|
63
|
+
res.end("x");
|
|
64
|
+
await finished(res);
|
|
65
|
+
expect(res.finished).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("ShimServerResponse headers", () => {
|
|
69
|
+
it("keeps set-cookie out of the flat map", () => {
|
|
70
|
+
const res = new response_1.ShimServerResponse();
|
|
71
|
+
const sink = collect(res);
|
|
72
|
+
res.appendHeader("Set-Cookie", "a=1; Path=/");
|
|
73
|
+
res.appendHeader("Set-Cookie", "b=2; Path=/");
|
|
74
|
+
res.setHeader("X-Other", "keep");
|
|
75
|
+
res.flushHeaders();
|
|
76
|
+
expect(sink.head()?.cookies).toEqual(["a=1; Path=/", "b=2; Path=/"]);
|
|
77
|
+
expect(sink.head()?.headers).toEqual({ "x-other": "keep" });
|
|
78
|
+
});
|
|
79
|
+
it("joins other repeated headers with a comma", () => {
|
|
80
|
+
const res = new response_1.ShimServerResponse();
|
|
81
|
+
const sink = collect(res);
|
|
82
|
+
res.setHeader("Vary", ["Accept", "Cookie"]);
|
|
83
|
+
res.flushHeaders();
|
|
84
|
+
expect(sink.head()?.headers.vary).toBe("Accept, Cookie");
|
|
85
|
+
});
|
|
86
|
+
it("takes the last of multiple Location values and warns", () => {
|
|
87
|
+
const res = new response_1.ShimServerResponse();
|
|
88
|
+
const sink = collect(res);
|
|
89
|
+
const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
|
|
90
|
+
res.setHeader("Location", ["/first", "/second"]);
|
|
91
|
+
res.flushHeaders();
|
|
92
|
+
// Comma-joining would produce a URL that resolves to nothing.
|
|
93
|
+
expect(sink.head()?.headers.location).toBe("/second");
|
|
94
|
+
expect(warn).toHaveBeenCalled();
|
|
95
|
+
warn.mockRestore();
|
|
96
|
+
});
|
|
97
|
+
it("is case-insensitive and supports the rest of the header API", () => {
|
|
98
|
+
const res = new response_1.ShimServerResponse();
|
|
99
|
+
res.setHeader("X-A", "1");
|
|
100
|
+
expect(res.getHeader("x-a")).toBe("1");
|
|
101
|
+
expect(res.hasHeader("X-A")).toBe(true);
|
|
102
|
+
expect(res.getHeaderNames()).toEqual(["x-a"]);
|
|
103
|
+
expect(res.getHeaders()).toEqual({ "x-a": "1" });
|
|
104
|
+
res.removeHeader("X-A");
|
|
105
|
+
expect(res.hasHeader("x-a")).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe("ShimServerResponse.writeHead", () => {
|
|
109
|
+
it("accepts a status message plus a header object", () => {
|
|
110
|
+
const res = new response_1.ShimServerResponse();
|
|
111
|
+
const sink = collect(res);
|
|
112
|
+
res.writeHead(301, "Moved", { Location: "/there" });
|
|
113
|
+
expect(sink.head()).toEqual({
|
|
114
|
+
statusCode: 301,
|
|
115
|
+
statusMessage: "Moved",
|
|
116
|
+
headers: { location: "/there" },
|
|
117
|
+
cookies: [],
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
it("keeps every value of a name the flat array form repeats", () => {
|
|
121
|
+
const res = new response_1.ShimServerResponse();
|
|
122
|
+
const sink = collect(res);
|
|
123
|
+
res.setHeader("Set-Cookie", "stale=1");
|
|
124
|
+
res.setHeader("X-A", "stale");
|
|
125
|
+
res.writeHead(200, ["Set-Cookie", "a=1", "Set-Cookie", "b=2", "X-A", "1"]);
|
|
126
|
+
expect(sink.head()?.cookies).toEqual(["a=1", "b=2"]);
|
|
127
|
+
expect(sink.head()?.headers["x-a"]).toBe("1");
|
|
128
|
+
});
|
|
129
|
+
it("accepts the flat even/odd array form", () => {
|
|
130
|
+
const res = new response_1.ShimServerResponse();
|
|
131
|
+
const sink = collect(res);
|
|
132
|
+
res.writeHead(200, ["Content-Type", "text/plain", "X-B", "2"]);
|
|
133
|
+
expect(sink.head()?.headers).toEqual({
|
|
134
|
+
"content-type": "text/plain",
|
|
135
|
+
"x-b": "2",
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
it("accepts the tuple array form", () => {
|
|
139
|
+
const res = new response_1.ShimServerResponse();
|
|
140
|
+
const sink = collect(res);
|
|
141
|
+
res.writeHead(200, [
|
|
142
|
+
["Content-Type", "text/plain"],
|
|
143
|
+
["X-B", "2"],
|
|
144
|
+
]);
|
|
145
|
+
expect(sink.head()?.headers).toEqual({
|
|
146
|
+
"content-type": "text/plain",
|
|
147
|
+
"x-b": "2",
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe("setCookieList", () => {
|
|
152
|
+
it.each([
|
|
153
|
+
"token=x; expires=Wed, 21 Oct 2026 07:28:00 GMT; Path=/",
|
|
154
|
+
"token=x; Expires=Wednesday, 21-Oct-26 07:28:00 GMT; Path=/",
|
|
155
|
+
"a=1; Expires=Thu, 01 Jan 2026 00:00:00 GMT",
|
|
156
|
+
])("keeps a single cookie whole: %s", (cookie) => {
|
|
157
|
+
expect((0, response_1.setCookieList)(cookie)).toEqual([cookie]);
|
|
158
|
+
});
|
|
159
|
+
it("treats each array entry as one cookie and drops empties", () => {
|
|
160
|
+
expect((0, response_1.setCookieList)(["a=1; expires=Wed, 21 Oct 2026 07:28:00 GMT", "b=2", ""])).toEqual(["a=1; expires=Wed, 21 Oct 2026 07:28:00 GMT", "b=2"]);
|
|
161
|
+
});
|
|
162
|
+
it("emits a lowercase-expires cookie as one Set-Cookie line", () => {
|
|
163
|
+
const res = new response_1.ShimServerResponse();
|
|
164
|
+
const cookie = "token=x; expires=Wed, 21 Oct 2026 07:28:00 GMT; Path=/";
|
|
165
|
+
res.setHeader("Set-Cookie", cookie);
|
|
166
|
+
let head;
|
|
167
|
+
res.on("head", (h) => (head = h));
|
|
168
|
+
res.flushHeaders();
|
|
169
|
+
expect(head?.cookies).toEqual([cookie]);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
describe("unsupported ServerResponse methods", () => {
|
|
173
|
+
it.each(["addTrailers", "assignSocket", "writeContinue", "writeEarlyHints"])("throws a named error from %s()", (method) => {
|
|
174
|
+
const res = new response_1.ShimServerResponse();
|
|
175
|
+
expect(() => res[method]()).toThrow(`res.${method}()`);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydW50aW1lL2h0dHAvcmVzcG9uc2UudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHlDQUE2RTtBQUU3RSxpRUFBaUU7QUFDakUsU0FBUyxPQUFPLENBQUMsR0FBdUI7SUFJdEMsSUFBSSxJQUE4QixDQUFDO0lBQ25DLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQW1CLEVBQUUsRUFBRTtRQUN2QyxJQUFJLEdBQUcsS0FBSyxDQUFDO0lBQ2YsQ0FBQyxDQUFDLENBQUM7SUFDSCxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQWEsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3RELE9BQU87UUFDTCxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSTtRQUNoQixJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3BELENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxRQUFRLENBQUMsR0FBdUI7SUFDdkMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN6QixHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUMxQixHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxRQUFRLENBQUMseUJBQXlCLEVBQUUsR0FBRyxFQUFFO0lBQ3ZDLEVBQUUsQ0FBQyx1REFBdUQsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNyRSxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUVwQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3ZCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDMUIsVUFBVSxFQUFFLEdBQUc7WUFDZixhQUFhLEVBQUUsSUFBSTtZQUNuQixPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFO1lBQ3hDLE9BQU8sRUFBRSxFQUFFO1NBQ1osQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ1YsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLEdBQUcsQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDO1FBQ3JCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNWLE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNFQUFzRSxFQUFFLEdBQUcsRUFBRTtRQUM5RSxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxLQUFLLEdBQW1CLEVBQUUsQ0FBQztRQUNqQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQWtCLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN6RCxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNmLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlCLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGtFQUFrRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2hGLE1BQU0sR0FBRyxHQUFHLElBQUksNkJBQWtCLEVBQUUsQ0FBQztRQUNyQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDYixNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyw0QkFBNEIsRUFBRSxHQUFHLEVBQUU7SUFDMUMsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtRQUM5QyxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLEdBQUcsQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzlDLEdBQUcsQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzlDLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMkNBQTJDLEVBQUUsR0FBRyxFQUFFO1FBQ25ELE1BQU0sR0FBRyxHQUFHLElBQUksNkJBQWtCLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUM1QyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDM0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0RBQXNELEVBQUUsR0FBRyxFQUFFO1FBQzlELE1BQU0sR0FBRyxHQUFHLElBQUksNkJBQWtCLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsa0JBQWtCLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUNqRCxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsOERBQThEO1FBQzlELE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN0RCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDckIsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUUsR0FBRyxFQUFFO1FBQ3JFLE1BQU0sR0FBRyxHQUFHLElBQUksNkJBQWtCLEVBQUUsQ0FBQztRQUNyQyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMxQixNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDakQsR0FBRyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtJQUM1QyxFQUFFLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFO1FBQ3ZELE1BQU0sR0FBRyxHQUFHLElBQUksNkJBQWtCLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEQsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUMxQixVQUFVLEVBQUUsR0FBRztZQUNmLGFBQWEsRUFBRSxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUU7WUFDL0IsT0FBTyxFQUFFLEVBQUU7U0FDWixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx5REFBeUQsRUFBRSxHQUFHLEVBQUU7UUFDakUsTUFBTSxHQUFHLEdBQUcsSUFBSSw2QkFBa0IsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMxQixHQUFHLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN2QyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5QixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLFlBQVksRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2hELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtRQUM5QyxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsY0FBYyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMvRCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUNuQyxjQUFjLEVBQUUsWUFBWTtZQUM1QixLQUFLLEVBQUUsR0FBRztTQUNYLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtRQUN0QyxNQUFNLEdBQUcsR0FBRyxJQUFJLDZCQUFrQixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQztZQUM5QixDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7U0FDWSxDQUFDLENBQUM7UUFDNUIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDbkMsY0FBYyxFQUFFLFlBQVk7WUFDNUIsS0FBSyxFQUFFLEdBQUc7U0FDWCxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7SUFDN0IsRUFBRSxDQUFDLElBQUksQ0FBQztRQUNOLHdEQUF3RDtRQUN4RCw0REFBNEQ7UUFDNUQsNENBQTRDO0tBQzdDLENBQUMsQ0FBQyxpQ0FBaUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1FBQy9DLE1BQU0sQ0FBQyxJQUFBLHdCQUFhLEVBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ2xELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEdBQUcsRUFBRTtRQUNqRSxNQUFNLENBQ0osSUFBQSx3QkFBYSxFQUFDLENBQUMsNENBQTRDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQ3pFLENBQUMsT0FBTyxDQUFDLENBQUMsNENBQTRDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx5REFBeUQsRUFBRSxHQUFHLEVBQUU7UUFDakUsTUFBTSxHQUFHLEdBQUcsSUFBSSw2QkFBa0IsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sTUFBTSxHQUFHLHdEQUF3RCxDQUFDO1FBQ3hFLEdBQUcsQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BDLElBQUksSUFBOEIsQ0FBQztRQUNuQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQWUsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoRCxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzFDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsb0NBQW9DLEVBQUUsR0FBRyxFQUFFO0lBQ2xELEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxhQUFhLEVBQUUsY0FBYyxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQzFFLGdDQUFnQyxFQUNoQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1FBQ1QsTUFBTSxHQUFHLEdBQUcsSUFBSSw2QkFBa0IsRUFHakMsQ0FBQztRQUNGLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekQsQ0FBQyxDQUNGLENBQUM7QUFDSixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlc3BvbnNlSGVhZCwgU2hpbVNlcnZlclJlc3BvbnNlLCBzZXRDb29raWVMaXN0IH0gZnJvbSBcIi4vcmVzcG9uc2VcIjtcblxuLyoqIENvbGxlY3RzIHRoZSBoZWFkIGFuZCB0aGUgYm9keSBieXRlcyB0aGUgd2F5IGEgc2luayB3b3VsZC4gKi9cbmZ1bmN0aW9uIGNvbGxlY3QocmVzOiBTaGltU2VydmVyUmVzcG9uc2UpOiB7XG4gIGhlYWQ6ICgpID0+IFJlc3BvbnNlSGVhZCB8IHVuZGVmaW5lZDtcbiAgYm9keTogKCkgPT4gc3RyaW5nO1xufSB7XG4gIGxldCBoZWFkOiBSZXNwb25zZUhlYWQgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGNodW5rczogQnVmZmVyW10gPSBbXTtcbiAgcmVzLm9uY2UoXCJoZWFkXCIsICh2YWx1ZTogUmVzcG9uc2VIZWFkKSA9PiB7XG4gICAgaGVhZCA9IHZhbHVlO1xuICB9KTtcbiAgcmVzLm9uKFwiZGF0YVwiLCAoY2h1bms6IEJ1ZmZlcikgPT4gY2h1bmtzLnB1c2goY2h1bmspKTtcbiAgcmV0dXJuIHtcbiAgICBoZWFkOiAoKSA9PiBoZWFkLFxuICAgIGJvZHk6ICgpID0+IEJ1ZmZlci5jb25jYXQoY2h1bmtzKS50b1N0cmluZyhcInV0Zi04XCIpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBmaW5pc2hlZChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHJlcy5vbmNlKFwiZW5kXCIsIHJlc29sdmUpO1xuICAgIHJlcy5vbmNlKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICByZXMucmVzdW1lKCk7XG4gIH0pO1xufVxuXG5kZXNjcmliZShcIlNoaW1TZXJ2ZXJSZXNwb25zZSBoZWFkXCIsICgpID0+IHtcbiAgaXQoXCJlbWl0cyBzdGF0dXMgYW5kIGhlYWRlcnMgb25jZSwgb24gdGhlIGZpcnN0IGJvZHkgYnl0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvaHRtbFwiKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCkpLnRvQmVVbmRlZmluZWQoKTtcblxuICAgIHJlcy53cml0ZShcIjxwPmhpPC9wPlwiKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCkpLnRvRXF1YWwoe1xuICAgICAgc3RhdHVzQ29kZTogMjAwLFxuICAgICAgc3RhdHVzTWVzc2FnZTogXCJPS1wiLFxuICAgICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvaHRtbFwiIH0sXG4gICAgICBjb29raWVzOiBbXSxcbiAgICB9KTtcbiAgICByZXMuZW5kKCk7XG4gICAgYXdhaXQgZmluaXNoZWQocmVzKTtcbiAgICBleHBlY3Qoc2luay5ib2R5KCkpLnRvQmUoXCI8cD5oaTwvcD5cIik7XG4gIH0pO1xuXG4gIGl0KFwic3RpbGwgZW1pdHMgYSBoZWFkIGZvciBhbiBlbXB0eSBib2R5XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXMgPSBuZXcgU2hpbVNlcnZlclJlc3BvbnNlKCk7XG4gICAgY29uc3Qgc2luayA9IGNvbGxlY3QocmVzKTtcbiAgICByZXMuc3RhdHVzQ29kZSA9IDIwNDtcbiAgICByZXMuZW5kKCk7XG4gICAgYXdhaXQgZmluaXNoZWQocmVzKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCk/LnN0YXR1c0NvZGUpLnRvQmUoMjA0KTtcbiAgfSk7XG5cbiAgaXQoXCJpcyBpZGVtcG90ZW50LCBzbyBhbiBleHBsaWNpdCBmbHVzaEhlYWRlcnMoKSBwbHVzIGEgd3JpdGUgZW1pdHMgb25jZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IGhlYWRzOiBSZXNwb25zZUhlYWRbXSA9IFtdO1xuICAgIHJlcy5vbihcImhlYWRcIiwgKGhlYWQ6IFJlc3BvbnNlSGVhZCkgPT4gaGVhZHMucHVzaChoZWFkKSk7XG4gICAgcmVzLmZsdXNoSGVhZGVycygpO1xuICAgIHJlcy53cml0ZShcImFcIik7XG4gICAgcmVzLmZsdXNoSGVhZGVycygpO1xuICAgIGV4cGVjdChoZWFkcykudG9IYXZlTGVuZ3RoKDEpO1xuICAgIGV4cGVjdChyZXMuaGVhZGVyc1NlbnQpLnRvQmUodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KFwicmVwb3J0cyBgZmluaXNoZWRgIG9uY2UgZW5kZWQsIHdoaWNoIE5vZGVOZXh0UmVzcG9uc2Uuc2VudCByZWFkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbGxlY3QocmVzKTtcbiAgICBleHBlY3QocmVzLmZpbmlzaGVkKS50b0JlKGZhbHNlKTtcbiAgICByZXMuZW5kKFwieFwiKTtcbiAgICBhd2FpdCBmaW5pc2hlZChyZXMpO1xuICAgIGV4cGVjdChyZXMuZmluaXNoZWQpLnRvQmUodHJ1ZSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwiU2hpbVNlcnZlclJlc3BvbnNlIGhlYWRlcnNcIiwgKCkgPT4ge1xuICBpdChcImtlZXBzIHNldC1jb29raWUgb3V0IG9mIHRoZSBmbGF0IG1hcFwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLmFwcGVuZEhlYWRlcihcIlNldC1Db29raWVcIiwgXCJhPTE7IFBhdGg9L1wiKTtcbiAgICByZXMuYXBwZW5kSGVhZGVyKFwiU2V0LUNvb2tpZVwiLCBcImI9MjsgUGF0aD0vXCIpO1xuICAgIHJlcy5zZXRIZWFkZXIoXCJYLU90aGVyXCIsIFwia2VlcFwiKTtcbiAgICByZXMuZmx1c2hIZWFkZXJzKCk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZCgpPy5jb29raWVzKS50b0VxdWFsKFtcImE9MTsgUGF0aD0vXCIsIFwiYj0yOyBQYXRoPS9cIl0pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQoKT8uaGVhZGVycykudG9FcXVhbCh7IFwieC1vdGhlclwiOiBcImtlZXBcIiB9KTtcbiAgfSk7XG5cbiAgaXQoXCJqb2lucyBvdGhlciByZXBlYXRlZCBoZWFkZXJzIHdpdGggYSBjb21tYVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLnNldEhlYWRlcihcIlZhcnlcIiwgW1wiQWNjZXB0XCIsIFwiQ29va2llXCJdKTtcbiAgICByZXMuZmx1c2hIZWFkZXJzKCk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZCgpPy5oZWFkZXJzLnZhcnkpLnRvQmUoXCJBY2NlcHQsIENvb2tpZVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJ0YWtlcyB0aGUgbGFzdCBvZiBtdWx0aXBsZSBMb2NhdGlvbiB2YWx1ZXMgYW5kIHdhcm5zXCIsICgpID0+IHtcbiAgICBjb25zdCByZXMgPSBuZXcgU2hpbVNlcnZlclJlc3BvbnNlKCk7XG4gICAgY29uc3Qgc2luayA9IGNvbGxlY3QocmVzKTtcbiAgICBjb25zdCB3YXJuID0gamVzdC5zcHlPbihjb25zb2xlLCBcIndhcm5cIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgICByZXMuc2V0SGVhZGVyKFwiTG9jYXRpb25cIiwgW1wiL2ZpcnN0XCIsIFwiL3NlY29uZFwiXSk7XG4gICAgcmVzLmZsdXNoSGVhZGVycygpO1xuICAgIC8vIENvbW1hLWpvaW5pbmcgd291bGQgcHJvZHVjZSBhIFVSTCB0aGF0IHJlc29sdmVzIHRvIG5vdGhpbmcuXG4gICAgZXhwZWN0KHNpbmsuaGVhZCgpPy5oZWFkZXJzLmxvY2F0aW9uKS50b0JlKFwiL3NlY29uZFwiKTtcbiAgICBleHBlY3Qod2FybikudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIHdhcm4ubW9ja1Jlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoXCJpcyBjYXNlLWluc2Vuc2l0aXZlIGFuZCBzdXBwb3J0cyB0aGUgcmVzdCBvZiB0aGUgaGVhZGVyIEFQSVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIHJlcy5zZXRIZWFkZXIoXCJYLUFcIiwgXCIxXCIpO1xuICAgIGV4cGVjdChyZXMuZ2V0SGVhZGVyKFwieC1hXCIpKS50b0JlKFwiMVwiKTtcbiAgICBleHBlY3QocmVzLmhhc0hlYWRlcihcIlgtQVwiKSkudG9CZSh0cnVlKTtcbiAgICBleHBlY3QocmVzLmdldEhlYWRlck5hbWVzKCkpLnRvRXF1YWwoW1wieC1hXCJdKTtcbiAgICBleHBlY3QocmVzLmdldEhlYWRlcnMoKSkudG9FcXVhbCh7IFwieC1hXCI6IFwiMVwiIH0pO1xuICAgIHJlcy5yZW1vdmVIZWFkZXIoXCJYLUFcIik7XG4gICAgZXhwZWN0KHJlcy5oYXNIZWFkZXIoXCJ4LWFcIikpLnRvQmUoZmFsc2UpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcIlNoaW1TZXJ2ZXJSZXNwb25zZS53cml0ZUhlYWRcIiwgKCkgPT4ge1xuICBpdChcImFjY2VwdHMgYSBzdGF0dXMgbWVzc2FnZSBwbHVzIGEgaGVhZGVyIG9iamVjdFwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLndyaXRlSGVhZCgzMDEsIFwiTW92ZWRcIiwgeyBMb2NhdGlvbjogXCIvdGhlcmVcIiB9KTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCkpLnRvRXF1YWwoe1xuICAgICAgc3RhdHVzQ29kZTogMzAxLFxuICAgICAgc3RhdHVzTWVzc2FnZTogXCJNb3ZlZFwiLFxuICAgICAgaGVhZGVyczogeyBsb2NhdGlvbjogXCIvdGhlcmVcIiB9LFxuICAgICAgY29va2llczogW10sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwia2VlcHMgZXZlcnkgdmFsdWUgb2YgYSBuYW1lIHRoZSBmbGF0IGFycmF5IGZvcm0gcmVwZWF0c1wiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLnNldEhlYWRlcihcIlNldC1Db29raWVcIiwgXCJzdGFsZT0xXCIpO1xuICAgIHJlcy5zZXRIZWFkZXIoXCJYLUFcIiwgXCJzdGFsZVwiKTtcbiAgICByZXMud3JpdGVIZWFkKDIwMCwgW1wiU2V0LUNvb2tpZVwiLCBcImE9MVwiLCBcIlNldC1Db29raWVcIiwgXCJiPTJcIiwgXCJYLUFcIiwgXCIxXCJdKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCk/LmNvb2tpZXMpLnRvRXF1YWwoW1wiYT0xXCIsIFwiYj0yXCJdKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCk/LmhlYWRlcnNbXCJ4LWFcIl0pLnRvQmUoXCIxXCIpO1xuICB9KTtcblxuICBpdChcImFjY2VwdHMgdGhlIGZsYXQgZXZlbi9vZGQgYXJyYXkgZm9ybVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IHNpbmsgPSBjb2xsZWN0KHJlcyk7XG4gICAgcmVzLndyaXRlSGVhZCgyMDAsIFtcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvcGxhaW5cIiwgXCJYLUJcIiwgXCIyXCJdKTtcbiAgICBleHBlY3Qoc2luay5oZWFkKCk/LmhlYWRlcnMpLnRvRXF1YWwoe1xuICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJ0ZXh0L3BsYWluXCIsXG4gICAgICBcIngtYlwiOiBcIjJcIixcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJhY2NlcHRzIHRoZSB0dXBsZSBhcnJheSBmb3JtXCIsICgpID0+IHtcbiAgICBjb25zdCByZXMgPSBuZXcgU2hpbVNlcnZlclJlc3BvbnNlKCk7XG4gICAgY29uc3Qgc2luayA9IGNvbGxlY3QocmVzKTtcbiAgICByZXMud3JpdGVIZWFkKDIwMCwgW1xuICAgICAgW1wiQ29udGVudC1UeXBlXCIsIFwidGV4dC9wbGFpblwiXSxcbiAgICAgIFtcIlgtQlwiLCBcIjJcIl0sXG4gICAgXSBhcyB1bmtub3duIGFzIHN0cmluZ1tdW10pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQoKT8uaGVhZGVycykudG9FcXVhbCh7XG4gICAgICBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvcGxhaW5cIixcbiAgICAgIFwieC1iXCI6IFwiMlwiLFxuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcInNldENvb2tpZUxpc3RcIiwgKCkgPT4ge1xuICBpdC5lYWNoKFtcbiAgICBcInRva2VuPXg7IGV4cGlyZXM9V2VkLCAyMSBPY3QgMjAyNiAwNzoyODowMCBHTVQ7IFBhdGg9L1wiLFxuICAgIFwidG9rZW49eDsgRXhwaXJlcz1XZWRuZXNkYXksIDIxLU9jdC0yNiAwNzoyODowMCBHTVQ7IFBhdGg9L1wiLFxuICAgIFwiYT0xOyBFeHBpcmVzPVRodSwgMDEgSmFuIDIwMjYgMDA6MDA6MDAgR01UXCIsXG4gIF0pKFwia2VlcHMgYSBzaW5nbGUgY29va2llIHdob2xlOiAlc1wiLCAoY29va2llKSA9PiB7XG4gICAgZXhwZWN0KHNldENvb2tpZUxpc3QoY29va2llKSkudG9FcXVhbChbY29va2llXSk7XG4gIH0pO1xuXG4gIGl0KFwidHJlYXRzIGVhY2ggYXJyYXkgZW50cnkgYXMgb25lIGNvb2tpZSBhbmQgZHJvcHMgZW1wdGllc1wiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgc2V0Q29va2llTGlzdChbXCJhPTE7IGV4cGlyZXM9V2VkLCAyMSBPY3QgMjAyNiAwNzoyODowMCBHTVRcIiwgXCJiPTJcIiwgXCJcIl0pLFxuICAgICkudG9FcXVhbChbXCJhPTE7IGV4cGlyZXM9V2VkLCAyMSBPY3QgMjAyNiAwNzoyODowMCBHTVRcIiwgXCJiPTJcIl0pO1xuICB9KTtcblxuICBpdChcImVtaXRzIGEgbG93ZXJjYXNlLWV4cGlyZXMgY29va2llIGFzIG9uZSBTZXQtQ29va2llIGxpbmVcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHJlcyA9IG5ldyBTaGltU2VydmVyUmVzcG9uc2UoKTtcbiAgICBjb25zdCBjb29raWUgPSBcInRva2VuPXg7IGV4cGlyZXM9V2VkLCAyMSBPY3QgMjAyNiAwNzoyODowMCBHTVQ7IFBhdGg9L1wiO1xuICAgIHJlcy5zZXRIZWFkZXIoXCJTZXQtQ29va2llXCIsIGNvb2tpZSk7XG4gICAgbGV0IGhlYWQ6IFJlc3BvbnNlSGVhZCB8IHVuZGVmaW5lZDtcbiAgICByZXMub24oXCJoZWFkXCIsIChoOiBSZXNwb25zZUhlYWQpID0+IChoZWFkID0gaCkpO1xuICAgIHJlcy5mbHVzaEhlYWRlcnMoKTtcbiAgICBleHBlY3QoaGVhZD8uY29va2llcykudG9FcXVhbChbY29va2llXSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwidW5zdXBwb3J0ZWQgU2VydmVyUmVzcG9uc2UgbWV0aG9kc1wiLCAoKSA9PiB7XG4gIGl0LmVhY2goW1wiYWRkVHJhaWxlcnNcIiwgXCJhc3NpZ25Tb2NrZXRcIiwgXCJ3cml0ZUNvbnRpbnVlXCIsIFwid3JpdGVFYXJseUhpbnRzXCJdKShcbiAgICBcInRocm93cyBhIG5hbWVkIGVycm9yIGZyb20gJXMoKVwiLFxuICAgIChtZXRob2QpID0+IHtcbiAgICAgIGNvbnN0IHJlcyA9IG5ldyBTaGltU2VydmVyUmVzcG9uc2UoKSBhcyB1bmtub3duIGFzIFJlY29yZDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICAoKSA9PiB2b2lkXG4gICAgICA+O1xuICAgICAgZXhwZWN0KCgpID0+IHJlc1ttZXRob2RdKCkpLnRvVGhyb3coYHJlcy4ke21ldGhvZH0oKWApO1xuICAgIH0sXG4gICk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connecting a {@link ShimServerResponse} to the bytes-out side of a shell, and
|
|
3
|
+
* the one thing that has to happen on the way: gzip.
|
|
4
|
+
*
|
|
5
|
+
* This lives in shared runtime code rather than in the Lambda shell on purpose.
|
|
6
|
+
* Neither managed layer can compress a *streamed* response:
|
|
7
|
+
*
|
|
8
|
+
* - API Gateway's `minCompressionSize` is set (`src/nextjs-api.ts`) but inert,
|
|
9
|
+
* because cdk-nextjs also sets `ResponseTransferMode.STREAM`, and STREAM drops
|
|
10
|
+
* content encoding outright — "If you want to compress your integration
|
|
11
|
+
* response, do this in your integration".
|
|
12
|
+
* - CloudFront requires the origin to send `Content-Length`, which a streamed
|
|
13
|
+
* response by definition does not. It still compresses non-streamed responses
|
|
14
|
+
* and S3 assets, so the gap is exactly streamed HTML and RSC payloads — the
|
|
15
|
+
* largest text responses we serve.
|
|
16
|
+
*
|
|
17
|
+
* Until the container path was dropped, Lambda Web Adapter did this for us, which
|
|
18
|
+
* is why nothing in the old code mentions it. **Don't "fix" the API Gateway or
|
|
19
|
+
* CloudFront settings expecting them to take over.**
|
|
20
|
+
*
|
|
21
|
+
* gzip rather than brotli: brotli's streaming throughput at default quality is
|
|
22
|
+
* poor, and CloudFront prefers `br` only when the origin didn't already encode —
|
|
23
|
+
* which stops applying the moment we set `content-encoding` ourselves.
|
|
24
|
+
*/
|
|
25
|
+
import { Writable } from "node:stream";
|
|
26
|
+
import type { ShimIncomingMessage } from "./request";
|
|
27
|
+
import { ResponseHead, ShimServerResponse } from "./response";
|
|
28
|
+
export interface ResponseSink {
|
|
29
|
+
/**
|
|
30
|
+
* Set by the Lambda sink, for both integrations: a streamed Lambda response
|
|
31
|
+
* with zero payload bytes after the metadata delimiter is not recognized as a
|
|
32
|
+
* metadata response at all, so a single space is written instead of nothing.
|
|
33
|
+
*
|
|
34
|
+
* API Gateway answers 502. A Function URL is worse because it looks like it
|
|
35
|
+
* worked: the prelude is discarded and the response arrives as a bare
|
|
36
|
+
* `200 application/octet-stream` with an empty body, none of the app's headers,
|
|
37
|
+
* and an HTTP/2 stream that does not close cleanly — whatever the real status
|
|
38
|
+
* was. Measured against a `NextjsGlobalFunctions` deployment: `HEAD` on a 404
|
|
39
|
+
* page answered `200`, and a server action whose reply is empty (an action that
|
|
40
|
+
* only `redirect()`s, which Next.js answers with `x-action-redirect` and no
|
|
41
|
+
* body) lost the redirect header and so never navigated.
|
|
42
|
+
*
|
|
43
|
+
* The pre-adapter image handler carried the same workaround for 304s. RFC 9110
|
|
44
|
+
* forbids a body on 204/304, and a space technically violates that, but losing
|
|
45
|
+
* the status entirely is the worse failure — and on the CloudFront path a
|
|
46
|
+
* conditional request cannot reach the origin anyway, because `if-none-match`
|
|
47
|
+
* is not in the dynamic cache policy's header allowlist. The container sink
|
|
48
|
+
* writes to a real `ServerResponse` and does not set this.
|
|
49
|
+
*/
|
|
50
|
+
readonly padEmptyBody?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Called exactly once, before any body byte, with the final head. Returns the
|
|
53
|
+
* stream the body is written to; {@link pipeToSink} ends it.
|
|
54
|
+
*/
|
|
55
|
+
begin(head: ResponseHead): Writable;
|
|
56
|
+
}
|
|
57
|
+
export interface PipeOptions {
|
|
58
|
+
/** `next.config` `compress`. */
|
|
59
|
+
readonly compress: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Pipe `res` into `sink`, gzipping when that is both allowed and useful.
|
|
63
|
+
*
|
|
64
|
+
* Resolves when the sink's stream has finished, which for Lambda is the point the
|
|
65
|
+
* client has the whole response. Must be called *before* anything writes to
|
|
66
|
+
* `res`, because it subscribes to the one-shot `"head"` event.
|
|
67
|
+
*/
|
|
68
|
+
export declare function pipeToSink(req: ShimIncomingMessage, res: ShimServerResponse, sink: ResponseSink, options: PipeOptions): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* A `q=0` on gzip is a refusal, and both `*` forms have to be honored, so this
|
|
71
|
+
* parses rather than substring-matching.
|
|
72
|
+
*/
|
|
73
|
+
export declare function acceptsGzip(header: string | string[] | undefined): boolean;
|