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,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pipeToSink = pipeToSink;
|
|
4
|
+
exports.acceptsGzip = acceptsGzip;
|
|
5
|
+
/**
|
|
6
|
+
* Connecting a {@link ShimServerResponse} to the bytes-out side of a shell, and
|
|
7
|
+
* the one thing that has to happen on the way: gzip.
|
|
8
|
+
*
|
|
9
|
+
* This lives in shared runtime code rather than in the Lambda shell on purpose.
|
|
10
|
+
* Neither managed layer can compress a *streamed* response:
|
|
11
|
+
*
|
|
12
|
+
* - API Gateway's `minCompressionSize` is set (`src/nextjs-api.ts`) but inert,
|
|
13
|
+
* because cdk-nextjs also sets `ResponseTransferMode.STREAM`, and STREAM drops
|
|
14
|
+
* content encoding outright — "If you want to compress your integration
|
|
15
|
+
* response, do this in your integration".
|
|
16
|
+
* - CloudFront requires the origin to send `Content-Length`, which a streamed
|
|
17
|
+
* response by definition does not. It still compresses non-streamed responses
|
|
18
|
+
* and S3 assets, so the gap is exactly streamed HTML and RSC payloads — the
|
|
19
|
+
* largest text responses we serve.
|
|
20
|
+
*
|
|
21
|
+
* Until the container path was dropped, Lambda Web Adapter did this for us, which
|
|
22
|
+
* is why nothing in the old code mentions it. **Don't "fix" the API Gateway or
|
|
23
|
+
* CloudFront settings expecting them to take over.**
|
|
24
|
+
*
|
|
25
|
+
* gzip rather than brotli: brotli's streaming throughput at default quality is
|
|
26
|
+
* poor, and CloudFront prefers `br` only when the origin didn't already encode —
|
|
27
|
+
* which stops applying the moment we set `content-encoding` ourselves.
|
|
28
|
+
*/
|
|
29
|
+
const node_stream_1 = require("node:stream");
|
|
30
|
+
const promises_1 = require("node:stream/promises");
|
|
31
|
+
const node_zlib_1 = require("node:zlib");
|
|
32
|
+
/**
|
|
33
|
+
* Content types worth compressing. Everything Next streams as HTML or an RSC
|
|
34
|
+
* payload is `text/*`; images and fonts are already compressed, and gzipping an
|
|
35
|
+
* optimized AVIF just burns CPU.
|
|
36
|
+
*/
|
|
37
|
+
const COMPRESSIBLE = /^(?:text\/|application\/(?:json|javascript|xml|manifest|rss\+xml|atom\+xml)|image\/svg\+xml)/;
|
|
38
|
+
/**
|
|
39
|
+
* Statuses whose body must not be compressed: 204 and 304 have none, and a 206's
|
|
40
|
+
* body is a byte range of the *uncompressed* representation.
|
|
41
|
+
*
|
|
42
|
+
* 206 is reachable — `serveStaticFile` is `send` underneath, which advertises
|
|
43
|
+
* `Accept-Ranges: bytes` and honors `Range` on the static HTML the runtime serves
|
|
44
|
+
* itself. Gzipping one produced a response whose `Content-Range` still described
|
|
45
|
+
* the uncompressed slice (`withGzipHeaders` drops `content-length` but cannot
|
|
46
|
+
* restate a range), so the client got bytes that did not match what it asked for.
|
|
47
|
+
*/
|
|
48
|
+
const UNCOMPRESSABLE_STATUS = new Set([204, 206, 304]);
|
|
49
|
+
/** `compression`'s own test for the directive. */
|
|
50
|
+
const NO_TRANSFORM = /(?:^|,)\s*?no-transform\s*?(?:,|$)/i;
|
|
51
|
+
/**
|
|
52
|
+
* Pipe `res` into `sink`, gzipping when that is both allowed and useful.
|
|
53
|
+
*
|
|
54
|
+
* Resolves when the sink's stream has finished, which for Lambda is the point the
|
|
55
|
+
* client has the whole response. Must be called *before* anything writes to
|
|
56
|
+
* `res`, because it subscribes to the one-shot `"head"` event.
|
|
57
|
+
*/
|
|
58
|
+
function pipeToSink(req, res, sink, options) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
let piping = false;
|
|
61
|
+
res.once("error", reject);
|
|
62
|
+
// Destroyed before the head went out, and without an error: a client that
|
|
63
|
+
// disconnected before the first byte, which `handle()` answers with
|
|
64
|
+
// `res.destroy()`. `Transform.destroy()` with no argument emits only
|
|
65
|
+
// `"close"`, and the pipeline below never started, so nothing else can ever
|
|
66
|
+
// settle this promise — leaving `handle()` awaiting it forever, its
|
|
67
|
+
// `waitUntil` work (ISR revalidation, cache writes) never flushed and the
|
|
68
|
+
// in-flight render's closure retained for the life of the process.
|
|
69
|
+
res.once("close", () => {
|
|
70
|
+
if (!piping) {
|
|
71
|
+
resolve();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
res.once("head", (head) => {
|
|
75
|
+
piping = true;
|
|
76
|
+
const stages = [];
|
|
77
|
+
const gzip = shouldGzip(req, res, head, options);
|
|
78
|
+
if (gzip) {
|
|
79
|
+
const compressor = (0, node_zlib_1.createGzip)();
|
|
80
|
+
// Next.js calls `res.flush()` after each chunk it writes
|
|
81
|
+
// (`next/dist/server/pipe-readable.js`); without forwarding it, streamed
|
|
82
|
+
// HTML sits in zlib's buffer and the response arrives all at once.
|
|
83
|
+
res.flush = () => compressor.flush(node_zlib_1.constants.Z_SYNC_FLUSH);
|
|
84
|
+
stages.push(compressor);
|
|
85
|
+
}
|
|
86
|
+
if (sink.padEmptyBody) {
|
|
87
|
+
stages.push(padEmptyBody());
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
stages.push(sink.begin(gzip ? withGzipHeaders(head) : head));
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
// This runs inside whichever `res` call flushed the head — usually a
|
|
94
|
+
// `write()` from deep inside Next.js — so an escaping throw lands there,
|
|
95
|
+
// the pipeline below never starts, and nothing would settle this
|
|
96
|
+
// promise: `handle()` would hang. A sink's `writeHead` rejecting a
|
|
97
|
+
// header value is how it happens. Destroying `res` is what stops the
|
|
98
|
+
// writer; the `"error"` that emits is a no-op after the `reject`.
|
|
99
|
+
for (const stage of stages) {
|
|
100
|
+
stage.destroy();
|
|
101
|
+
}
|
|
102
|
+
reject(error);
|
|
103
|
+
res.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
(0, promises_1.pipeline)(res, ...stages).then(resolve, reject);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function shouldGzip(req, res, head, options) {
|
|
111
|
+
if (!options.compress) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (req.method === "HEAD" || UNCOMPRESSABLE_STATUS.has(head.statusCode)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
// Next.js encodes some responses itself; double-encoding is not a thing.
|
|
118
|
+
if (res.hasHeader("content-encoding")) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (!COMPRESSIBLE.test(head.headers["content-type"] ?? "")) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// The response's opt-out, which `next start`'s `compression` honors too: an
|
|
125
|
+
// SSE stream sets it so that nothing buffers its events.
|
|
126
|
+
if (NO_TRANSFORM.test(head.headers["cache-control"] ?? "")) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return acceptsGzip(req.headers["accept-encoding"]);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A `q=0` on gzip is a refusal, and both `*` forms have to be honored, so this
|
|
133
|
+
* parses rather than substring-matching.
|
|
134
|
+
*/
|
|
135
|
+
function acceptsGzip(header) {
|
|
136
|
+
const value = Array.isArray(header) ? header.join(",") : header;
|
|
137
|
+
if (!value) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
let wildcard;
|
|
141
|
+
for (const part of value.split(",")) {
|
|
142
|
+
const [rawName, ...params] = part.split(";");
|
|
143
|
+
const name = rawName.trim().toLowerCase();
|
|
144
|
+
if (name !== "gzip" && name !== "*") {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const q = params
|
|
148
|
+
.map((p) => p.trim().toLowerCase())
|
|
149
|
+
.find((p) => p.startsWith("q="));
|
|
150
|
+
const accepted = q === undefined || Number(q.slice(2)) > 0;
|
|
151
|
+
if (name === "gzip") {
|
|
152
|
+
return accepted;
|
|
153
|
+
}
|
|
154
|
+
wildcard = accepted;
|
|
155
|
+
}
|
|
156
|
+
return wildcard ?? false;
|
|
157
|
+
}
|
|
158
|
+
function withGzipHeaders(head) {
|
|
159
|
+
const headers = {
|
|
160
|
+
...head.headers,
|
|
161
|
+
"content-encoding": "gzip",
|
|
162
|
+
};
|
|
163
|
+
// The length we were told is the uncompressed one, and we do not know the
|
|
164
|
+
// compressed one until the stream ends.
|
|
165
|
+
delete headers["content-length"];
|
|
166
|
+
const vary = headers.vary;
|
|
167
|
+
if (!vary) {
|
|
168
|
+
headers.vary = "Accept-Encoding";
|
|
169
|
+
}
|
|
170
|
+
else if (!/\baccept-encoding\b/i.test(vary)) {
|
|
171
|
+
headers.vary = `${vary}, Accept-Encoding`;
|
|
172
|
+
}
|
|
173
|
+
return { ...head, headers };
|
|
174
|
+
}
|
|
175
|
+
/** See {@link ResponseSink.padEmptyBody}. */
|
|
176
|
+
function padEmptyBody() {
|
|
177
|
+
let wroteSomething = false;
|
|
178
|
+
return new node_stream_1.Transform({
|
|
179
|
+
transform(chunk, _encoding, callback) {
|
|
180
|
+
wroteSomething = true;
|
|
181
|
+
callback(null, chunk);
|
|
182
|
+
},
|
|
183
|
+
flush(callback) {
|
|
184
|
+
callback(null, wroteSomething ? undefined : " ");
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydW50aW1lL2h0dHAvc2luay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQStGQSxnQ0F5REM7QUFpQ0Qsa0NBc0JDO0FBL01EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVCRztBQUNILDZDQUFrRDtBQUNsRCxtREFBZ0Q7QUFDaEQseUNBQWtEO0FBa0NsRDs7OztHQUlHO0FBQ0gsTUFBTSxZQUFZLEdBQ2hCLDhGQUE4RixDQUFDO0FBRWpHOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFdkQsa0RBQWtEO0FBQ2xELE1BQU0sWUFBWSxHQUFHLHFDQUFxQyxDQUFDO0FBTzNEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFVBQVUsQ0FDeEIsR0FBd0IsRUFDeEIsR0FBdUIsRUFDdkIsSUFBa0IsRUFDbEIsT0FBb0I7SUFFcEIsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUMzQyxJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDbkIsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDMUIsMEVBQTBFO1FBQzFFLG9FQUFvRTtRQUNwRSxxRUFBcUU7UUFDckUsNEVBQTRFO1FBQzVFLG9FQUFvRTtRQUNwRSwwRUFBMEU7UUFDMUUsbUVBQW1FO1FBQ25FLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osT0FBTyxFQUFFLENBQUM7WUFDWixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQWtCLEVBQUUs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c0NvbnRlbnQiOlsiLyoqXG4gKiBDb25uZWN0aW5nIGEge0BsaW5rIFNoaW1TZXJ2ZXJSZXNwb25zZX0gdG8gdGhlIGJ5dGVzLW91dCBzaWRlIG9mIGEgc2hlbGwsIGFuZFxuICogdGhlIG9uZSB0aGluZyB0aGF0IGhhcyB0byBoYXBwZW4gb24gdGhlIHdheTogZ3ppcC5cbiAqXG4gKiBUaGlzIGxpdmVzIGluIHNoYXJlZCBydW50aW1lIGNvZGUgcmF0aGVyIHRoYW4gaW4gdGhlIExhbWJkYSBzaGVsbCBvbiBwdXJwb3NlLlxuICogTmVpdGhlciBtYW5hZ2VkIGxheWVyIGNhbiBjb21wcmVzcyBhICpzdHJlYW1lZCogcmVzcG9uc2U6XG4gKlxuICogLSBBUEkgR2F0ZXdheSdzIGBtaW5Db21wcmVzc2lvblNpemVgIGlzIHNldCAoYHNyYy9uZXh0anMtYXBpLnRzYCkgYnV0IGluZXJ0LFxuICogICBiZWNhdXNlIGNkay1uZXh0anMgYWxzbyBzZXRzIGBSZXNwb25zZVRyYW5zZmVyTW9kZS5TVFJFQU1gLCBhbmQgU1RSRUFNIGRyb3BzXG4gKiAgIGNvbnRlbnQgZW5jb2Rpbmcgb3V0cmlnaHQg4oCUIFwiSWYgeW91IHdhbnQgdG8gY29tcHJlc3MgeW91ciBpbnRlZ3JhdGlvblxuICogICByZXNwb25zZSwgZG8gdGhpcyBpbiB5b3VyIGludGVncmF0aW9uXCIuXG4gKiAtIENsb3VkRnJvbnQgcmVxdWlyZXMgdGhlIG9yaWdpbiB0byBzZW5kIGBDb250ZW50LUxlbmd0aGAsIHdoaWNoIGEgc3RyZWFtZWRcbiAqICAgcmVzcG9uc2UgYnkgZGVmaW5pdGlvbiBkb2VzIG5vdC4gSXQgc3RpbGwgY29tcHJlc3NlcyBub24tc3RyZWFtZWQgcmVzcG9uc2VzXG4gKiAgIGFuZCBTMyBhc3NldHMsIHNvIHRoZSBnYXAgaXMgZXhhY3RseSBzdHJlYW1lZCBIVE1MIGFuZCBSU0MgcGF5bG9hZHMg4oCUIHRoZVxuICogICBsYXJnZXN0IHRleHQgcmVzcG9uc2VzIHdlIHNlcnZlLlxuICpcbiAqIFVudGlsIHRoZSBjb250YWluZXIgcGF0aCB3YXMgZHJvcHBlZCwgTGFtYmRhIFdlYiBBZGFwdGVyIGRpZCB0aGlzIGZvciB1cywgd2hpY2hcbiAqIGlzIHdoeSBub3RoaW5nIGluIHRoZSBvbGQgY29kZSBtZW50aW9ucyBpdC4gKipEb24ndCBcImZpeFwiIHRoZSBBUEkgR2F0ZXdheSBvclxuICogQ2xvdWRGcm9udCBzZXR0aW5ncyBleHBlY3RpbmcgdGhlbSB0byB0YWtlIG92ZXIuKipcbiAqXG4gKiBnemlwIHJhdGhlciB0aGFuIGJyb3RsaTogYnJvdGxpJ3Mgc3RyZWFtaW5nIHRocm91Z2hwdXQgYXQgZGVmYXVsdCBxdWFsaXR5IGlzXG4gKiBwb29yLCBhbmQgQ2xvdWRGcm9udCBwcmVmZXJzIGBicmAgb25seSB3aGVuIHRoZSBvcmlnaW4gZGlkbid0IGFscmVhZHkgZW5jb2RlIOKAlFxuICogd2hpY2ggc3RvcHMgYXBwbHlpbmcgdGhlIG1vbWVudCB3ZSBzZXQgYGNvbnRlbnQtZW5jb2RpbmdgIG91cnNlbHZlcy5cbiAqL1xuaW1wb3J0IHsgVHJhbnNmb3JtLCBXcml0YWJsZSB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuaW1wb3J0IHsgcGlwZWxpbmUgfSBmcm9tIFwibm9kZTpzdHJlYW0vcHJvbWlzZXNcIjtcbmltcG9ydCB7IGNvbnN0YW50cywgY3JlYXRlR3ppcCB9IGZyb20gXCJub2RlOnpsaWJcIjtcbmltcG9ydCB0eXBlIHsgU2hpbUluY29taW5nTWVzc2FnZSB9IGZyb20gXCIuL3JlcXVlc3RcIjtcbmltcG9ydCB7IFJlc3BvbnNlSGVhZCwgU2hpbVNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIi4vcmVzcG9uc2VcIjtcblxuZXhwb3J0IGludGVyZmFjZSBSZXNwb25zZVNpbmsge1xuICAvKipcbiAgICogU2V0IGJ5IHRoZSBMYW1iZGEgc2luaywgZm9yIGJvdGggaW50ZWdyYXRpb25zOiBhIHN0cmVhbWVkIExhbWJkYSByZXNwb25zZVxuICAgKiB3aXRoIHplcm8gcGF5bG9hZCBieXRlcyBhZnRlciB0aGUgbWV0YWRhdGEgZGVsaW1pdGVyIGlzIG5vdCByZWNvZ25pemVkIGFzIGFcbiAgICogbWV0YWRhdGEgcmVzcG9uc2UgYXQgYWxsLCBzbyBhIHNpbmdsZSBzcGFjZSBpcyB3cml0dGVuIGluc3RlYWQgb2Ygbm90aGluZy5cbiAgICpcbiAgICogQVBJIEdhdGV3YXkgYW5zd2VycyA1MDIuIEEgRnVuY3Rpb24gVVJMIGlzIHdvcnNlIGJlY2F1c2UgaXQgbG9va3MgbGlrZSBpdFxuICAgKiB3b3JrZWQ6IHRoZSBwcmVsdWRlIGlzIGRpc2NhcmRlZCBhbmQgdGhlIHJlc3BvbnNlIGFycml2ZXMgYXMgYSBiYXJlXG4gICAqIGAyMDAgYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtYCB3aXRoIGFuIGVtcHR5IGJvZHksIG5vbmUgb2YgdGhlIGFwcCdzIGhlYWRlcnMsXG4gICAqIGFuZCBhbiBIVFRQLzIgc3RyZWFtIHRoYXQgZG9lcyBub3QgY2xvc2UgY2xlYW5seSDigJQgd2hhdGV2ZXIgdGhlIHJlYWwgc3RhdHVzXG4gICAqIHdhcy4gTWVhc3VyZWQgYWdhaW5zdCBhIGBOZXh0anNHbG9iYWxGdW5jdGlvbnNgIGRlcGxveW1lbnQ6IGBIRUFEYCBvbiBhIDQwNFxuICAgKiBwYWdlIGFuc3dlcmVkIGAyMDBgLCBhbmQgYSBzZXJ2ZXIgYWN0aW9uIHdob3NlIHJlcGx5IGlzIGVtcHR5IChhbiBhY3Rpb24gdGhhdFxuICAgKiBvbmx5IGByZWRpcmVjdCgpYHMsIHdoaWNoIE5leHQuanMgYW5zd2VycyB3aXRoIGB4LWFjdGlvbi1yZWRpcmVjdGAgYW5kIG5vXG4gICAqIGJvZHkpIGxvc3QgdGhlIHJlZGlyZWN0IGhlYWRlciBhbmQgc28gbmV2ZXIgbmF2aWdhdGVkLlxuICAgKlxuICAgKiBUaGUgcHJlLWFkYXB0ZXIgaW1hZ2UgaGFuZGxlciBjYXJyaWVkIHRoZSBzYW1lIHdvcmthcm91bmQgZm9yIDMwNHMuIFJGQyA5MTEwXG4gICAqIGZvcmJpZHMgYSBib2R5IG9uIDIwNC8zMDQsIGFuZCBhIHNwYWNlIHRlY2huaWNhbGx5IHZpb2xhdGVzIHRoYXQsIGJ1dCBsb3NpbmdcbiAgICogdGhlIHN0YXR1cyBlbnRpcmVseSBpcyB0aGUgd29yc2UgZmFpbHVyZSDigJQgYW5kIG9uIHRoZSBDbG91ZEZyb250IHBhdGggYVxuICAgKiBjb25kaXRpb25hbCByZXF1ZXN0IGNhbm5vdCByZWFjaCB0aGUgb3JpZ2luIGFueXdheSwgYmVjYXVzZSBgaWYtbm9uZS1tYXRjaGBcbiAgICogaXMgbm90IGluIHRoZSBkeW5hbWljIGNhY2hlIHBvbGljeSdzIGhlYWRlciBhbGxvd2xpc3QuIFRoZSBjb250YWluZXIgc2lua1xuICAgKiB3cml0ZXMgdG8gYSByZWFsIGBTZXJ2ZXJSZXNwb25zZWAgYW5kIGRvZXMgbm90IHNldCB0aGlzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGFkRW1wdHlCb2R5PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIENhbGxlZCBleGFjdGx5IG9uY2UsIGJlZm9yZSBhbnkgYm9keSBieXRlLCB3aXRoIHRoZSBmaW5hbCBoZWFkLiBSZXR1cm5zIHRoZVxuICAgKiBzdHJlYW0gdGhlIGJvZHkgaXMgd3JpdHRlbiB0bzsge0BsaW5rIHBpcGVUb1Npbmt9IGVuZHMgaXQuXG4gICAqL1xuICBiZWdpbihoZWFkOiBSZXNwb25zZUhlYWQpOiBXcml0YWJsZTtcbn1cblxuLyoqXG4gKiBDb250ZW50IHR5cGVzIHdvcnRoIGNvbXByZXNzaW5nLiBFdmVyeXRoaW5nIE5leHQgc3RyZWFtcyBhcyBIVE1MIG9yIGFuIFJTQ1xuICogcGF5bG9hZCBpcyBgdGV4dC8qYDsgaW1hZ2VzIGFuZCBmb250cyBhcmUgYWxyZWFkeSBjb21wcmVzc2VkLCBhbmQgZ3ppcHBpbmcgYW5cbiAqIG9wdGltaXplZCBBVklGIGp1c3QgYnVybnMgQ1BVLlxuICovXG5jb25zdCBDT01QUkVTU0lCTEUgPVxuICAvXig/OnRleHRcXC98YXBwbGljYXRpb25cXC8oPzpqc29ufGphdmFzY3JpcHR8eG1sfG1hbmlmZXN0fHJzc1xcK3htbHxhdG9tXFwreG1sKXxpbWFnZVxcL3N2Z1xcK3htbCkvO1xuXG4vKipcbiAqIFN0YXR1c2VzIHdob3NlIGJvZHkgbXVzdCBub3QgYmUgY29tcHJlc3NlZDogMjA0IGFuZCAzMDQgaGF2ZSBub25lLCBhbmQgYSAyMDYnc1xuICogYm9keSBpcyBhIGJ5dGUgcmFuZ2Ugb2YgdGhlICp1bmNvbXByZXNzZWQqIHJlcHJlc2VudGF0aW9uLlxuICpcbiAqIDIwNiBpcyByZWFjaGFibGUg4oCUIGBzZXJ2ZVN0YXRpY0ZpbGVgIGlzIGBzZW5kYCB1bmRlcm5lYXRoLCB3aGljaCBhZHZlcnRpc2VzXG4gKiBgQWNjZXB0LVJhbmdlczogYnl0ZXNgIGFuZCBob25vcnMgYFJhbmdlYCBvbiB0aGUgc3RhdGljIEhUTUwgdGhlIHJ1bnRpbWUgc2VydmVzXG4gKiBpdHNlbGYuIEd6aXBwaW5nIG9uZSBwcm9kdWNlZCBhIHJlc3BvbnNlIHdob3NlIGBDb250ZW50LVJhbmdlYCBzdGlsbCBkZXNjcmliZWRcbiAqIHRoZSB1bmNvbXByZXNzZWQgc2xpY2UgKGB3aXRoR3ppcEhlYWRlcnNgIGRyb3BzIGBjb250ZW50LWxlbmd0aGAgYnV0IGNhbm5vdFxuICogcmVzdGF0ZSBhIHJhbmdlKSwgc28gdGhlIGNsaWVudCBnb3QgYnl0ZXMgdGhhdCBkaWQgbm90IG1hdGNoIHdoYXQgaXQgYXNrZWQgZm9yLlxuICovXG5jb25zdCBVTkNPTVBSRVNTQUJMRV9TVEFUVVMgPSBuZXcgU2V0KFsyMDQsIDIwNiwgMzA0XSk7XG5cbi8qKiBgY29tcHJlc3Npb25gJ3Mgb3duIHRlc3QgZm9yIHRoZSBkaXJlY3RpdmUuICovXG5jb25zdCBOT19UUkFOU0ZPUk0gPSAvKD86XnwsKVxccyo/bm8tdHJhbnNmb3JtXFxzKj8oPzosfCQpL2k7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGlwZU9wdGlvbnMge1xuICAvKiogYG5leHQuY29uZmlnYCBgY29tcHJlc3NgLiAqL1xuICByZWFkb25seSBjb21wcmVzczogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBQaXBlIGByZXNgIGludG8gYHNpbmtgLCBnemlwcGluZyB3aGVuIHRoYXQgaXMgYm90aCBhbGxvd2VkIGFuZCB1c2VmdWwuXG4gKlxuICogUmVzb2x2ZXMgd2hlbiB0aGUgc2luaydzIHN0cmVhbSBoYXMgZmluaXNoZWQsIHdoaWNoIGZvciBMYW1iZGEgaXMgdGhlIHBvaW50IHRoZVxuICogY2xpZW50IGhhcyB0aGUgd2hvbGUgcmVzcG9uc2UuIE11c3QgYmUgY2FsbGVkICpiZWZvcmUqIGFueXRoaW5nIHdyaXRlcyB0b1xuICogYHJlc2AsIGJlY2F1c2UgaXQgc3Vic2NyaWJlcyB0byB0aGUgb25lLXNob3QgYFwiaGVhZFwiYCBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBpcGVUb1NpbmsoXG4gIHJlcTogU2hpbUluY29taW5nTWVzc2FnZSxcbiAgcmVzOiBTaGltU2VydmVyUmVzcG9uc2UsXG4gIHNpbms6IFJlc3BvbnNlU2luayxcbiAgb3B0aW9uczogUGlwZU9wdGlvbnMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgcGlwaW5nID0gZmFsc2U7XG4gICAgcmVzLm9uY2UoXCJlcnJvclwiLCByZWplY3QpO1xuICAgIC8vIERlc3Ryb3llZCBiZWZvcmUgdGhlIGhlYWQgd2VudCBvdXQsIGFuZCB3aXRob3V0IGFuIGVycm9yOiBhIGNsaWVudCB0aGF0XG4gICAgLy8gZGlzY29ubmVjdGVkIGJlZm9yZSB0aGUgZmlyc3QgYnl0ZSwgd2hpY2ggYGhhbmRsZSgpYCBhbnN3ZXJzIHdpdGhcbiAgICAvLyBgcmVzLmRlc3Ryb3koKWAuIGBUcmFuc2Zvcm0uZGVzdHJveSgpYCB3aXRoIG5vIGFyZ3VtZW50IGVtaXRzIG9ubHlcbiAgICAvLyBgXCJjbG9zZVwiYCwgYW5kIHRoZSBwaXBlbGluZSBiZWxvdyBuZXZlciBzdGFydGVkLCBzbyBub3RoaW5nIGVsc2UgY2FuIGV2ZXJcbiAgICAvLyBzZXR0bGUgdGhpcyBwcm9taXNlIOKAlCBsZWF2aW5nIGBoYW5kbGUoKWAgYXdhaXRpbmcgaXQgZm9yZXZlciwgaXRzXG4gICAgLy8gYHdhaXRVbnRpbGAgd29yayAoSVNSIHJldmFsaWRhdGlvbiwgY2FjaGUgd3JpdGVzKSBuZXZlciBmbHVzaGVkIGFuZCB0aGVcbiAgICAvLyBpbi1mbGlnaHQgcmVuZGVyJ3MgY2xvc3VyZSByZXRhaW5lZCBmb3IgdGhlIGxpZmUgb2YgdGhlIHByb2Nlc3MuXG4gICAgcmVzLm9uY2UoXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgICBpZiAoIXBpcGluZykge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVzLm9uY2UoXCJoZWFkXCIsIChoZWFkOiBSZXNwb25zZUhlYWQpID0+IHtcbiAgICAgIHBpcGluZyA9IHRydWU7XG4gICAgICBjb25zdCBzdGFnZXM6IEFycmF5PFRyYW5zZm9ybSB8IFdyaXRhYmxlPiA9IFtdO1xuXG4gICAgICBjb25zdCBnemlwID0gc2hvdWxkR3ppcChyZXEsIHJlcywgaGVhZCwgb3B0aW9ucyk7XG4gICAgICBpZiAoZ3ppcCkge1xuICAgICAgICBjb25zdCBjb21wcmVzc29yID0gY3JlYXRlR3ppcCgpO1xuICAgICAgICAvLyBOZXh0LmpzIGNhbGxzIGByZXMuZmx1c2goKWAgYWZ0ZXIgZWFjaCBjaHVuayBpdCB3cml0ZXNcbiAgICAgICAgLy8gKGBuZXh0L2Rpc3Qvc2VydmVyL3BpcGUtcmVhZGFibGUuanNgKTsgd2l0aG91dCBmb3J3YXJkaW5nIGl0LCBzdHJlYW1lZFxuICAgICAgICAvLyBIVE1MIHNpdHMgaW4gemxpYidzIGJ1ZmZlciBhbmQgdGhlIHJlc3BvbnNlIGFycml2ZXMgYWxsIGF0IG9uY2UuXG4gICAgICAgIHJlcy5mbHVzaCA9ICgpID0+IGNvbXByZXNzb3IuZmx1c2goY29uc3RhbnRzLlpfU1lOQ19GTFVTSCk7XG4gICAgICAgIHN0YWdlcy5wdXNoKGNvbXByZXNzb3IpO1xuICAgICAgfVxuICAgICAgaWYgKHNpbmsucGFkRW1wdHlCb2R5KSB7XG4gICAgICAgIHN0YWdlcy5wdXNoKHBhZEVtcHR5Qm9keSgpKTtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHN0YWdlcy5wdXNoKHNpbmsuYmVnaW4oZ3ppcCA/IHdpdGhHemlwSGVhZGVycyhoZWFkKSA6IGhlYWQpKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIFRoaXMgcnVucyBpbnNpZGUgd2hpY2hldmVyIGByZXNgIGNhbGwgZmx1c2hlZCB0aGUgaGVhZCDigJQgdXN1YWxseSBhXG4gICAgICAgIC8vIGB3cml0ZSgpYCBmcm9tIGRlZXAgaW5zaWRlIE5leHQuanMg4oCUIHNvIGFuIGVzY2FwaW5nIHRocm93IGxhbmRzIHRoZXJlLFxuICAgICAgICAvLyB0aGUgcGlwZWxpbmUgYmVsb3cgbmV2ZXIgc3RhcnRzLCBhbmQgbm90aGluZyB3b3VsZCBzZXR0bGUgdGhpc1xuICAgICAgICAvLyBwcm9taXNlOiBgaGFuZGxlKClgIHdvdWxkIGhhbmcuIEEgc2luaydzIGB3cml0ZUhlYWRgIHJlamVjdGluZyBhXG4gICAgICAgIC8vIGhlYWRlciB2YWx1ZSBpcyBob3cgaXQgaGFwcGVucy4gRGVzdHJveWluZyBgcmVzYCBpcyB3aGF0IHN0b3BzIHRoZVxuICAgICAgICAvLyB3cml0ZXI7IHRoZSBgXCJlcnJvclwiYCB0aGF0IGVtaXRzIGlzIGEgbm8tb3AgYWZ0ZXIgdGhlIGByZWplY3RgLlxuICAgICAgICBmb3IgKGNvbnN0IHN0YWdlIG9mIHN0YWdlcykge1xuICAgICAgICAgIHN0YWdlLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICByZXMuZGVzdHJveShlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHBpcGVsaW5lKHJlcywgLi4uKHN0YWdlcyBhcyBbV3JpdGFibGVdKSkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2hvdWxkR3ppcChcbiAgcmVxOiBTaGltSW5jb21pbmdNZXNzYWdlLFxuICByZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSxcbiAgaGVhZDogUmVzcG9uc2VIZWFkLFxuICBvcHRpb25zOiBQaXBlT3B0aW9ucyxcbik6IGJvb2xlYW4ge1xuICBpZiAoIW9wdGlvbnMuY29tcHJlc3MpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHJlcS5tZXRob2QgPT09IFwiSEVBRFwiIHx8IFVOQ09NUFJFU1NBQkxFX1NUQVRVUy5oYXMoaGVhZC5zdGF0dXNDb2RlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBOZXh0LmpzIGVuY29kZXMgc29tZSByZXNwb25zZXMgaXRzZWxmOyBkb3VibGUtZW5jb2RpbmcgaXMgbm90IGEgdGhpbmcuXG4gIGlmIChyZXMuaGFzSGVhZGVyKFwiY29udGVudC1lbmNvZGluZ1wiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoIUNPTVBSRVNTSUJMRS50ZXN0KGhlYWQuaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSA/PyBcIlwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBUaGUgcmVzcG9uc2UncyBvcHQtb3V0LCB3aGljaCBgbmV4dCBzdGFydGAncyBgY29tcHJlc3Npb25gIGhvbm9ycyB0b286IGFuXG4gIC8vIFNTRSBzdHJlYW0gc2V0cyBpdCBzbyB0aGF0IG5vdGhpbmcgYnVmZmVycyBpdHMgZXZlbnRzLlxuICBpZiAoTk9fVFJBTlNGT1JNLnRlc3QoaGVhZC5oZWFkZXJzW1wiY2FjaGUtY29udHJvbFwiXSA/PyBcIlwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gYWNjZXB0c0d6aXAocmVxLmhlYWRlcnNbXCJhY2NlcHQtZW5jb2RpbmdcIl0pO1xufVxuXG4vKipcbiAqIEEgYHE9MGAgb24gZ3ppcCBpcyBhIHJlZnVzYWwsIGFuZCBib3RoIGAqYCBmb3JtcyBoYXZlIHRvIGJlIGhvbm9yZWQsIHNvIHRoaXNcbiAqIHBhcnNlcyByYXRoZXIgdGhhbiBzdWJzdHJpbmctbWF0Y2hpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhY2NlcHRzR3ppcChoZWFkZXI6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIGNvbnN0IHZhbHVlID0gQXJyYXkuaXNBcnJheShoZWFkZXIpID8gaGVhZGVyLmpvaW4oXCIsXCIpIDogaGVhZGVyO1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGxldCB3aWxkY2FyZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIHZhbHVlLnNwbGl0KFwiLFwiKSkge1xuICAgIGNvbnN0IFtyYXdOYW1lLCAuLi5wYXJhbXNdID0gcGFydC5zcGxpdChcIjtcIik7XG4gICAgY29uc3QgbmFtZSA9IHJhd05hbWUudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKG5hbWUgIT09IFwiZ3ppcFwiICYmIG5hbWUgIT09IFwiKlwiKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgcSA9IHBhcmFtc1xuICAgICAgLm1hcCgocCkgPT4gcC50cmltKCkudG9Mb3dlckNhc2UoKSlcbiAgICAgIC5maW5kKChwKSA9PiBwLnN0YXJ0c1dpdGgoXCJxPVwiKSk7XG4gICAgY29uc3QgYWNjZXB0ZWQgPSBxID09PSB1bmRlZmluZWQgfHwgTnVtYmVyKHEuc2xpY2UoMikpID4gMDtcbiAgICBpZiAobmFtZSA9PT0gXCJnemlwXCIpIHtcbiAgICAgIHJldHVybiBhY2NlcHRlZDtcbiAgICB9XG4gICAgd2lsZGNhcmQgPSBhY2NlcHRlZDtcbiAgfVxuICByZXR1cm4gd2lsZGNhcmQgPz8gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHdpdGhHemlwSGVhZGVycyhoZWFkOiBSZXNwb25zZUhlYWQpOiBSZXNwb25zZUhlYWQge1xuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIC4uLmhlYWQuaGVhZGVycyxcbiAgICBcImNvbnRlbnQtZW5jb2RpbmdcIjogXCJnemlwXCIsXG4gIH07XG4gIC8vIFRoZSBsZW5ndGggd2Ugd2VyZSB0b2xkIGlzIHRoZSB1bmNvbXByZXNzZWQgb25lLCBhbmQgd2UgZG8gbm90IGtub3cgdGhlXG4gIC8vIGNvbXByZXNzZWQgb25lIHVudGlsIHRoZSBzdHJlYW0gZW5kcy5cbiAgZGVsZXRlIGhlYWRlcnNbXCJjb250ZW50LWxlbmd0aFwiXTtcbiAgY29uc3QgdmFyeSA9IGhlYWRlcnMudmFyeTtcbiAgaWYgKCF2YXJ5KSB7XG4gICAgaGVhZGVycy52YXJ5ID0gXCJBY2NlcHQtRW5jb2RpbmdcIjtcbiAgfSBlbHNlIGlmICghL1xcYmFjY2VwdC1lbmNvZGluZ1xcYi9pLnRlc3QodmFyeSkpIHtcbiAgICBoZWFkZXJzLnZhcnkgPSBgJHt2YXJ5fSwgQWNjZXB0LUVuY29kaW5nYDtcbiAgfVxuICByZXR1cm4geyAuLi5oZWFkLCBoZWFkZXJzIH07XG59XG5cbi8qKiBTZWUge0BsaW5rIFJlc3BvbnNlU2luay5wYWRFbXB0eUJvZHl9LiAqL1xuZnVuY3Rpb24gcGFkRW1wdHlCb2R5KCk6IFRyYW5zZm9ybSB7XG4gIGxldCB3cm90ZVNvbWV0aGluZyA9IGZhbHNlO1xuICByZXR1cm4gbmV3IFRyYW5zZm9ybSh7XG4gICAgdHJhbnNmb3JtKGNodW5rLCBfZW5jb2RpbmcsIGNhbGxiYWNrKSB7XG4gICAgICB3cm90ZVNvbWV0aGluZyA9IHRydWU7XG4gICAgICBjYWxsYmFjayhudWxsLCBjaHVuayk7XG4gICAgfSxcbiAgICBmbHVzaChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2sobnVsbCwgd3JvdGVTb21ldGhpbmcgPyB1bmRlZmluZWQgOiBcIiBcIik7XG4gICAgfSxcbiAgfSk7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_stream_1 = require("node:stream");
|
|
4
|
+
const node_zlib_1 = require("node:zlib");
|
|
5
|
+
const request_1 = require("./request");
|
|
6
|
+
const response_1 = require("./response");
|
|
7
|
+
const sink_1 = require("./sink");
|
|
8
|
+
class CollectingSink {
|
|
9
|
+
padEmptyBody;
|
|
10
|
+
head;
|
|
11
|
+
chunks = [];
|
|
12
|
+
constructor(padEmptyBody = false) {
|
|
13
|
+
this.padEmptyBody = padEmptyBody;
|
|
14
|
+
}
|
|
15
|
+
begin(head) {
|
|
16
|
+
this.head = head;
|
|
17
|
+
const chunks = this.chunks;
|
|
18
|
+
return new node_stream_1.Writable({
|
|
19
|
+
write(chunk, _encoding, callback) {
|
|
20
|
+
chunks.push(Buffer.from(chunk));
|
|
21
|
+
callback();
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
get body() {
|
|
26
|
+
return Buffer.concat(this.chunks);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function requestWith(headers, method = "GET") {
|
|
30
|
+
return new request_1.ShimIncomingMessage({ method, url: "/", headers });
|
|
31
|
+
}
|
|
32
|
+
/** Runs one response through the sink and resolves once the sink is finished. */
|
|
33
|
+
async function run(write, options = {}) {
|
|
34
|
+
const req = options.req ?? requestWith({ "accept-encoding": "gzip" });
|
|
35
|
+
const res = new response_1.ShimServerResponse();
|
|
36
|
+
const sink = new CollectingSink(options.padEmptyBody);
|
|
37
|
+
const done = (0, sink_1.pipeToSink)(req, res, sink, {
|
|
38
|
+
compress: options.compress ?? true,
|
|
39
|
+
});
|
|
40
|
+
write(res);
|
|
41
|
+
await done;
|
|
42
|
+
return sink;
|
|
43
|
+
}
|
|
44
|
+
describe("pipeToSink compression", () => {
|
|
45
|
+
it("gzips compressible content when the client accepts it", async () => {
|
|
46
|
+
const sink = await run((res) => {
|
|
47
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
48
|
+
res.setHeader("Content-Length", "13");
|
|
49
|
+
res.end("<p>hello</p>");
|
|
50
|
+
});
|
|
51
|
+
expect(sink.head?.headers["content-encoding"]).toBe("gzip");
|
|
52
|
+
// The length we were told is the uncompressed one and the compressed one is
|
|
53
|
+
// not known until the stream ends.
|
|
54
|
+
expect(sink.head?.headers["content-length"]).toBeUndefined();
|
|
55
|
+
expect(sink.head?.headers.vary).toBe("Accept-Encoding");
|
|
56
|
+
expect((0, node_zlib_1.gunzipSync)(sink.body).toString("utf-8")).toBe("<p>hello</p>");
|
|
57
|
+
});
|
|
58
|
+
it("appends to an existing vary rather than replacing it", async () => {
|
|
59
|
+
const sink = await run((res) => {
|
|
60
|
+
res.setHeader("Content-Type", "text/html");
|
|
61
|
+
res.setHeader("Vary", "Cookie");
|
|
62
|
+
res.end("x");
|
|
63
|
+
});
|
|
64
|
+
expect(sink.head?.headers.vary).toBe("Cookie, Accept-Encoding");
|
|
65
|
+
});
|
|
66
|
+
it("forwards res.flush() to the compressor so streamed HTML is not buffered", async () => {
|
|
67
|
+
const seen = [];
|
|
68
|
+
const sink = await run((res) => {
|
|
69
|
+
res.setHeader("Content-Type", "text/html");
|
|
70
|
+
res.write("<html>");
|
|
71
|
+
// Next.js does exactly this after every chunk (`pipe-readable.js`).
|
|
72
|
+
res.flush?.();
|
|
73
|
+
seen.push(1);
|
|
74
|
+
res.end("</html>");
|
|
75
|
+
});
|
|
76
|
+
expect(seen).toEqual([1]);
|
|
77
|
+
expect((0, node_zlib_1.gunzipSync)(sink.body).toString("utf-8")).toBe("<html></html>");
|
|
78
|
+
});
|
|
79
|
+
it.each([
|
|
80
|
+
["an incompressible content type", { "content-type": "image/avif" }],
|
|
81
|
+
["an already-encoded body", { "content-encoding": "br" }],
|
|
82
|
+
[
|
|
83
|
+
"a response that opts out with no-transform",
|
|
84
|
+
{
|
|
85
|
+
"content-type": "text/event-stream",
|
|
86
|
+
"cache-control": "no-cache, no-transform",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
])("does not gzip %s", async (_name, headers) => {
|
|
90
|
+
const sink = await run((res) => {
|
|
91
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
92
|
+
res.setHeader(name, value);
|
|
93
|
+
}
|
|
94
|
+
res.end("body");
|
|
95
|
+
});
|
|
96
|
+
expect(sink.head?.headers["content-encoding"]).not.toBe("gzip");
|
|
97
|
+
expect(sink.body.toString("utf-8")).toBe("body");
|
|
98
|
+
});
|
|
99
|
+
it("does not gzip a 206, whose body is a range of the stored bytes", async () => {
|
|
100
|
+
// The one uncompressable status that carries a body. `content-range` counts
|
|
101
|
+
// bytes of the representation the client asked for, so gzipping the slice
|
|
102
|
+
// makes the range meaningless - and a client stitching ranges together
|
|
103
|
+
// (video, a resumed download) cannot use it.
|
|
104
|
+
const sink = await run((res) => {
|
|
105
|
+
res.statusCode = 206;
|
|
106
|
+
res.setHeader("Content-Type", "text/plain");
|
|
107
|
+
res.setHeader("Content-Range", "bytes 0-3/1000");
|
|
108
|
+
res.end("body");
|
|
109
|
+
});
|
|
110
|
+
expect(sink.head?.headers["content-encoding"]).toBeUndefined();
|
|
111
|
+
expect(sink.body.toString("utf-8")).toBe("body");
|
|
112
|
+
});
|
|
113
|
+
it("does not gzip when the client did not offer it", async () => {
|
|
114
|
+
const sink = await run((res) => {
|
|
115
|
+
res.setHeader("Content-Type", "text/html");
|
|
116
|
+
res.end("body");
|
|
117
|
+
}, { req: requestWith({}) });
|
|
118
|
+
expect(sink.head?.headers["content-encoding"]).toBeUndefined();
|
|
119
|
+
expect(sink.body.toString("utf-8")).toBe("body");
|
|
120
|
+
});
|
|
121
|
+
it("does not gzip when next.config sets compress: false", async () => {
|
|
122
|
+
const sink = await run((res) => {
|
|
123
|
+
res.setHeader("Content-Type", "text/html");
|
|
124
|
+
res.end("body");
|
|
125
|
+
}, { compress: false });
|
|
126
|
+
expect(sink.head?.headers["content-encoding"]).toBeUndefined();
|
|
127
|
+
});
|
|
128
|
+
it.each([
|
|
129
|
+
["a HEAD request", { method: "HEAD", status: 200 }],
|
|
130
|
+
["a 204", { method: "GET", status: 204 }],
|
|
131
|
+
["a 304", { method: "GET", status: 304 }],
|
|
132
|
+
])("does not gzip %s", async (_name, { method, status }) => {
|
|
133
|
+
const sink = await run((res) => {
|
|
134
|
+
res.statusCode = status;
|
|
135
|
+
res.setHeader("Content-Type", "text/html");
|
|
136
|
+
res.end();
|
|
137
|
+
}, { req: requestWith({ "accept-encoding": "gzip" }, method) });
|
|
138
|
+
expect(sink.head?.headers["content-encoding"]).toBeUndefined();
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe("pipeToSink empty-body padding", () => {
|
|
142
|
+
it("writes a single space when the sink asks for it", async () => {
|
|
143
|
+
const sink = await run((res) => {
|
|
144
|
+
res.statusCode = 304;
|
|
145
|
+
res.end();
|
|
146
|
+
}, { padEmptyBody: true });
|
|
147
|
+
// Zero payload bytes after the prelude makes API Gateway answer 502, and
|
|
148
|
+
// makes a Function URL drop the prelude and answer a bare
|
|
149
|
+
// `200 application/octet-stream`.
|
|
150
|
+
expect(sink.body.toString("utf-8")).toBe(" ");
|
|
151
|
+
});
|
|
152
|
+
it("pads a HEAD response, whose body is empty by definition", async () => {
|
|
153
|
+
const sink = await run((res) => {
|
|
154
|
+
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
155
|
+
res.setHeader("content-length", "5798");
|
|
156
|
+
res.end();
|
|
157
|
+
}, {
|
|
158
|
+
padEmptyBody: true,
|
|
159
|
+
req: requestWith({ "accept-encoding": "gzip" }, "HEAD"),
|
|
160
|
+
});
|
|
161
|
+
expect(sink.body.toString("utf-8")).toBe(" ");
|
|
162
|
+
// The head still describes what a GET would return; the padding byte is not
|
|
163
|
+
// a body and the integration overwrites `content-length` with 0.
|
|
164
|
+
expect(sink.head?.headers["content-length"]).toBe("5798");
|
|
165
|
+
});
|
|
166
|
+
it("leaves a non-empty body alone", async () => {
|
|
167
|
+
const sink = await run((res) => res.end("real"), {
|
|
168
|
+
padEmptyBody: true,
|
|
169
|
+
compress: false,
|
|
170
|
+
});
|
|
171
|
+
expect(sink.body.toString("utf-8")).toBe("real");
|
|
172
|
+
});
|
|
173
|
+
it("sends nothing for an empty body when the sink does not ask", async () => {
|
|
174
|
+
const sink = await run((res) => {
|
|
175
|
+
res.statusCode = 304;
|
|
176
|
+
res.end();
|
|
177
|
+
});
|
|
178
|
+
expect(sink.body).toHaveLength(0);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe("pipeToSink lifecycle", () => {
|
|
182
|
+
/**
|
|
183
|
+
* `handle()` awaits this promise before it flushes `waitUntil` work — ISR
|
|
184
|
+
* revalidation, cache writes — and before the request's closures can be
|
|
185
|
+
* collected. A client that disconnects before the first byte destroys the
|
|
186
|
+
* response without an error, which emits only `"close"`: the pipeline never
|
|
187
|
+
* started, so nothing else can settle the promise and the await never returned.
|
|
188
|
+
*/
|
|
189
|
+
it("settles when the response is destroyed before the head goes out", async () => {
|
|
190
|
+
const req = requestWith({});
|
|
191
|
+
const res = new response_1.ShimServerResponse();
|
|
192
|
+
const done = (0, sink_1.pipeToSink)(req, res, new CollectingSink(), {
|
|
193
|
+
compress: true,
|
|
194
|
+
});
|
|
195
|
+
res.destroy();
|
|
196
|
+
await expect(done).resolves.toBeUndefined();
|
|
197
|
+
});
|
|
198
|
+
// The normal path has to keep settling on the pipeline, not on `"close"`: the
|
|
199
|
+
// body must be fully flushed into the sink by the time this resolves.
|
|
200
|
+
it("still settles on the pipeline once the head has gone out", async () => {
|
|
201
|
+
const sink = await run((res) => {
|
|
202
|
+
res.setHeader("content-type", "text/plain");
|
|
203
|
+
res.end("body");
|
|
204
|
+
}, { compress: false });
|
|
205
|
+
expect(sink.body.toString()).toBe("body");
|
|
206
|
+
});
|
|
207
|
+
it("rejects when the response errors", async () => {
|
|
208
|
+
const req = requestWith({});
|
|
209
|
+
const res = new response_1.ShimServerResponse();
|
|
210
|
+
const done = (0, sink_1.pipeToSink)(req, res, new CollectingSink(), {
|
|
211
|
+
compress: true,
|
|
212
|
+
});
|
|
213
|
+
res.destroy(new Error("boom"));
|
|
214
|
+
await expect(done).rejects.toThrow("boom");
|
|
215
|
+
});
|
|
216
|
+
// A sink that cannot take the head — `writeHead` rejecting a header value is
|
|
217
|
+
// the real case — throws from inside the `"head"` listener, where nothing
|
|
218
|
+
// else would catch it and the pipeline never starts.
|
|
219
|
+
it.each([
|
|
220
|
+
["writes a body", (res) => res.end("body")],
|
|
221
|
+
["ends empty", (res) => res.end()],
|
|
222
|
+
["flushes its head first", (res) => res.writeHead(200)],
|
|
223
|
+
])("rejects and destroys the response when begin() throws and the response %s", async (_name, write) => {
|
|
224
|
+
const req = requestWith({});
|
|
225
|
+
const res = new response_1.ShimServerResponse();
|
|
226
|
+
const done = (0, sink_1.pipeToSink)(req, res, {
|
|
227
|
+
begin() {
|
|
228
|
+
throw new Error("bad head");
|
|
229
|
+
},
|
|
230
|
+
}, { compress: false });
|
|
231
|
+
write(res);
|
|
232
|
+
await expect(done).rejects.toThrow("bad head");
|
|
233
|
+
expect(res.destroyed).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
describe("acceptsGzip", () => {
|
|
237
|
+
it.each([
|
|
238
|
+
["gzip", true],
|
|
239
|
+
["gzip, deflate, br", true],
|
|
240
|
+
["GZIP;q=0.5", true],
|
|
241
|
+
["gzip;q=0", false],
|
|
242
|
+
["*", true],
|
|
243
|
+
["*;q=0", false],
|
|
244
|
+
// An explicit gzip preference wins over the wildcard, in either order.
|
|
245
|
+
["*;q=0, gzip", true],
|
|
246
|
+
["gzip;q=0, *", false],
|
|
247
|
+
["br, deflate", false],
|
|
248
|
+
["", false],
|
|
249
|
+
[undefined, false],
|
|
250
|
+
])("%s → %s", (header, expected) => {
|
|
251
|
+
expect((0, sink_1.acceptsGzip)(header)).toBe(expected);
|
|
252
|
+
});
|
|
253
|
+
it("joins a repeated header before parsing", () => {
|
|
254
|
+
expect((0, sink_1.acceptsGzip)(["br", "gzip"])).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luay50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bnRpbWUvaHR0cC9zaW5rLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2Q0FBdUM7QUFDdkMseUNBQXVDO0FBQ3ZDLHVDQUFnRDtBQUNoRCx5Q0FBOEQ7QUFDOUQsaUNBQStEO0FBRS9ELE1BQU0sY0FBYztJQUlpQjtJQUg1QixJQUFJLENBQWdCO0lBQ1gsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUV0QyxZQUFtQyxlQUFlLEtBQUs7UUFBcEIsaUJBQVksR0FBWixZQUFZLENBQVE7SUFBRyxDQUFDO0lBRXBELEtBQUssQ0FBQyxJQUFrQjtRQUM3QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzNCLE9BQU8sSUFBSSxzQkFBUSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLFFBQVE7Z0JBQzlCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNoQyxRQUFRLEVBQUUsQ0FBQztZQUNiLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBVyxJQUFJO1FBQ2IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFFRCxTQUFTLFdBQVcsQ0FDbEIsT0FBK0IsRUFDL0IsTUFBTSxHQUFHLEtBQUs7SUFFZCxPQUFPLElBQUksNkJBQW1CLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFRRCxpRkFBaUY7QUFDakYsS0FBSyxVQUFVLEdBQUcsQ0FDaEIsS0FBd0MsRUFDeEMsVUFBb0IsRUFBRTtJQUV0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QUM7SUFDN0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFO1FBQ2hELE1BQU0sQ0FBQyxJQUFBLGtCQUFXLEVBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV3JpdGFibGUgfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB7IGd1bnppcFN5bmMgfSBmcm9tIFwibm9kZTp6bGliXCI7XG5pbXBvcnQgeyBTaGltSW5jb21pbmdNZXNzYWdlIH0gZnJvbSBcIi4vcmVxdWVzdFwiO1xuaW1wb3J0IHsgUmVzcG9uc2VIZWFkLCBTaGltU2VydmVyUmVzcG9uc2UgfSBmcm9tIFwiLi9yZXNwb25zZVwiO1xuaW1wb3J0IHsgYWNjZXB0c0d6aXAsIHBpcGVUb1NpbmssIFJlc3BvbnNlU2luayB9IGZyb20gXCIuL3NpbmtcIjtcblxuY2xhc3MgQ29sbGVjdGluZ1NpbmsgaW1wbGVtZW50cyBSZXNwb25zZVNpbmsge1xuICBwdWJsaWMgaGVhZD86IFJlc3BvbnNlSGVhZDtcbiAgcHVibGljIHJlYWRvbmx5IGNodW5rczogQnVmZmVyW10gPSBbXTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBhZEVtcHR5Qm9keSA9IGZhbHNlKSB7fVxuXG4gIHB1YmxpYyBiZWdpbihoZWFkOiBSZXNwb25zZUhlYWQpOiBXcml0YWJsZSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICBjb25zdCBjaHVua3MgPSB0aGlzLmNodW5rcztcbiAgICByZXR1cm4gbmV3IFdyaXRhYmxlKHtcbiAgICAgIHdyaXRlKGNodW5rLCBfZW5jb2RpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNodW5rcy5wdXNoKEJ1ZmZlci5mcm9tKGNodW5rKSk7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldCBib2R5KCk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQodGhpcy5jaHVua3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RXaXRoKFxuICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICBtZXRob2QgPSBcIkdFVFwiLFxuKTogU2hpbUluY29taW5nTWVzc2FnZSB7XG4gIHJldHVybiBuZXcgU2hpbUluY29taW5nTWVzc2FnZSh7IG1ldGhvZCwgdXJsOiBcIi9cIiwgaGVhZGVycyB9KTtcbn1cblxuaW50ZXJmYWNlIFBpcGVDYXNlIHtcbiAgcmVhZG9ubHkgcmVxPzogU2hpbUluY29taW5nTWVzc2FnZTtcbiAgcmVhZG9ubHkgY29tcHJlc3M/OiBib29sZWFuO1xuICByZWFkb25seSBwYWRFbXB0eUJvZHk/OiBib29sZWFuO1xufVxuXG4vKiogUnVucyBvbmUgcmVzcG9uc2UgdGhyb3VnaCB0aGUgc2luayBhbmQgcmVzb2x2ZXMgb25jZSB0aGUgc2luayBpcyBmaW5pc2hlZC4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bihcbiAgd3JpdGU6IChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gdm9pZCxcbiAgb3B0aW9uczogUGlwZUNhc2UgPSB7fSxcbik6IFByb21pc2U8Q29sbGVjdGluZ1Npbms+IHtcbiAgY29uc3QgcmVxID0gb3B0aW9ucy5yZXEgPz8gcmVxdWVzdFdpdGgoeyBcImFjY2VwdC1lbmNvZGluZ1wiOiBcImd6aXBcIiB9KTtcbiAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICBjb25zdCBzaW5rID0gbmV3IENvbGxlY3RpbmdTaW5rKG9wdGlvbnMucGFkRW1wdHlCb2R5KTtcbiAgY29uc3QgZG9uZSA9IHBpcGVUb1NpbmsocmVxLCByZXMsIHNpbmssIHtcbiAgICBjb21wcmVzczogb3B0aW9ucy5jb21wcmVzcyA/PyB0cnVlLFxuICB9KTtcbiAgd3JpdGUocmVzKTtcbiAgYXdhaXQgZG9uZTtcbiAgcmV0dXJuIHNpbms7XG59XG5cbmRlc2NyaWJlKFwicGlwZVRvU2luayBjb21wcmVzc2lvblwiLCAoKSA9PiB7XG4gIGl0KFwiZ3ppcHMgY29tcHJlc3NpYmxlIGNvbnRlbnQgd2hlbiB0aGUgY2xpZW50IGFjY2VwdHMgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oKHJlcykgPT4ge1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvaHRtbDsgY2hhcnNldD11dGYtOFwiKTtcbiAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LUxlbmd0aFwiLCBcIjEzXCIpO1xuICAgICAgcmVzLmVuZChcIjxwPmhlbGxvPC9wPlwiKTtcbiAgICB9KTtcbiAgICBleHBlY3Qoc2luay5oZWFkPy5oZWFkZXJzW1wiY29udGVudC1lbmNvZGluZ1wiXSkudG9CZShcImd6aXBcIik7XG4gICAgLy8gVGhlIGxlbmd0aCB3ZSB3ZXJlIHRvbGQgaXMgdGhlIHVuY29tcHJlc3NlZCBvbmUgYW5kIHRoZSBjb21wcmVzc2VkIG9uZSBpc1xuICAgIC8vIG5vdCBrbm93biB1bnRpbCB0aGUgc3RyZWFtIGVuZHMuXG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVycy52YXJ5KS50b0JlKFwiQWNjZXB0LUVuY29kaW5nXCIpO1xuICAgIGV4cGVjdChndW56aXBTeW5jKHNpbmsuYm9keSkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIjxwPmhlbGxvPC9wPlwiKTtcbiAgfSk7XG5cbiAgaXQoXCJhcHBlbmRzIHRvIGFuIGV4aXN0aW5nIHZhcnkgcmF0aGVyIHRoYW4gcmVwbGFjaW5nIGl0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICByZXMuc2V0SGVhZGVyKFwiVmFyeVwiLCBcIkNvb2tpZVwiKTtcbiAgICAgIHJlcy5lbmQoXCJ4XCIpO1xuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnMudmFyeSkudG9CZShcIkNvb2tpZSwgQWNjZXB0LUVuY29kaW5nXCIpO1xuICB9KTtcblxuICBpdChcImZvcndhcmRzIHJlcy5mbHVzaCgpIHRvIHRoZSBjb21wcmVzc29yIHNvIHN0cmVhbWVkIEhUTUwgaXMgbm90IGJ1ZmZlcmVkXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzZWVuOiBudW1iZXJbXSA9IFtdO1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oKHJlcykgPT4ge1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvaHRtbFwiKTtcbiAgICAgIHJlcy53cml0ZShcIjxodG1sPlwiKTtcbiAgICAgIC8vIE5leHQuanMgZG9lcyBleGFjdGx5IHRoaXMgYWZ0ZXIgZXZlcnkgY2h1bmsgKGBwaXBlLXJlYWRhYmxlLmpzYCkuXG4gICAgICByZXMuZmx1c2g/LigpO1xuICAgICAgc2Vlbi5wdXNoKDEpO1xuICAgICAgcmVzLmVuZChcIjwvaHRtbD5cIik7XG4gICAgfSk7XG4gICAgZXhwZWN0KHNlZW4pLnRvRXF1YWwoWzFdKTtcbiAgICBleHBlY3QoZ3VuemlwU3luYyhzaW5rLmJvZHkpLnRvU3RyaW5nKFwidXRmLThcIikpLnRvQmUoXCI8aHRtbD48L2h0bWw+XCIpO1xuICB9KTtcblxuICBpdC5lYWNoKFtcbiAgICBbXCJhbiBpbmNvbXByZXNzaWJsZSBjb250ZW50IHR5cGVcIiwgeyBcImNvbnRlbnQtdHlwZVwiOiBcImltYWdlL2F2aWZcIiB9XSxcbiAgICBbXCJhbiBhbHJlYWR5LWVuY29kZWQgYm9keVwiLCB7IFwiY29udGVudC1lbmNvZGluZ1wiOiBcImJyXCIgfV0sXG4gICAgW1xuICAgICAgXCJhIHJlc3BvbnNlIHRoYXQgb3B0cyBvdXQgd2l0aCBuby10cmFuc2Zvcm1cIixcbiAgICAgIHtcbiAgICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJ0ZXh0L2V2ZW50LXN0cmVhbVwiLFxuICAgICAgICBcImNhY2hlLWNvbnRyb2xcIjogXCJuby1jYWNoZSwgbm8tdHJhbnNmb3JtXCIsXG4gICAgICB9LFxuICAgIF0sXG4gIF0pKFwiZG9lcyBub3QgZ3ppcCAlc1wiLCBhc3luYyAoX25hbWUsIGhlYWRlcnMpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhoZWFkZXJzKSkge1xuICAgICAgICByZXMuc2V0SGVhZGVyKG5hbWUsIHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnNbXCJjb250ZW50LWVuY29kaW5nXCJdKS5ub3QudG9CZShcImd6aXBcIik7XG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZyhcInV0Zi04XCIpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJkb2VzIG5vdCBnemlwIGEgMjA2LCB3aG9zZSBib2R5IGlzIGEgcmFuZ2Ugb2YgdGhlIHN0b3JlZCBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIG9uZSB1bmNvbXByZXNzYWJsZSBzdGF0dXMgdGhhdCBjYXJyaWVzIGEgYm9keS4gYGNvbnRlbnQtcmFuZ2VgIGNvdW50c1xuICAgIC8vIGJ5dGVzIG9mIHRoZSByZXByZXNlbnRhdGlvbiB0aGUgY2xpZW50IGFza2VkIGZvciwgc28gZ3ppcHBpbmcgdGhlIHNsaWNlXG4gICAgLy8gbWFrZXMgdGhlIHJhbmdlIG1lYW5pbmdsZXNzIC0gYW5kIGEgY2xpZW50IHN0aXRjaGluZyByYW5nZXMgdG9nZXRoZXJcbiAgICAvLyAodmlkZW8sIGEgcmVzdW1lZCBkb3dubG9hZCkgY2Fubm90IHVzZSBpdC5cbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIHJlcy5zdGF0dXNDb2RlID0gMjA2O1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvcGxhaW5cIik7XG4gICAgICByZXMuc2V0SGVhZGVyKFwiQ29udGVudC1SYW5nZVwiLCBcImJ5dGVzIDAtMy8xMDAwXCIpO1xuICAgICAgcmVzLmVuZChcImJvZHlcIik7XG4gICAgfSk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtZW5jb2RpbmdcIl0pLnRvQmVVbmRlZmluZWQoKTtcbiAgICBleHBlY3Qoc2luay5ib2R5LnRvU3RyaW5nKFwidXRmLThcIikpLnRvQmUoXCJib2R5XCIpO1xuICB9KTtcblxuICBpdChcImRvZXMgbm90IGd6aXAgd2hlbiB0aGUgY2xpZW50IGRpZCBub3Qgb2ZmZXIgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgICAgfSxcbiAgICAgIHsgcmVxOiByZXF1ZXN0V2l0aCh7fSkgfSxcbiAgICApO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnNbXCJjb250ZW50LWVuY29kaW5nXCJdKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZyhcInV0Zi04XCIpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJkb2VzIG5vdCBnemlwIHdoZW4gbmV4dC5jb25maWcgc2V0cyBjb21wcmVzczogZmFsc2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgICAgfSxcbiAgICAgIHsgY29tcHJlc3M6IGZhbHNlIH0sXG4gICAgKTtcbiAgICBleHBlY3Qoc2luay5oZWFkPy5oZWFkZXJzW1wiY29udGVudC1lbmNvZGluZ1wiXSkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcblxuICBpdC5lYWNoKFtcbiAgICBbXCJhIEhFQUQgcmVxdWVzdFwiLCB7IG1ldGhvZDogXCJIRUFEXCIsIHN0YXR1czogMjAwIH1dLFxuICAgIFtcImEgMjA0XCIsIHsgbWV0aG9kOiBcIkdFVFwiLCBzdGF0dXM6IDIwNCB9XSxcbiAgICBbXCJhIDMwNFwiLCB7IG1ldGhvZDogXCJHRVRcIiwgc3RhdHVzOiAzMDQgfV0sXG4gIF0pKFwiZG9lcyBub3QgZ3ppcCAlc1wiLCBhc3luYyAoX25hbWUsIHsgbWV0aG9kLCBzdGF0dXMgfSkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXNDb2RlID0gc3RhdHVzO1xuICAgICAgICByZXMuc2V0SGVhZGVyKFwiQ29udGVudC1UeXBlXCIsIFwidGV4dC9odG1sXCIpO1xuICAgICAgICByZXMuZW5kKCk7XG4gICAgICB9LFxuICAgICAgeyByZXE6IHJlcXVlc3RXaXRoKHsgXCJhY2NlcHQtZW5jb2RpbmdcIjogXCJnemlwXCIgfSwgbWV0aG9kKSB9LFxuICAgICk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtZW5jb2RpbmdcIl0pLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJwaXBlVG9TaW5rIGVtcHR5LWJvZHkgcGFkZGluZ1wiLCAoKSA9PiB7XG4gIGl0KFwid3JpdGVzIGEgc2luZ2xlIHNwYWNlIHdoZW4gdGhlIHNpbmsgYXNrcyBmb3IgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXNDb2RlID0gMzA0O1xuICAgICAgICByZXMuZW5kKCk7XG4gICAgICB9LFxuICAgICAgeyBwYWRFbXB0eUJvZHk6IHRydWUgfSxcbiAgICApO1xuICAgIC8vIFplcm8gcGF5bG9hZCBieXRlcyBhZnRlciB0aGUgcHJlbHVkZSBtYWtlcyBBUEkgR2F0ZXdheSBhbnN3ZXIgNTAyLCBhbmRcbiAgICAvLyBtYWtlcyBhIEZ1bmN0aW9uIFVSTCBkcm9wIHRoZSBwcmVsdWRlIGFuZCBhbnN3ZXIgYSBiYXJlXG4gICAgLy8gYDIwMCBhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1gLlxuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIiBcIik7XG4gIH0pO1xuXG4gIGl0KFwicGFkcyBhIEhFQUQgcmVzcG9uc2UsIHdob3NlIGJvZHkgaXMgZW1wdHkgYnkgZGVmaW5pdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bihcbiAgICAgIChyZXMpID0+IHtcbiAgICAgICAgcmVzLnNldEhlYWRlcihcImNvbnRlbnQtdHlwZVwiLCBcInRleHQvaHRtbDsgY2hhcnNldD11dGYtOFwiKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcihcImNvbnRlbnQtbGVuZ3RoXCIsIFwiNTc5OFwiKTtcbiAgICAgICAgcmVzLmVuZCgpO1xuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgcGFkRW1wdHlCb2R5OiB0cnVlLFxuICAgICAgICByZXE6IHJlcXVlc3RXaXRoKHsgXCJhY2NlcHQtZW5jb2RpbmdcIjogXCJnemlwXCIgfSwgXCJIRUFEXCIpLFxuICAgICAgfSxcbiAgICApO1xuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIiBcIik7XG4gICAgLy8gVGhlIGhlYWQgc3RpbGwgZGVzY3JpYmVzIHdoYXQgYSBHRVQgd291bGQgcmV0dXJuOyB0aGUgcGFkZGluZyBieXRlIGlzIG5vdFxuICAgIC8vIGEgYm9keSBhbmQgdGhlIGludGVncmF0aW9uIG92ZXJ3cml0ZXMgYGNvbnRlbnQtbGVuZ3RoYCB3aXRoIDAuXG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdKS50b0JlKFwiNTc5OFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJsZWF2ZXMgYSBub24tZW1wdHkgYm9keSBhbG9uZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bigocmVzKSA9PiByZXMuZW5kKFwicmVhbFwiKSwge1xuICAgICAgcGFkRW1wdHlCb2R5OiB0cnVlLFxuICAgICAgY29tcHJlc3M6IGZhbHNlLFxuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcInJlYWxcIik7XG4gIH0pO1xuXG4gIGl0KFwic2VuZHMgbm90aGluZyBmb3IgYW4gZW1wdHkgYm9keSB3aGVuIHRoZSBzaW5rIGRvZXMgbm90IGFza1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bigocmVzKSA9PiB7XG4gICAgICByZXMuc3RhdHVzQ29kZSA9IDMwNDtcbiAgICAgIHJlcy5lbmQoKTtcbiAgICB9KTtcbiAgICBleHBlY3Qoc2luay5ib2R5KS50b0hhdmVMZW5ndGgoMCk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwicGlwZVRvU2luayBsaWZlY3ljbGVcIiwgKCkgPT4ge1xuICAvKipcbiAgICogYGhhbmRsZSgpYCBhd2FpdHMgdGhpcyBwcm9taXNlIGJlZm9yZSBpdCBmbHVzaGVzIGB3YWl0VW50aWxgIHdvcmsg4oCUIElTUlxuICAgKiByZXZhbGlkYXRpb24sIGNhY2hlIHdyaXRlcyDigJQgYW5kIGJlZm9yZSB0aGUgcmVxdWVzdCdzIGNsb3N1cmVzIGNhbiBiZVxuICAgKiBjb2xsZWN0ZWQuIEEgY2xpZW50IHRoYXQgZGlzY29ubmVjdHMgYmVmb3JlIHRoZSBmaXJzdCBieXRlIGRlc3Ryb3lzIHRoZVxuICAgKiByZXNwb25zZSB3aXRob3V0IGFuIGVycm9yLCB3aGljaCBlbWl0cyBvbmx5IGBcImNsb3NlXCJgOiB0aGUgcGlwZWxpbmUgbmV2ZXJcbiAgICogc3RhcnRlZCwgc28gbm90aGluZyBlbHNlIGNhbiBzZXR0bGUgdGhlIHByb21pc2UgYW5kIHRoZSBhd2FpdCBuZXZlciByZXR1cm5lZC5cbiAgICovXG4gIGl0KFwic2V0dGxlcyB3aGVuIHRoZSByZXNwb25zZSBpcyBkZXN0cm95ZWQgYmVmb3JlIHRoZSBoZWFkIGdvZXMgb3V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXEgPSByZXF1ZXN0V2l0aCh7fSk7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IGRvbmUgPSBwaXBlVG9TaW5rKHJlcSwgcmVzLCBuZXcgQ29sbGVjdGluZ1NpbmsoKSwge1xuICAgICAgY29tcHJlc3M6IHRydWUsXG4gICAgfSk7XG5cbiAgICByZXMuZGVzdHJveSgpO1xuXG4gICAgYXdhaXQgZXhwZWN0KGRvbmUpLnJlc29sdmVzLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG5cbiAgLy8gVGhlIG5vcm1hbCBwYXRoIGhhcyB0byBrZWVwIHNldHRsaW5nIG9uIHRoZSBwaXBlbGluZSwgbm90IG9uIGBcImNsb3NlXCJgOiB0aGVcbiAgLy8gYm9keSBtdXN0IGJlIGZ1bGx5IGZsdXNoZWQgaW50byB0aGUgc2luayBieSB0aGUgdGltZSB0aGlzIHJlc29sdmVzLlxuICBpdChcInN0aWxsIHNldHRsZXMgb24gdGhlIHBpcGVsaW5lIG9uY2UgdGhlIGhlYWQgaGFzIGdvbmUgb3V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKFxuICAgICAgKHJlcykgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKFwiY29udGVudC10eXBlXCIsIFwidGV4dC9wbGFpblwiKTtcbiAgICAgICAgcmVzLmVuZChcImJvZHlcIik7XG4gICAgICB9LFxuICAgICAgeyBjb21wcmVzczogZmFsc2UgfSxcbiAgICApO1xuXG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZygpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJyZWplY3RzIHdoZW4gdGhlIHJlc3BvbnNlIGVycm9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gcmVxdWVzdFdpdGgoe30pO1xuICAgIGNvbnN0IHJlcyA9IG5ldyBTaGltU2VydmVyUmVzcG9uc2UoKTtcbiAgICBjb25zdCBkb25lID0gcGlwZVRvU2luayhyZXEsIHJlcywgbmV3IENvbGxlY3RpbmdTaW5rKCksIHtcbiAgICAgIGNvbXByZXNzOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgcmVzLmRlc3Ryb3kobmV3IEVycm9yKFwiYm9vbVwiKSk7XG5cbiAgICBhd2FpdCBleHBlY3QoZG9uZSkucmVqZWN0cy50b1Rocm93KFwiYm9vbVwiKTtcbiAgfSk7XG5cbiAgLy8gQSBzaW5rIHRoYXQgY2Fubm90IHRha2UgdGhlIGhlYWQg4oCUIGB3cml0ZUhlYWRgIHJlamVjdGluZyBhIGhlYWRlciB2YWx1ZSBpc1xuICAvLyB0aGUgcmVhbCBjYXNlIOKAlCB0aHJvd3MgZnJvbSBpbnNpZGUgdGhlIGBcImhlYWRcImAgbGlzdGVuZXIsIHdoZXJlIG5vdGhpbmdcbiAgLy8gZWxzZSB3b3VsZCBjYXRjaCBpdCBhbmQgdGhlIHBpcGVsaW5lIG5ldmVyIHN0YXJ0cy5cbiAgaXQuZWFjaChbXG4gICAgW1wid3JpdGVzIGEgYm9keVwiLCAocmVzOiBTaGltU2VydmVyUmVzcG9uc2UpID0+IHJlcy5lbmQoXCJib2R5XCIpXSxcbiAgICBbXCJlbmRzIGVtcHR5XCIsIChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gcmVzLmVuZCgpXSxcbiAgICBbXCJmbHVzaGVzIGl0cyBoZWFkIGZpcnN0XCIsIChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gcmVzLndyaXRlSGVhZCgyMDApXSxcbiAgXSkoXG4gICAgXCJyZWplY3RzIGFuZCBkZXN0cm95cyB0aGUgcmVzcG9uc2Ugd2hlbiBiZWdpbigpIHRocm93cyBhbmQgdGhlIHJlc3BvbnNlICVzXCIsXG4gICAgYXN5bmMgKF9uYW1lLCB3cml0ZSkgPT4ge1xuICAgICAgY29uc3QgcmVxID0gcmVxdWVzdFdpdGgoe30pO1xuICAgICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgICAgY29uc3QgZG9uZSA9IHBpcGVUb1NpbmsoXG4gICAgICAgIHJlcSxcbiAgICAgICAgcmVzLFxuICAgICAgICB7XG4gICAgICAgICAgYmVnaW4oKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJiYWQgaGVhZFwiKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7IGNvbXByZXNzOiBmYWxzZSB9LFxuICAgICAgKTtcblxuICAgICAgd3JpdGUocmVzKTtcblxuICAgICAgYXdhaXQgZXhwZWN0KGRvbmUpLnJlamVjdHMudG9UaHJvdyhcImJhZCBoZWFkXCIpO1xuICAgICAgZXhwZWN0KHJlcy5kZXN0cm95ZWQpLnRvQmUodHJ1ZSk7XG4gICAgfSxcbiAgKTtcbn0pO1xuXG5kZXNjcmliZShcImFjY2VwdHNHemlwXCIsICgpID0+IHtcbiAgaXQuZWFjaChbXG4gICAgW1wiZ3ppcFwiLCB0cnVlXSxcbiAgICBbXCJnemlwLCBkZWZsYXRlLCBiclwiLCB0cnVlXSxcbiAgICBbXCJHWklQO3E9MC41XCIsIHRydWVdLFxuICAgIFtcImd6aXA7cT0wXCIsIGZhbHNlXSxcbiAgICBbXCIqXCIsIHRydWVdLFxuICAgIFtcIio7cT0wXCIsIGZhbHNlXSxcbiAgICAvLyBBbiBleHBsaWNpdCBnemlwIHByZWZlcmVuY2Ugd2lucyBvdmVyIHRoZSB3aWxkY2FyZCwgaW4gZWl0aGVyIG9yZGVyLlxuICAgIFtcIio7cT0wLCBnemlwXCIsIHRydWVdLFxuICAgIFtcImd6aXA7cT0wLCAqXCIsIGZhbHNlXSxcbiAgICBbXCJiciwgZGVmbGF0ZVwiLCBmYWxzZV0sXG4gICAgW1wiXCIsIGZhbHNlXSxcbiAgICBbdW5kZWZpbmVkLCBmYWxzZV0sXG4gIF0pKFwiJXMg4oaSICVzXCIsIChoZWFkZXIsIGV4cGVjdGVkKSA9PiB7XG4gICAgZXhwZWN0KGFjY2VwdHNHemlwKGhlYWRlcikpLnRvQmUoZXhwZWN0ZWQpO1xuICB9KTtcblxuICBpdChcImpvaW5zIGEgcmVwZWF0ZWQgaGVhZGVyIGJlZm9yZSBwYXJzaW5nXCIsICgpID0+IHtcbiAgICBleHBlY3QoYWNjZXB0c0d6aXAoW1wiYnJcIiwgXCJnemlwXCJdKSkudG9CZSh0cnVlKTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 fetching and error mapping for `/_next/image`, split out from
|
|
3
|
+
* {@link ./image.ts} so it is unit-testable without `next` present.
|
|
4
|
+
*
|
|
5
|
+
* The one value from `next` that this file needs is passed in rather than
|
|
6
|
+
* imported: `next` is external to the shell bundles, so a static `import` here
|
|
7
|
+
* would be hoisted into the bundle where it cannot resolve. `image.ts` requires
|
|
8
|
+
* it through `./next-modules` instead.
|
|
9
|
+
*/
|
|
10
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
11
|
+
/** Where the app is served versus where its assets were uploaded. */
|
|
12
|
+
export interface S3AssetLocation {
|
|
13
|
+
/**
|
|
14
|
+
* The app's own `basePath` — the prefix of the *URL* it is served at. Only
|
|
15
|
+
* stripped from the href, never used to build a key: on the API Gateway
|
|
16
|
+
* deployment types this is the stage name, which never appears in S3.
|
|
17
|
+
*/
|
|
18
|
+
readonly urlBasePath: string;
|
|
19
|
+
/**
|
|
20
|
+
* `NextjsStaticAssets.keyPrefix`: the S3 key prefix the assets were uploaded
|
|
21
|
+
* under, without a leading slash. Empty for a bucket-root deployment.
|
|
22
|
+
*/
|
|
23
|
+
readonly keyPrefix: string;
|
|
24
|
+
/**
|
|
25
|
+
* The app's `assetPrefix`, when it is a path (`/cdn`). Next.js puts it in
|
|
26
|
+
* front of `/_next/` in place of `basePath`, so a statically imported image's
|
|
27
|
+
* href is `/cdn/_next/static/media/…`, and `next start` strips it again when
|
|
28
|
+
* it serves the file. An absolute `assetPrefix` makes the href absolute, which
|
|
29
|
+
* never reaches here.
|
|
30
|
+
* @default - none
|
|
31
|
+
*/
|
|
32
|
+
readonly assetPrefix?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetches a non-absolute (local) image referenced by an `<Image>` from S3.
|
|
36
|
+
*
|
|
37
|
+
* `url` is inconsistent about the app's `basePath`: next-image-loader bakes it
|
|
38
|
+
* into the href for statically imported images, while plain string paths are
|
|
39
|
+
* passed through as literally written by the app. So it is stripped when present,
|
|
40
|
+
* leaving a path relative to the asset root, and the bucket's own key prefix is
|
|
41
|
+
* applied to that. Deriving the key from `basePath` instead is wrong whenever the
|
|
42
|
+
* two differ, which they do for every API Gateway deployment.
|
|
43
|
+
*
|
|
44
|
+
* The key is percent-decoded, because an S3 key is the file's real name while
|
|
45
|
+
* `url` is a URL path. `public/hello world.jpg` arrives here as
|
|
46
|
+
* `/hello%20world.jpg` — the `url` query value is double-encoded, so decoding the
|
|
47
|
+
* query string leaves one layer — and its object key is `hello world.jpg`.
|
|
48
|
+
* Next.js's own `fetchInternalImage` gets the decode for free, since it makes an
|
|
49
|
+
* HTTP subrequest and its static file server resolves the path against the
|
|
50
|
+
* filesystem; skipping it here 400'd that file
|
|
51
|
+
* (`next-image-legacy/unicode`). Unicode needs nothing: `äöüščří.png` survives
|
|
52
|
+
* the query decode as itself and is already the object's name.
|
|
53
|
+
*
|
|
54
|
+
* Throws {@link ImageTooLargeError} rather than read past `maximumBody`
|
|
55
|
+
* (`images.maximumResponseBody`), which `next start` enforces on local sources
|
|
56
|
+
* too: a large `public/` file would otherwise be read into memory whole.
|
|
57
|
+
*/
|
|
58
|
+
export declare function fetchFromS3(s3: S3Client, bucket: string, url: string, location: S3AssetLocation, maximumBody: number): Promise<{
|
|
59
|
+
buffer: Buffer;
|
|
60
|
+
contentType: string | null;
|
|
61
|
+
etag: string;
|
|
62
|
+
}>;
|
|
63
|
+
/** A source over `images.maximumResponseBody`; see {@link fetchFromS3}. */
|
|
64
|
+
export declare class ImageTooLargeError extends Error {
|
|
65
|
+
constructor(key: string);
|
|
66
|
+
}
|
|
67
|
+
/** `ImageError` from `next/dist/server/image-optimizer.js`. */
|
|
68
|
+
export type ImageErrorClass = (typeof import("next/dist/server/image-optimizer.js"))["ImageError"];
|
|
69
|
+
/**
|
|
70
|
+
* Maps an error thrown while processing an image request to the HTTP
|
|
71
|
+
* status/message it should produce, preserving the status Next.js's own
|
|
72
|
+
* `ImageError`/`fetchExternalImage` attach. A source over
|
|
73
|
+
* `images.maximumResponseBody` is the 413 `fetchInternalImage` answers.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveErrorResponse(error: unknown, ImageError: ImageErrorClass): {
|
|
76
|
+
statusCode: number;
|
|
77
|
+
message: string;
|
|
78
|
+
};
|