cdk-nextjs 0.6.2 → 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 +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 +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 +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 +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 +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,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loading and invoking build-output entrypoints.
|
|
3
|
+
*
|
|
4
|
+
* All four invocable output types — `app-page`, `app-route`, `page`, `page-api` —
|
|
5
|
+
* export the same `handler(req, res, ctx)` from
|
|
6
|
+
* `next/dist/build/templates/{app-page,app-route,pages,pages-api}.js`, so there
|
|
7
|
+
* is nothing to switch on: `AdapterEntrypoint.type` is carried for diagnostics,
|
|
8
|
+
* not dispatch.
|
|
9
|
+
*
|
|
10
|
+
* Loading is lazy and memoized per file. Lazy because a cold start that requires
|
|
11
|
+
* every route's module pays for the whole app on the first request; memoized
|
|
12
|
+
* because locale variants and `_next/data` siblings of one route all resolve to
|
|
13
|
+
* the same `filePath`.
|
|
14
|
+
*/
|
|
15
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
16
|
+
import { AdapterEntrypoint, AdapterManifest } from "./manifest";
|
|
17
|
+
/**
|
|
18
|
+
* Per-request context, the third argument of every entrypoint `handler`.
|
|
19
|
+
*
|
|
20
|
+
* `requestMeta` is `RequestMeta` from `next/dist/server/request-meta`, typed
|
|
21
|
+
* loosely here so this module does not need a `next` type import.
|
|
22
|
+
*/
|
|
23
|
+
export interface EntrypointContext {
|
|
24
|
+
readonly waitUntil?: (promise: Promise<unknown>) => void;
|
|
25
|
+
readonly requestMeta?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export type EntrypointHandler = (req: IncomingMessage, res: ServerResponse, ctx: EntrypointContext) => Promise<void | null | undefined>;
|
|
28
|
+
export declare class EntrypointRegistry {
|
|
29
|
+
private readonly root;
|
|
30
|
+
private readonly manifest;
|
|
31
|
+
private readonly handlers;
|
|
32
|
+
/**
|
|
33
|
+
* @param root absolute path the manifest's repo-root-relative `filePath`s
|
|
34
|
+
* resolve against — the staging root, which is `process.cwd()` at runtime.
|
|
35
|
+
* @param manifest used only to explain a failed load; see {@link ownedRouteError}.
|
|
36
|
+
*/
|
|
37
|
+
constructor(root: string, manifest: AdapterManifest);
|
|
38
|
+
load(entrypoint: AdapterEntrypoint): Promise<EntrypointHandler>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A request for a route packaged into another `functionGroups` group.
|
|
42
|
+
*
|
|
43
|
+
* The runtime answers it with a 308 to the URL's canonical spelling when case
|
|
44
|
+
* is the only difference (`caseCanonicalPath`), and a 404 otherwise, not a 500. The usual way here is a URL the
|
|
45
|
+
* edge matches differently from Next.js: CloudFront behaviors and API Gateway
|
|
46
|
+
* resources are case-sensitive and Next.js's route matching is not, so
|
|
47
|
+
* `/API/reports/1` misses the `api/reports/*` behavior, reaches the default
|
|
48
|
+
* group, and matches `/api/reports/[id]` there. At the edge that is a different
|
|
49
|
+
* URL, one no group serves, and a 404 says so; a 500 blamed the deployment.
|
|
50
|
+
*/
|
|
51
|
+
export declare class RouteInOtherGroupError extends Error {
|
|
52
|
+
/** The group whose package has the route. */
|
|
53
|
+
readonly owner: string;
|
|
54
|
+
constructor(message: string,
|
|
55
|
+
/** The group whose package has the route. */
|
|
56
|
+
owner: string, options?: ErrorOptions);
|
|
57
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RouteInOtherGroupError = exports.EntrypointRegistry = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const load_module_1 = require("./load-module");
|
|
6
|
+
const manifest_1 = require("./manifest");
|
|
7
|
+
class EntrypointRegistry {
|
|
8
|
+
root;
|
|
9
|
+
manifest;
|
|
10
|
+
handlers = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* @param root absolute path the manifest's repo-root-relative `filePath`s
|
|
13
|
+
* resolve against — the staging root, which is `process.cwd()` at runtime.
|
|
14
|
+
* @param manifest used only to explain a failed load; see {@link ownedRouteError}.
|
|
15
|
+
*/
|
|
16
|
+
constructor(root, manifest) {
|
|
17
|
+
this.root = root;
|
|
18
|
+
this.manifest = manifest;
|
|
19
|
+
}
|
|
20
|
+
load(entrypoint) {
|
|
21
|
+
let handler = this.handlers.get(entrypoint.filePath);
|
|
22
|
+
if (!handler) {
|
|
23
|
+
handler = loadEntrypointHandler(this.root, entrypoint, this.manifest);
|
|
24
|
+
// Cached as the promise so two concurrent first requests for one route
|
|
25
|
+
// share a single (expensive) module load.
|
|
26
|
+
this.handlers.set(entrypoint.filePath, handler);
|
|
27
|
+
// Evicted on failure, because the cache is keyed on the file and not on
|
|
28
|
+
// the attempt: a load can fail for a reason that has nothing to do with the
|
|
29
|
+
// file (EMFILE under a cold-start burst, an allocation near the memory
|
|
30
|
+
// limit), and a cached rejection makes that transient failure permanent —
|
|
31
|
+
// the same 500 for every later request until the sandbox is recycled.
|
|
32
|
+
handler.catch(() => {
|
|
33
|
+
if (this.handlers.get(entrypoint.filePath) === handler) {
|
|
34
|
+
this.handlers.delete(entrypoint.filePath);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return handler;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.EntrypointRegistry = EntrypointRegistry;
|
|
42
|
+
async function loadEntrypointHandler(root, entrypoint, manifest) {
|
|
43
|
+
const absolute = (0, node_path_1.join)(root, entrypoint.filePath);
|
|
44
|
+
let exports;
|
|
45
|
+
try {
|
|
46
|
+
exports = await (0, load_module_1.loadBuiltModule)(absolute);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = `Could not load the entrypoint for "${entrypoint.id}" from ` +
|
|
50
|
+
`"${absolute}" (manifest filePath "${entrypoint.filePath}", type ` +
|
|
51
|
+
`"${entrypoint.type}"). The deployment package is incomplete.`;
|
|
52
|
+
const owner = owningGroup(entrypoint, manifest);
|
|
53
|
+
if (owner) {
|
|
54
|
+
throw new RouteInOtherGroupError(message + ownedRouteError(owner.self, owner.owner), owner.owner, { cause: error });
|
|
55
|
+
}
|
|
56
|
+
throw new Error(message, { cause: error });
|
|
57
|
+
}
|
|
58
|
+
return (0, load_module_1.requireFunctionExport)(exports, "handler", () => `The entrypoint for "${entrypoint.id}" at "${absolute}"`);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A request for a route packaged into another `functionGroups` group.
|
|
62
|
+
*
|
|
63
|
+
* The runtime answers it with a 308 to the URL's canonical spelling when case
|
|
64
|
+
* is the only difference (`caseCanonicalPath`), and a 404 otherwise, not a 500. The usual way here is a URL the
|
|
65
|
+
* edge matches differently from Next.js: CloudFront behaviors and API Gateway
|
|
66
|
+
* resources are case-sensitive and Next.js's route matching is not, so
|
|
67
|
+
* `/API/reports/1` misses the `api/reports/*` behavior, reaches the default
|
|
68
|
+
* group, and matches `/api/reports/[id]` there. At the edge that is a different
|
|
69
|
+
* URL, one no group serves, and a 404 says so; a 500 blamed the deployment.
|
|
70
|
+
*/
|
|
71
|
+
class RouteInOtherGroupError extends Error {
|
|
72
|
+
owner;
|
|
73
|
+
constructor(message,
|
|
74
|
+
/** The group whose package has the route. */
|
|
75
|
+
owner, options) {
|
|
76
|
+
super(message, options);
|
|
77
|
+
this.owner = owner;
|
|
78
|
+
this.name = "RouteInOtherGroupError";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.RouteInOtherGroupError = RouteInOtherGroupError;
|
|
82
|
+
/**
|
|
83
|
+
* The one thing splitting can break that nothing else can: a request arriving at
|
|
84
|
+
* a function whose package does not contain the route.
|
|
85
|
+
*
|
|
86
|
+
* Every group ships the same manifest, so the function knows the route exists and
|
|
87
|
+
* which group owns it; what it does not have is the file. Without this the
|
|
88
|
+
* symptom is a module-not-found on a path nobody wrote, and the cause — a
|
|
89
|
+
* CloudFront behavior or API Gateway resource pointing at the wrong function, or
|
|
90
|
+
* a URL whose case the edge did not match — is several layers away. With it, the
|
|
91
|
+
* log names both groups.
|
|
92
|
+
*/
|
|
93
|
+
function owningGroup(entrypoint, manifest) {
|
|
94
|
+
const groups = manifest.groups;
|
|
95
|
+
const self = process.env[manifest_1.FUNCTION_GROUP_ENV_VAR];
|
|
96
|
+
if (!groups || !self) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
const templates = Object.entries(manifest.entrypoints)
|
|
100
|
+
.filter(([, candidate]) => candidate.id === entrypoint.id)
|
|
101
|
+
.map(([template]) => template);
|
|
102
|
+
const owner = Object.entries(groups).find(([, owned]) => owned.some((template) => templates.includes(template)))?.[0];
|
|
103
|
+
return owner && owner !== self ? { self, owner } : undefined;
|
|
104
|
+
}
|
|
105
|
+
function ownedRouteError(self, owner) {
|
|
106
|
+
return (` This function is \`functionGroups\` group "${self}", but this route was ` +
|
|
107
|
+
`packaged into group "${owner}" — so the request reached the wrong function. ` +
|
|
108
|
+
`Check that the route pattern in group "${owner}" covers the URL that was ` +
|
|
109
|
+
`requested: a pattern can be too narrow at the edge while still claiming the ` +
|
|
110
|
+
`route at build time (for example "/reports/**" claims "/reports/[id]" but ` +
|
|
111
|
+
`the CloudFront behavior it becomes, "reports/*", does not match "/reports"), ` +
|
|
112
|
+
`and the edge matches case-sensitively where Next.js does not ("/API/x" ` +
|
|
113
|
+
`misses an "api/*" behavior).`);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50cnlwb2ludHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9lbnRyeXBvaW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFlQSx5Q0FBaUM7QUFDakMsK0NBQXVFO0FBQ3ZFLHlDQUlvQjtBQW1CcEIsTUFBYSxrQkFBa0I7SUFTVjtJQUNBO0lBVEYsUUFBUSxHQUFHLElBQUksR0FBRyxFQUFzQyxDQUFDO0lBRTFFOzs7O09BSUc7SUFDSCxZQUNtQixJQUFZLEVBQ1osUUFBeUI7UUFEekIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUNaLGFBQVEsR0FBUixRQUFRLENBQWlCO0lBQ3pDLENBQUM7SUFFRyxJQUFJLENBQUMsVUFBNkI7UUFDdkMsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE9BQU8sR0FBRyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdEUsdUVBQXVFO1lBQ3ZFLDBDQUEwQztZQUMxQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELHdFQUF3RTtZQUN4RSw0RUFBNEU7WUFDNUUsdUVBQXVFO1lBQ3ZFLDBFQUEwRTtZQUMxRSxzRUFBc0U7WUFDdEUsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7Z0JBQ2pCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLE9BQU8sRUFBRSxDQUFDO29CQUN2RCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQzVDLENBQUM7WUFD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Q0FBQyxDQUFDO0lBQ1AsT0FBTyxLQUFLLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUMvRCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsSUFBWSxFQUFFLEtBQWE7SUFDbEQsT0FBTyxDQUNMLCtDQUErQyxJQUFJLHdCQUF3QjtRQUMzRSx3QkFBd0IsS0FBSyxpREFBaUQ7UUFDOUUsMENBQTBDLEtBQUssNEJBQTRCO1FBQzNFLDhFQUE4RTtRQUM5RSw0RUFBNEU7UUFDNUUsK0VBQStFO1FBQy9FLHlFQUF5RTtRQUN6RSw4QkFBOEIsQ0FDL0IsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExvYWRpbmcgYW5kIGludm9raW5nIGJ1aWxkLW91dHB1dCBlbnRyeXBvaW50cy5cbiAqXG4gKiBBbGwgZm91ciBpbnZvY2FibGUgb3V0cHV0IHR5cGVzIOKAlCBgYXBwLXBhZ2VgLCBgYXBwLXJvdXRlYCwgYHBhZ2VgLCBgcGFnZS1hcGlgIOKAlFxuICogZXhwb3J0IHRoZSBzYW1lIGBoYW5kbGVyKHJlcSwgcmVzLCBjdHgpYCBmcm9tXG4gKiBgbmV4dC9kaXN0L2J1aWxkL3RlbXBsYXRlcy97YXBwLXBhZ2UsYXBwLXJvdXRlLHBhZ2VzLHBhZ2VzLWFwaX0uanNgLCBzbyB0aGVyZVxuICogaXMgbm90aGluZyB0byBzd2l0Y2ggb246IGBBZGFwdGVyRW50cnlwb2ludC50eXBlYCBpcyBjYXJyaWVkIGZvciBkaWFnbm9zdGljcyxcbiAqIG5vdCBkaXNwYXRjaC5cbiAqXG4gKiBMb2FkaW5nIGlzIGxhenkgYW5kIG1lbW9pemVkIHBlciBmaWxlLiBMYXp5IGJlY2F1c2UgYSBjb2xkIHN0YXJ0IHRoYXQgcmVxdWlyZXNcbiAqIGV2ZXJ5IHJvdXRlJ3MgbW9kdWxlIHBheXMgZm9yIHRoZSB3aG9sZSBhcHAgb24gdGhlIGZpcnN0IHJlcXVlc3Q7IG1lbW9pemVkXG4gKiBiZWNhdXNlIGxvY2FsZSB2YXJpYW50cyBhbmQgYF9uZXh0L2RhdGFgIHNpYmxpbmdzIG9mIG9uZSByb3V0ZSBhbGwgcmVzb2x2ZSB0b1xuICogdGhlIHNhbWUgYGZpbGVQYXRoYC5cbiAqL1xuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGxvYWRCdWlsdE1vZHVsZSwgcmVxdWlyZUZ1bmN0aW9uRXhwb3J0IH0gZnJvbSBcIi4vbG9hZC1tb2R1bGVcIjtcbmltcG9ydCB7XG4gIEFkYXB0ZXJFbnRyeXBvaW50LFxuICBBZGFwdGVyTWFuaWZlc3QsXG4gIEZVTkNUSU9OX0dST1VQX0VOVl9WQVIsXG59IGZyb20gXCIuL21hbmlmZXN0XCI7XG5cbi8qKlxuICogUGVyLXJlcXVlc3QgY29udGV4dCwgdGhlIHRoaXJkIGFyZ3VtZW50IG9mIGV2ZXJ5IGVudHJ5cG9pbnQgYGhhbmRsZXJgLlxuICpcbiAqIGByZXF1ZXN0TWV0YWAgaXMgYFJlcXVlc3RNZXRhYCBmcm9tIGBuZXh0L2Rpc3Qvc2VydmVyL3JlcXVlc3QtbWV0YWAsIHR5cGVkXG4gKiBsb29zZWx5IGhlcmUgc28gdGhpcyBtb2R1bGUgZG9lcyBub3QgbmVlZCBhIGBuZXh0YCB0eXBlIGltcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnRyeXBvaW50Q29udGV4dCB7XG4gIHJlYWRvbmx5IHdhaXRVbnRpbD86IChwcm9taXNlOiBQcm9taXNlPHVua25vd24+KSA9PiB2b2lkO1xuICByZWFkb25seSByZXF1ZXN0TWV0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG5leHBvcnQgdHlwZSBFbnRyeXBvaW50SGFuZGxlciA9IChcbiAgcmVxOiBJbmNvbWluZ01lc3NhZ2UsXG4gIHJlczogU2VydmVyUmVzcG9uc2UsXG4gIGN0eDogRW50cnlwb2ludENvbnRleHQsXG4pID0+IFByb21pc2U8dm9pZCB8IG51bGwgfCB1bmRlZmluZWQ+O1xuXG5leHBvcnQgY2xhc3MgRW50cnlwb2ludFJlZ2lzdHJ5IHtcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVycyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPEVudHJ5cG9pbnRIYW5kbGVyPj4oKTtcblxuICAvKipcbiAgICogQHBhcmFtIHJvb3QgYWJzb2x1dGUgcGF0aCB0aGUgbWFuaWZlc3QncyByZXBvLXJvb3QtcmVsYXRpdmUgYGZpbGVQYXRoYHNcbiAgICogcmVzb2x2ZSBhZ2FpbnN0IOKAlCB0aGUgc3RhZ2luZyByb290LCB3aGljaCBpcyBgcHJvY2Vzcy5jd2QoKWAgYXQgcnVudGltZS5cbiAgICogQHBhcmFtIG1hbmlmZXN0IHVzZWQgb25seSB0byBleHBsYWluIGEgZmFpbGVkIGxvYWQ7IHNlZSB7QGxpbmsgb3duZWRSb3V0ZUVycm9yfS5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJvb3Q6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1hbmlmZXN0OiBBZGFwdGVyTWFuaWZlc3QsXG4gICkge31cblxuICBwdWJsaWMgbG9hZChlbnRyeXBvaW50OiBBZGFwdGVyRW50cnlwb2ludCk6IFByb21pc2U8RW50cnlwb2ludEhhbmRsZXI+IHtcbiAgICBsZXQgaGFuZGxlciA9IHRoaXMuaGFuZGxlcnMuZ2V0KGVudHJ5cG9pbnQuZmlsZVBhdGgpO1xuICAgIGlmICghaGFuZGxlcikge1xuICAgICAgaGFuZGxlciA9IGxvYWRFbnRyeXBvaW50SGFuZGxlcih0aGlzLnJvb3QsIGVudHJ5cG9pbnQsIHRoaXMubWFuaWZlc3QpO1xuICAgICAgLy8gQ2FjaGVkIGFzIHRoZSBwcm9taXNlIHNvIHR3byBjb25jdXJyZW50IGZpcnN0IHJlcXVlc3RzIGZvciBvbmUgcm91dGVcbiAgICAgIC8vIHNoYXJlIGEgc2luZ2xlIChleHBlbnNpdmUpIG1vZHVsZSBsb2FkLlxuICAgICAgdGhpcy5oYW5kbGVycy5zZXQoZW50cnlwb2ludC5maWxlUGF0aCwgaGFuZGxlcik7XG4gICAgICAvLyBFdmljdGVkIG9uIGZhaWx1cmUsIGJlY2F1c2UgdGhlIGNhY2hlIGlzIGtleWVkIG9uIHRoZSBmaWxlIGFuZCBub3Qgb25cbiAgICAgIC8vIHRoZSBhdHRlbXB0OiBhIGxvYWQgY2FuIGZhaWwgZm9yIGEgcmVhc29uIHRoYXQgaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCB0aGVcbiAgICAgIC8vIGZpbGUgKEVNRklMRSB1bmRlciBhIGNvbGQtc3RhcnQgYnVyc3QsIGFuIGFsbG9jYXRpb24gbmVhciB0aGUgbWVtb3J5XG4gICAgICAvLyBsaW1pdCksIGFuZCBhIGNhY2hlZCByZWplY3Rpb24gbWFrZXMgdGhhdCB0cmFuc2llbnQgZmFpbHVyZSBwZXJtYW5lbnQg4oCUXG4gICAgICAvLyB0aGUgc2FtZSA1MDAgZm9yIGV2ZXJ5IGxhdGVyIHJlcXVlc3QgdW50aWwgdGhlIHNhbmRib3ggaXMgcmVjeWNsZWQuXG4gICAgICBoYW5kbGVyLmNhdGNoKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaGFuZGxlcnMuZ2V0KGVudHJ5cG9pbnQuZmlsZVBhdGgpID09PSBoYW5kbGVyKSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVycy5kZWxldGUoZW50cnlwb2ludC5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gaGFuZGxlcjtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBsb2FkRW50cnlwb2ludEhhbmRsZXIoXG4gIHJvb3Q6IHN0cmluZyxcbiAgZW50cnlwb2ludDogQWRhcHRlckVudHJ5cG9pbnQsXG4gIG1hbmlmZXN0OiBBZGFwdGVyTWFuaWZlc3QsXG4pOiBQcm9taXNlPEVudHJ5cG9pbnRIYW5kbGVyPiB7XG4gIGNvbnN0IGFic29sdXRlID0gam9pbihyb290LCBlbnRyeXBvaW50LmZpbGVQYXRoKTtcbiAgbGV0IGV4cG9ydHM6IHVua25vd247XG4gIHRyeSB7XG4gICAgZXhwb3J0cyA9IGF3YWl0IGxvYWRCdWlsdE1vZHVsZShhYnNvbHV0ZSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9XG4gICAgICBgQ291bGQgbm90IGxvYWQgdGhlIGVudHJ5cG9pbnQgZm9yIFwiJHtlbnRyeXBvaW50LmlkfVwiIGZyb20gYCArXG4gICAgICBgXCIke2Fic29sdXRlfVwiIChtYW5pZmVzdCBmaWxlUGF0aCBcIiR7ZW50cnlwb2ludC5maWxlUGF0aH1cIiwgdHlwZSBgICtcbiAgICAgIGBcIiR7ZW50cnlwb2ludC50eXBlfVwiKS4gVGhlIGRlcGxveW1lbnQgcGFja2FnZSBpcyBpbmNvbXBsZXRlLmA7XG4gICAgY29uc3Qgb3duZXIgPSBvd25pbmdHcm91cChlbnRyeXBvaW50LCBtYW5pZmVzdCk7XG4gICAgaWYgKG93bmVyKSB7XG4gICAgICB0aHJvdyBuZXcgUm91dGVJbk90aGVyR3JvdXBFcnJvcihcbiAgICAgICAgbWVzc2FnZSArIG93bmVkUm91dGVFcnJvcihvd25lci5zZWxmLCBvd25lci5vd25lciksXG4gICAgICAgIG93bmVyLm93bmVyLFxuICAgICAgICB7IGNhdXNlOiBlcnJvciB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UsIHsgY2F1c2U6IGVycm9yIH0pO1xuICB9XG4gIHJldHVybiByZXF1aXJlRnVuY3Rpb25FeHBvcnQ8RW50cnlwb2ludEhhbmRsZXI+KFxuICAgIGV4cG9ydHMsXG4gICAgXCJoYW5kbGVyXCIsXG4gICAgKCkgPT4gYFRoZSBlbnRyeXBvaW50IGZvciBcIiR7ZW50cnlwb2ludC5pZH1cIiBhdCBcIiR7YWJzb2x1dGV9XCJgLFxuICApO1xufVxuXG4vKipcbiAqIEEgcmVxdWVzdCBmb3IgYSByb3V0ZSBwYWNrYWdlZCBpbnRvIGFub3RoZXIgYGZ1bmN0aW9uR3JvdXBzYCBncm91cC5cbiAqXG4gKiBUaGUgcnVudGltZSBhbnN3ZXJzIGl0IHdpdGggYSAzMDggdG8gdGhlIFVSTCdzIGNhbm9uaWNhbCBzcGVsbGluZyB3aGVuIGNhc2VcbiAqIGlzIHRoZSBvbmx5IGRpZmZlcmVuY2UgKGBjYXNlQ2Fub25pY2FsUGF0aGApLCBhbmQgYSA0MDQgb3RoZXJ3aXNlLCBub3QgYSA1MDAuIFRoZSB1c3VhbCB3YXkgaGVyZSBpcyBhIFVSTCB0aGVcbiAqIGVkZ2UgbWF0Y2hlcyBkaWZmZXJlbnRseSBmcm9tIE5leHQuanM6IENsb3VkRnJvbnQgYmVoYXZpb3JzIGFuZCBBUEkgR2F0ZXdheVxuICogcmVzb3VyY2VzIGFyZSBjYXNlLXNlbnNpdGl2ZSBhbmQgTmV4dC5qcydzIHJvdXRlIG1hdGNoaW5nIGlzIG5vdCwgc29cbiAqIGAvQVBJL3JlcG9ydHMvMWAgbWlzc2VzIHRoZSBgYXBpL3JlcG9ydHMvKmAgYmVoYXZpb3IsIHJlYWNoZXMgdGhlIGRlZmF1bHRcbiAqIGdyb3VwLCBhbmQgbWF0Y2hlcyBgL2FwaS9yZXBvcnRzL1tpZF1gIHRoZXJlLiBBdCB0aGUgZWRnZSB0aGF0IGlzIGEgZGlmZmVyZW50XG4gKiBVUkwsIG9uZSBubyBncm91cCBzZXJ2ZXMsIGFuZCBhIDQwNCBzYXlzIHNvOyBhIDUwMCBibGFtZWQgdGhlIGRlcGxveW1lbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBSb3V0ZUluT3RoZXJHcm91cEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIC8qKiBUaGUgZ3JvdXAgd2hvc2UgcGFja2FnZSBoYXMgdGhlIHJvdXRlLiAqL1xuICAgIHB1YmxpYyByZWFkb25seSBvd25lcjogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBFcnJvck9wdGlvbnMsXG4gICkge1xuICAgIHN1cGVyKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICAgIHRoaXMubmFtZSA9IFwiUm91dGVJbk90aGVyR3JvdXBFcnJvclwiO1xuICB9XG59XG5cbi8qKlxuICogVGhlIG9uZSB0aGluZyBzcGxpdHRpbmcgY2FuIGJyZWFrIHRoYXQgbm90aGluZyBlbHNlIGNhbjogYSByZXF1ZXN0IGFycml2aW5nIGF0XG4gKiBhIGZ1bmN0aW9uIHdob3NlIHBhY2thZ2UgZG9lcyBub3QgY29udGFpbiB0aGUgcm91dGUuXG4gKlxuICogRXZlcnkgZ3JvdXAgc2hpcHMgdGhlIHNhbWUgbWFuaWZlc3QsIHNvIHRoZSBmdW5jdGlvbiBrbm93cyB0aGUgcm91dGUgZXhpc3RzIGFuZFxuICogd2hpY2ggZ3JvdXAgb3ducyBpdDsgd2hhdCBpdCBkb2VzIG5vdCBoYXZlIGlzIHRoZSBmaWxlLiBXaXRob3V0IHRoaXMgdGhlXG4gKiBzeW1wdG9tIGlzIGEgbW9kdWxlLW5vdC1mb3VuZCBvbiBhIHBhdGggbm9ib2R5IHdyb3RlLCBhbmQgdGhlIGNhdXNlIOKAlCBhXG4gKiBDbG91ZEZyb250IGJlaGF2aW9yIG9yIEFQSSBHYXRld2F5IHJlc291cmNlIHBvaW50aW5nIGF0IHRoZSB3cm9uZyBmdW5jdGlvbiwgb3JcbiAqIGEgVVJMIHdob3NlIGNhc2UgdGhlIGVkZ2UgZGlkIG5vdCBtYXRjaCDigJQgaXMgc2V2ZXJhbCBsYXllcnMgYXdheS4gV2l0aCBpdCwgdGhlXG4gKiBsb2cgbmFtZXMgYm90aCBncm91cHMuXG4gKi9cbmZ1bmN0aW9uIG93bmluZ0dyb3VwKFxuICBlbnRyeXBvaW50OiBBZGFwdGVyRW50cnlwb2ludCxcbiAgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdCxcbik6IHsgcmVhZG9ubHkgc2VsZjogc3RyaW5nOyByZWFkb25seSBvd25lcjogc3RyaW5nIH0gfCB1bmRlZmluZWQge1xuICBjb25zdCBncm91cHMgPSBtYW5pZmVzdC5ncm91cHM7XG4gIGNvbnN0IHNlbGYgPSBwcm9jZXNzLmVudltGVU5DVElPTl9HUk9VUF9FTlZfVkFSXTtcbiAgaWYgKCFncm91cHMgfHwgIXNlbGYpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IHRlbXBsYXRlcyA9IE9iamVjdC5lbnRyaWVzKG1hbmlmZXN0LmVudHJ5cG9pbnRzKVxuICAgIC5maWx0ZXIoKFssIGNhbmRpZGF0ZV0pID0+IGNhbmRpZGF0ZS5pZCA9PT0gZW50cnlwb2ludC5pZClcbiAgICAubWFwKChbdGVtcGxhdGVdKSA9PiB0ZW1wbGF0ZSk7XG4gIGNvbnN0IG93bmVyID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBzKS5maW5kKChbLCBvd25lZF0pID0+XG4gICAgb3duZWQuc29tZSgodGVtcGxhdGUpID0+IHRlbXBsYXRlcy5pbmNsdWRlcyh0ZW1wbGF0ZSkpLFxuICApPy5bMF07XG4gIHJldHVybiBvd25lciAmJiBvd25lciAhPT0gc2VsZiA/IHsgc2VsZiwgb3duZXIgfSA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gb3duZWRSb3V0ZUVycm9yKHNlbGY6IHN0cmluZywgb3duZXI6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiAoXG4gICAgYCBUaGlzIGZ1bmN0aW9uIGlzIFxcYGZ1bmN0aW9uR3JvdXBzXFxgIGdyb3VwIFwiJHtzZWxmfVwiLCBidXQgdGhpcyByb3V0ZSB3YXMgYCArXG4gICAgYHBhY2thZ2VkIGludG8gZ3JvdXAgXCIke293bmVyfVwiIOKAlCBzbyB0aGUgcmVxdWVzdCByZWFjaGVkIHRoZSB3cm9uZyBmdW5jdGlvbi4gYCArXG4gICAgYENoZWNrIHRoYXQgdGhlIHJvdXRlIHBhdHRlcm4gaW4gZ3JvdXAgXCIke293bmVyfVwiIGNvdmVycyB0aGUgVVJMIHRoYXQgd2FzIGAgK1xuICAgIGByZXF1ZXN0ZWQ6IGEgcGF0dGVybiBjYW4gYmUgdG9vIG5hcnJvdyBhdCB0aGUgZWRnZSB3aGlsZSBzdGlsbCBjbGFpbWluZyB0aGUgYCArXG4gICAgYHJvdXRlIGF0IGJ1aWxkIHRpbWUgKGZvciBleGFtcGxlIFwiL3JlcG9ydHMvKipcIiBjbGFpbXMgXCIvcmVwb3J0cy9baWRdXCIgYnV0IGAgK1xuICAgIGB0aGUgQ2xvdWRGcm9udCBiZWhhdmlvciBpdCBiZWNvbWVzLCBcInJlcG9ydHMvKlwiLCBkb2VzIG5vdCBtYXRjaCBcIi9yZXBvcnRzXCIpLCBgICtcbiAgICBgYW5kIHRoZSBlZGdlIG1hdGNoZXMgY2FzZS1zZW5zaXRpdmVseSB3aGVyZSBOZXh0LmpzIGRvZXMgbm90IChcIi9BUEkveFwiIGAgK1xuICAgIGBtaXNzZXMgYW4gXCJhcGkvKlwiIGJlaGF2aW9yKS5gXG4gICk7XG59XG4iXX0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An `AbortSignal` that fires when the client of a `node:http` request goes
|
|
3
|
+
* away, for the Containers shell to hand the runtime as `RuntimeRequest.signal`.
|
|
4
|
+
*/
|
|
5
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
6
|
+
export declare function clientAbortSignal(req: IncomingMessage, res: ServerResponse): AbortSignal;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientAbortSignal = clientAbortSignal;
|
|
4
|
+
function clientAbortSignal(req, res) {
|
|
5
|
+
const aborted = new AbortController();
|
|
6
|
+
req.once("aborted", () => aborted.abort());
|
|
7
|
+
// `aborted` only fires while the request body is still arriving. A client that
|
|
8
|
+
// sent a complete request and then left — a long-poll, an SSE stream — is only
|
|
9
|
+
// seen as the response's socket closing before the response finished, which
|
|
10
|
+
// is also how `next start` notices it (`res.on('close')` in
|
|
11
|
+
// `signalFromNodeResponse`).
|
|
12
|
+
res.once("close", () => {
|
|
13
|
+
if (!res.writableFinished) {
|
|
14
|
+
aborted.abort();
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
return aborted.signal;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJvcnQtc2lnbmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bnRpbWUvaHR0cC9hYm9ydC1zaWduYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFNQSw4Q0FpQkM7QUFqQkQsU0FBZ0IsaUJBQWlCLENBQy9CLEdBQW9CLEVBQ3BCLEdBQW1CO0lBRW5CLE1BQU0sT0FBTyxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7SUFDdEMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDM0MsK0VBQStFO0lBQy9FLCtFQUErRTtJQUMvRSw0RUFBNEU7SUFDNUUsNERBQTREO0lBQzVELDZCQUE2QjtJQUM3QixHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7UUFDckIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUM7QUFDeEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQW4gYEFib3J0U2lnbmFsYCB0aGF0IGZpcmVzIHdoZW4gdGhlIGNsaWVudCBvZiBhIGBub2RlOmh0dHBgIHJlcXVlc3QgZ29lc1xuICogYXdheSwgZm9yIHRoZSBDb250YWluZXJzIHNoZWxsIHRvIGhhbmQgdGhlIHJ1bnRpbWUgYXMgYFJ1bnRpbWVSZXF1ZXN0LnNpZ25hbGAuXG4gKi9cbmltcG9ydCB0eXBlIHsgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJub2RlOmh0dHBcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudEFib3J0U2lnbmFsKFxuICByZXE6IEluY29taW5nTWVzc2FnZSxcbiAgcmVzOiBTZXJ2ZXJSZXNwb25zZSxcbik6IEFib3J0U2lnbmFsIHtcbiAgY29uc3QgYWJvcnRlZCA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgcmVxLm9uY2UoXCJhYm9ydGVkXCIsICgpID0+IGFib3J0ZWQuYWJvcnQoKSk7XG4gIC8vIGBhYm9ydGVkYCBvbmx5IGZpcmVzIHdoaWxlIHRoZSByZXF1ZXN0IGJvZHkgaXMgc3RpbGwgYXJyaXZpbmcuIEEgY2xpZW50IHRoYXRcbiAgLy8gc2VudCBhIGNvbXBsZXRlIHJlcXVlc3QgYW5kIHRoZW4gbGVmdCDigJQgYSBsb25nLXBvbGwsIGFuIFNTRSBzdHJlYW0g4oCUIGlzIG9ubHlcbiAgLy8gc2VlbiBhcyB0aGUgcmVzcG9uc2UncyBzb2NrZXQgY2xvc2luZyBiZWZvcmUgdGhlIHJlc3BvbnNlIGZpbmlzaGVkLCB3aGljaFxuICAvLyBpcyBhbHNvIGhvdyBgbmV4dCBzdGFydGAgbm90aWNlcyBpdCAoYHJlcy5vbignY2xvc2UnKWAgaW5cbiAgLy8gYHNpZ25hbEZyb21Ob2RlUmVzcG9uc2VgKS5cbiAgcmVzLm9uY2UoXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgaWYgKCFyZXMud3JpdGFibGVGaW5pc2hlZCkge1xuICAgICAgYWJvcnRlZC5hYm9ydCgpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBhYm9ydGVkLnNpZ25hbDtcbn1cbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_http_1 = require("node:http");
|
|
4
|
+
const abort_signal_1 = require("./abort-signal");
|
|
5
|
+
/** A server whose handler hands each request's signal to `onSignal`. */
|
|
6
|
+
function listen(handler) {
|
|
7
|
+
const server = (0, node_http_1.createServer)((req, res) => handler((0, abort_signal_1.clientAbortSignal)(req, res), res));
|
|
8
|
+
return new Promise((resolve) => server.listen(0, "127.0.0.1", () => resolve({ server, port: server.address().port })));
|
|
9
|
+
}
|
|
10
|
+
describe("clientAbortSignal", () => {
|
|
11
|
+
let server;
|
|
12
|
+
afterEach(() => new Promise((resolve) => server ? server.close(() => resolve()) : resolve()));
|
|
13
|
+
// A long-poll: the request is complete, so `aborted` never fires on it.
|
|
14
|
+
it("fires when the client leaves after sending a complete request", async () => {
|
|
15
|
+
let signal;
|
|
16
|
+
const seen = new Promise((resolve) => {
|
|
17
|
+
void listen((s, res) => {
|
|
18
|
+
signal = s;
|
|
19
|
+
res.writeHead(200);
|
|
20
|
+
res.write("waiting");
|
|
21
|
+
s.addEventListener("abort", () => resolve());
|
|
22
|
+
}).then((listening) => {
|
|
23
|
+
server = listening.server;
|
|
24
|
+
const req = (0, node_http_1.request)({ port: listening.port, path: "/" }, (res) => {
|
|
25
|
+
res.once("data", () => req.destroy());
|
|
26
|
+
});
|
|
27
|
+
req.end();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
await seen;
|
|
31
|
+
expect(signal.aborted).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
it("stays quiet for a response that finished", async () => {
|
|
34
|
+
let signal;
|
|
35
|
+
const closed = new Promise((resolve) => {
|
|
36
|
+
void listen((s, res) => {
|
|
37
|
+
signal = s;
|
|
38
|
+
res.once("close", () => resolve());
|
|
39
|
+
res.end("done");
|
|
40
|
+
}).then((listening) => {
|
|
41
|
+
server = listening.server;
|
|
42
|
+
(0, node_http_1.request)({ port: listening.port, path: "/" }, (res) => res.resume()).end();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
await closed;
|
|
46
|
+
expect(signal.aborted).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJvcnQtc2lnbmFsLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVudGltZS9odHRwL2Fib3J0LXNpZ25hbC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEseUNBQTBEO0FBRTFELGlEQUFtRDtBQUVuRCx3RUFBd0U7QUFDeEUsU0FBUyxNQUFNLENBQ2IsT0FHUztJQUVULE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVksRUFBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUN2QyxPQUFPLENBQUMsSUFBQSxnQ0FBaUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQzFDLENBQUM7SUFDRixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDN0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEdBQUcsRUFBRSxDQUNqQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQWtCLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FDbEUsQ0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLEVBQUU7SUFDakMsSUFBSSxNQUEwQixDQUFDO0lBQy9CLFNBQVMsQ0FDUCxHQUFHLEVBQUUsQ0FDSCxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQzVCLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FDbkQsQ0FDSixDQUFDO0lBRUYsd0VBQXdFO0lBQ3hFLEVBQUUsQ0FBQywrREFBK0QsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM3RSxJQUFJLE1BQW9CLENBQUM7UUFDekIsTUFBTSxJQUFJLEdBQUcsSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN6QyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRTtnQkFDckIsTUFBTSxHQUFHLENBQUMsQ0FBQztnQkFDWCxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNuQixHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNyQixDQUFDLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDL0MsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7Z0JBQ3BCLE1BQU0sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO2dCQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFBLG1CQUFPLEVBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDL0QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLENBQUMsQ0FBQyxDQUFDO2dCQUNILEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNaLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksQ0FBQztRQUNYLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDBDQUEwQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3hELElBQUksTUFBb0IsQ0FBQztRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzNDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFO2dCQUNyQixNQUFNLEdBQUcsQ0FBQyxDQUFDO2dCQUNYLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQ25DLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbEIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7Z0JBQ3BCLE1BQU0sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO2dCQUMxQixJQUFBLG1CQUFPLEVBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUNuRCxHQUFHLENBQUMsTUFBTSxFQUFFLENBQ2IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNWLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLE1BQU0sQ0FBQztRQUNiLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVTZXJ2ZXIsIHJlcXVlc3QsIFNlcnZlciB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB0eXBlIHsgQWRkcmVzc0luZm8gfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7IGNsaWVudEFib3J0U2lnbmFsIH0gZnJvbSBcIi4vYWJvcnQtc2lnbmFsXCI7XG5cbi8qKiBBIHNlcnZlciB3aG9zZSBoYW5kbGVyIGhhbmRzIGVhY2ggcmVxdWVzdCdzIHNpZ25hbCB0byBgb25TaWduYWxgLiAqL1xuZnVuY3Rpb24gbGlzdGVuKFxuICBoYW5kbGVyOiAoXG4gICAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbiAgICByZXM6IGltcG9ydChcIm5vZGU6aHR0cFwiKS5TZXJ2ZXJSZXNwb25zZSxcbiAgKSA9PiB2b2lkLFxuKTogUHJvbWlzZTx7IHNlcnZlcjogU2VydmVyOyBwb3J0OiBudW1iZXIgfT4ge1xuICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKHJlcSwgcmVzKSA9PlxuICAgIGhhbmRsZXIoY2xpZW50QWJvcnRTaWduYWwocmVxLCByZXMpLCByZXMpLFxuICApO1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+XG4gICAgc2VydmVyLmxpc3RlbigwLCBcIjEyNy4wLjAuMVwiLCAoKSA9PlxuICAgICAgcmVzb2x2ZSh7IHNlcnZlciwgcG9ydDogKHNlcnZlci5hZGRyZXNzKCkgYXMgQWRkcmVzc0luZm8pLnBvcnQgfSksXG4gICAgKSxcbiAgKTtcbn1cblxuZGVzY3JpYmUoXCJjbGllbnRBYm9ydFNpZ25hbFwiLCAoKSA9PiB7XG4gIGxldCBzZXJ2ZXI6IFNlcnZlciB8IHVuZGVmaW5lZDtcbiAgYWZ0ZXJFYWNoKFxuICAgICgpID0+XG4gICAgICBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT5cbiAgICAgICAgc2VydmVyID8gc2VydmVyLmNsb3NlKCgpID0+IHJlc29sdmUoKSkgOiByZXNvbHZlKCksXG4gICAgICApLFxuICApO1xuXG4gIC8vIEEgbG9uZy1wb2xsOiB0aGUgcmVxdWVzdCBpcyBjb21wbGV0ZSwgc28gYGFib3J0ZWRgIG5ldmVyIGZpcmVzIG9uIGl0LlxuICBpdChcImZpcmVzIHdoZW4gdGhlIGNsaWVudCBsZWF2ZXMgYWZ0ZXIgc2VuZGluZyBhIGNvbXBsZXRlIHJlcXVlc3RcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGxldCBzaWduYWwhOiBBYm9ydFNpZ25hbDtcbiAgICBjb25zdCBzZWVuID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgIHZvaWQgbGlzdGVuKChzLCByZXMpID0+IHtcbiAgICAgICAgc2lnbmFsID0gcztcbiAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApO1xuICAgICAgICByZXMud3JpdGUoXCJ3YWl0aW5nXCIpO1xuICAgICAgICBzLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgfSkudGhlbigobGlzdGVuaW5nKSA9PiB7XG4gICAgICAgIHNlcnZlciA9IGxpc3RlbmluZy5zZXJ2ZXI7XG4gICAgICAgIGNvbnN0IHJlcSA9IHJlcXVlc3QoeyBwb3J0OiBsaXN0ZW5pbmcucG9ydCwgcGF0aDogXCIvXCIgfSwgKHJlcykgPT4ge1xuICAgICAgICAgIHJlcy5vbmNlKFwiZGF0YVwiLCAoKSA9PiByZXEuZGVzdHJveSgpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlcS5lbmQoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGF3YWl0IHNlZW47XG4gICAgZXhwZWN0KHNpZ25hbC5hYm9ydGVkKS50b0JlKHRydWUpO1xuICB9KTtcblxuICBpdChcInN0YXlzIHF1aWV0IGZvciBhIHJlc3BvbnNlIHRoYXQgZmluaXNoZWRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGxldCBzaWduYWwhOiBBYm9ydFNpZ25hbDtcbiAgICBjb25zdCBjbG9zZWQgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgdm9pZCBsaXN0ZW4oKHMsIHJlcykgPT4ge1xuICAgICAgICBzaWduYWwgPSBzO1xuICAgICAgICByZXMub25jZShcImNsb3NlXCIsICgpID0+IHJlc29sdmUoKSk7XG4gICAgICAgIHJlcy5lbmQoXCJkb25lXCIpO1xuICAgICAgfSkudGhlbigobGlzdGVuaW5nKSA9PiB7XG4gICAgICAgIHNlcnZlciA9IGxpc3RlbmluZy5zZXJ2ZXI7XG4gICAgICAgIHJlcXVlc3QoeyBwb3J0OiBsaXN0ZW5pbmcucG9ydCwgcGF0aDogXCIvXCIgfSwgKHJlcykgPT5cbiAgICAgICAgICByZXMucmVzdW1lKCksXG4gICAgICAgICkuZW5kKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBhd2FpdCBjbG9zZWQ7XG4gICAgZXhwZWN0KHNpZ25hbC5hYm9ydGVkKS50b0JlKGZhbHNlKTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IncomingHttpHeaders, IncomingMessage, Server } from "node:http";
|
|
2
|
+
import type { NextjsRuntime } from "../core";
|
|
3
|
+
/** Methods RFC 9110 allows a body on, and only when one is actually framed. */
|
|
4
|
+
export declare function hasRequestBody(req: IncomingMessage): boolean;
|
|
5
|
+
export interface RuntimeServer {
|
|
6
|
+
readonly server: Server;
|
|
7
|
+
/**
|
|
8
|
+
* Stops accepting connections, then resolves once the open ones are gone and
|
|
9
|
+
* every request's `waitUntil` work has settled.
|
|
10
|
+
*/
|
|
11
|
+
shutdown(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface RuntimeServerOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether every request comes through CloudFront, which sets
|
|
16
|
+
* `cloudfront-forwarded-proto` itself. True only on Global Containers, whose
|
|
17
|
+
* ALB is reachable through the distribution's VPC origin alone
|
|
18
|
+
* (`CDK_NEXTJS_TRUST_CLOUDFRONT_PROTO`, set by the construct). See
|
|
19
|
+
* {@link viewerHeaders}.
|
|
20
|
+
*/
|
|
21
|
+
readonly trustCloudFrontProto?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function createRuntimeServer(runtime: Pick<NextjsRuntime, "handle">, options?: RuntimeServerOptions): RuntimeServer;
|
|
24
|
+
/**
|
|
25
|
+
* The request's headers, with `x-forwarded-proto` naming the viewer's protocol
|
|
26
|
+
* when that is known.
|
|
27
|
+
*
|
|
28
|
+
* Behind CloudFront without a certificate, CloudFront reaches the ALB over plain
|
|
29
|
+
* HTTP, so the ALB's `x-forwarded-proto` is `http` for an app every viewer
|
|
30
|
+
* reaches over HTTPS. The runtime builds absolute URLs from it - `request.url`,
|
|
31
|
+
* `req.nextUrl.origin`, and the origin Next.js forwards a server action to,
|
|
32
|
+
* where CloudFront then answered 307 and `test/e2e/app-dir/action-forward-loop`
|
|
33
|
+
* failed. CloudFront's own `cloudfront-forwarded-proto` is the viewer's, but it
|
|
34
|
+
* is trusted only when every request comes through CloudFront: anywhere else a
|
|
35
|
+
* client could send it straight to the ALB and pick the scheme of URLs a cached
|
|
36
|
+
* page then serves to everyone.
|
|
37
|
+
*/
|
|
38
|
+
export declare function viewerHeaders(headers: IncomingHttpHeaders, trustCloudFrontProto: boolean | undefined): IncomingHttpHeaders;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasRequestBody = hasRequestBody;
|
|
4
|
+
exports.createRuntimeServer = createRuntimeServer;
|
|
5
|
+
exports.viewerHeaders = viewerHeaders;
|
|
6
|
+
/**
|
|
7
|
+
* The container shell's `node:http` server, and its shutdown.
|
|
8
|
+
*
|
|
9
|
+
* Its own module rather than inline in `server.mts` so it can be tested without
|
|
10
|
+
* starting the server that module starts on import.
|
|
11
|
+
*/
|
|
12
|
+
const node_http_1 = require("node:http");
|
|
13
|
+
const abort_signal_1 = require("./abort-signal");
|
|
14
|
+
const node_sink_1 = require("./node-sink");
|
|
15
|
+
/**
|
|
16
|
+
* Longer than the ALB's idle timeout (60 s by default). With Node's default of
|
|
17
|
+
* 5 s, the server closes keep-alive connections the ALB still considers open;
|
|
18
|
+
* the ALB answers the next request on one with a 502, and CloudFront caches
|
|
19
|
+
* that 502 for its error caching TTL, failing every request for the path until
|
|
20
|
+
* it expires. An ALB with a longer idle timeout needs this raised to match.
|
|
21
|
+
* https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html#connection-idle-timeout
|
|
22
|
+
*/
|
|
23
|
+
const KEEP_ALIVE_TIMEOUT_MS = 65_000;
|
|
24
|
+
/** Methods RFC 9110 allows a body on, and only when one is actually framed. */
|
|
25
|
+
function hasRequestBody(req) {
|
|
26
|
+
if (req.method === "GET" || req.method === "HEAD") {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return (req.headers["content-length"] !== undefined ||
|
|
30
|
+
req.headers["transfer-encoding"] !== undefined);
|
|
31
|
+
}
|
|
32
|
+
function createRuntimeServer(runtime, options = {}) {
|
|
33
|
+
// `handle` resolves only once the `waitUntil` work a request registered — ISR
|
|
34
|
+
// revalidation, notably — has settled, which is after its response and its
|
|
35
|
+
// connection are done. Tracked so shutdown can wait for that too.
|
|
36
|
+
const inFlight = new Set();
|
|
37
|
+
const server = (0, node_http_1.createServer)((req, res) => {
|
|
38
|
+
const handled = serve(runtime, req, res, options)
|
|
39
|
+
.catch((error) => {
|
|
40
|
+
// `NextjsRuntime.handle` answers 500 itself, so reaching this means the
|
|
41
|
+
// shell's own translation failed.
|
|
42
|
+
console.error("The container shell failed to handle a request:", error);
|
|
43
|
+
if (!res.headersSent) {
|
|
44
|
+
res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
|
|
45
|
+
}
|
|
46
|
+
res.end("Internal Server Error");
|
|
47
|
+
})
|
|
48
|
+
.finally(() => inFlight.delete(handled));
|
|
49
|
+
inFlight.add(handled);
|
|
50
|
+
});
|
|
51
|
+
server.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
|
|
52
|
+
// must exceed keepAliveTimeout, or Node can drop a connection that just
|
|
53
|
+
// started sending a request's headers
|
|
54
|
+
server.headersTimeout = KEEP_ALIVE_TIMEOUT_MS + 1_000;
|
|
55
|
+
// `server.close` alone is not enough: it calls back once the connections are
|
|
56
|
+
// gone, and a revalidation still running in `waitUntil` would be killed
|
|
57
|
+
// mid-write, losing the fresh entry.
|
|
58
|
+
const shutdown = () => new Promise((resolve) => {
|
|
59
|
+
server.close(() => {
|
|
60
|
+
void Promise.allSettled(inFlight).then(() => resolve());
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
return { server, shutdown };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The request's headers, with `x-forwarded-proto` naming the viewer's protocol
|
|
67
|
+
* when that is known.
|
|
68
|
+
*
|
|
69
|
+
* Behind CloudFront without a certificate, CloudFront reaches the ALB over plain
|
|
70
|
+
* HTTP, so the ALB's `x-forwarded-proto` is `http` for an app every viewer
|
|
71
|
+
* reaches over HTTPS. The runtime builds absolute URLs from it - `request.url`,
|
|
72
|
+
* `req.nextUrl.origin`, and the origin Next.js forwards a server action to,
|
|
73
|
+
* where CloudFront then answered 307 and `test/e2e/app-dir/action-forward-loop`
|
|
74
|
+
* failed. CloudFront's own `cloudfront-forwarded-proto` is the viewer's, but it
|
|
75
|
+
* is trusted only when every request comes through CloudFront: anywhere else a
|
|
76
|
+
* client could send it straight to the ALB and pick the scheme of URLs a cached
|
|
77
|
+
* page then serves to everyone.
|
|
78
|
+
*/
|
|
79
|
+
function viewerHeaders(headers, trustCloudFrontProto) {
|
|
80
|
+
const viewerProto = headers["cloudfront-forwarded-proto"];
|
|
81
|
+
if (!trustCloudFrontProto || typeof viewerProto !== "string") {
|
|
82
|
+
return headers;
|
|
83
|
+
}
|
|
84
|
+
return { ...headers, "x-forwarded-proto": viewerProto };
|
|
85
|
+
}
|
|
86
|
+
async function serve(runtime, req, res, options) {
|
|
87
|
+
await runtime.handle({
|
|
88
|
+
method: req.method ?? "GET",
|
|
89
|
+
url: req.url ?? "/",
|
|
90
|
+
headers: viewerHeaders(req.headers, options.trustCloudFrontProto),
|
|
91
|
+
body: hasRequestBody(req) ? req : undefined,
|
|
92
|
+
remoteAddress: req.socket.remoteAddress,
|
|
93
|
+
// TLS terminates at the ALB (Regional) or CloudFront (Global); the hop to
|
|
94
|
+
// this container is plaintext HTTP/1.1.
|
|
95
|
+
encrypted: false,
|
|
96
|
+
signal: (0, abort_signal_1.clientAbortSignal)(req, res),
|
|
97
|
+
}, new node_sink_1.NodeResponseSink(res));
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVudGltZS9odHRwL25vZGUtc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNEJBLHdDQVFDO0FBc0JELGtEQXVDQztBQWdCRCxzQ0FTQztBQTFIRDs7Ozs7R0FLRztBQUNILHlDQUF5QztBQVF6QyxpREFBbUQ7QUFDbkQsMkNBQStDO0FBRS9DOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLHFCQUFxQixHQUFHLE1BQU0sQ0FBQztBQUVyQywrRUFBK0U7QUFDL0UsU0FBZ0IsY0FBYyxDQUFDLEdBQW9CO0lBQ2pELElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxLQUFLLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUNsRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxPQUFPLENBQ0wsR0FBRyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLFNBQVM7UUFDM0MsR0FBRyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLFNBQVMsQ0FDL0MsQ0FBQztBQUNKLENBQUM7QUFzQkQsU0FBZ0IsbUJBQW1CLENBQ2pDLE9BQXNDLEVBQ3RDLFVBQWdDLEVBQUU7SUFFbEMsOEVBQThFO0lBQzlFLDJFQUEyRTtJQUMzRSxrRUFBa0U7SUFDbEUsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQWlCLENBQUM7SUFFMUMsTUFBTSxNQUFNLEdBQUcsSUFBQSx3QkFBWSxFQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUM7YUFDOUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDZix3RUFBd0U7WUFDeEUsa0NBQWtDO1lBQ2xDLE9BQU8sQ0FBQyxLQUFLLENBQUMsaURBQWlELEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDeEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDckIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxjQUFjLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDO1lBQ3RFLENBQUM7WUFDRCxHQUFHLENBQUMsR0FBRyxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDO2FBQ0QsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUMzQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hCLENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLGdCQUFnQixHQUFHLHFCQUFxQixDQUFDO0lBQ2hELHdFQUF3RTtJQUN4RSxzQ0FBc0M7SUFDdEMsTUFBTSxDQUFDLGNBQWMsR0FBRyxxQkFBcUIsR0FBRyxLQUFLLENBQUM7SUFFdEQsNkVBQTZFO0lBQzdFLHdFQUF3RTtJQUN4RSxxQ0FBcUM7SUFDckMsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQ3BCLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLEVBQUU7UUFDNUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7WUFDaEIsS0FBSyxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzFELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFTCxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQzlCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsU0FBZ0IsYUFBYSxDQUMzQixPQUE0QixFQUM1QixvQkFBeUM7SUFFekMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDMUQsSUFBSSxDQUFDLG9CQUFvQixJQUFJLE9BQU8sV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzdELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFDMUQsQ0FBQztBQUVELEtBQUssVUFBVSxLQUFLLENBQ2xCLE9BQXNDLEVBQ3RDLEdBQW9CLEVBQ3BCLEdBQW1CLEVBQ25CLE9BQTZCO0lBRTdCLE1BQU0sT0FBTyxDQUFDLE1BQU0sQ0FDbEI7UUFDRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sSUFBSSxLQUFLO1FBQzNCLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUc7UUFDbkIsT0FBTyxFQUFFLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQztRQUNqRSxJQUFJLEVBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVM7UUFDM0MsYUFBYSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYTtRQUN2QywwRUFBMEU7UUFDMUUsd0NBQXdDO1FBQ3hDLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLE1BQU0sRUFBRSxJQUFBLGdDQUFpQixFQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7S0FDcEMsRUFDRCxJQUFJLDRCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUMxQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIGNvbnRhaW5lciBzaGVsbCdzIGBub2RlOmh0dHBgIHNlcnZlciwgYW5kIGl0cyBzaHV0ZG93bi5cbiAqXG4gKiBJdHMgb3duIG1vZHVsZSByYXRoZXIgdGhhbiBpbmxpbmUgaW4gYHNlcnZlci5tdHNgIHNvIGl0IGNhbiBiZSB0ZXN0ZWQgd2l0aG91dFxuICogc3RhcnRpbmcgdGhlIHNlcnZlciB0aGF0IG1vZHVsZSBzdGFydHMgb24gaW1wb3J0LlxuICovXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgdHlwZSB7XG4gIEluY29taW5nSHR0cEhlYWRlcnMsXG4gIEluY29taW5nTWVzc2FnZSxcbiAgU2VydmVyLFxuICBTZXJ2ZXJSZXNwb25zZSxcbn0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHR5cGUgeyBOZXh0anNSdW50aW1lIH0gZnJvbSBcIi4uL2NvcmVcIjtcbmltcG9ydCB7IGNsaWVudEFib3J0U2lnbmFsIH0gZnJvbSBcIi4vYWJvcnQtc2lnbmFsXCI7XG5pbXBvcnQgeyBOb2RlUmVzcG9uc2VTaW5rIH0gZnJvbSBcIi4vbm9kZS1zaW5rXCI7XG5cbi8qKlxuICogTG9uZ2VyIHRoYW4gdGhlIEFMQidzIGlkbGUgdGltZW91dCAoNjAgcyBieSBkZWZhdWx0KS4gV2l0aCBOb2RlJ3MgZGVmYXVsdCBvZlxuICogNSBzLCB0aGUgc2VydmVyIGNsb3NlcyBrZWVwLWFsaXZlIGNvbm5lY3Rpb25zIHRoZSBBTEIgc3RpbGwgY29uc2lkZXJzIG9wZW47XG4gKiB0aGUgQUxCIGFuc3dlcnMgdGhlIG5leHQgcmVxdWVzdCBvbiBvbmUgd2l0aCBhIDUwMiwgYW5kIENsb3VkRnJvbnQgY2FjaGVzXG4gKiB0aGF0IDUwMiBmb3IgaXRzIGVycm9yIGNhY2hpbmcgVFRMLCBmYWlsaW5nIGV2ZXJ5IHJlcXVlc3QgZm9yIHRoZSBwYXRoIHVudGlsXG4gKiBpdCBleHBpcmVzLiBBbiBBTEIgd2l0aCBhIGxvbmdlciBpZGxlIHRpbWVvdXQgbmVlZHMgdGhpcyByYWlzZWQgdG8gbWF0Y2guXG4gKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWxhc3RpY2xvYWRiYWxhbmNpbmcvbGF0ZXN0L2FwcGxpY2F0aW9uL2VkaXQtbG9hZC1iYWxhbmNlci1hdHRyaWJ1dGVzLmh0bWwjY29ubmVjdGlvbi1pZGxlLXRpbWVvdXRcbiAqL1xuY29uc3QgS0VFUF9BTElWRV9USU1FT1VUX01TID0gNjVfMDAwO1xuXG4vKiogTWV0aG9kcyBSRkMgOTExMCBhbGxvd3MgYSBib2R5IG9uLCBhbmQgb25seSB3aGVuIG9uZSBpcyBhY3R1YWxseSBmcmFtZWQuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzUmVxdWVzdEJvZHkocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBib29sZWFuIHtcbiAgaWYgKHJlcS5tZXRob2QgPT09IFwiR0VUXCIgfHwgcmVxLm1ldGhvZCA9PT0gXCJIRUFEXCIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIChcbiAgICByZXEuaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdICE9PSB1bmRlZmluZWQgfHxcbiAgICByZXEuaGVhZGVyc1tcInRyYW5zZmVyLWVuY29kaW5nXCJdICE9PSB1bmRlZmluZWRcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSdW50aW1lU2VydmVyIHtcbiAgcmVhZG9ubHkgc2VydmVyOiBTZXJ2ZXI7XG4gIC8qKlxuICAgKiBTdG9wcyBhY2NlcHRpbmcgY29ubmVjdGlvbnMsIHRoZW4gcmVzb2x2ZXMgb25jZSB0aGUgb3BlbiBvbmVzIGFyZSBnb25lIGFuZFxuICAgKiBldmVyeSByZXF1ZXN0J3MgYHdhaXRVbnRpbGAgd29yayBoYXMgc2V0dGxlZC5cbiAgICovXG4gIHNodXRkb3duKCk6IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVudGltZVNlcnZlck9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciBldmVyeSByZXF1ZXN0IGNvbWVzIHRocm91Z2ggQ2xvdWRGcm9udCwgd2hpY2ggc2V0c1xuICAgKiBgY2xvdWRmcm9udC1mb3J3YXJkZWQtcHJvdG9gIGl0c2VsZi4gVHJ1ZSBvbmx5IG9uIEdsb2JhbCBDb250YWluZXJzLCB3aG9zZVxuICAgKiBBTEIgaXMgcmVhY2hhYmxlIHRocm91Z2ggdGhlIGRpc3RyaWJ1dGlvbidzIFZQQyBvcmlnaW4gYWxvbmVcbiAgICogKGBDREtfTkVYVEpTX1RSVVNUX0NMT1VERlJPTlRfUFJPVE9gLCBzZXQgYnkgdGhlIGNvbnN0cnVjdCkuIFNlZVxuICAgKiB7QGxpbmsgdmlld2VySGVhZGVyc30uXG4gICAqL1xuICByZWFkb25seSB0cnVzdENsb3VkRnJvbnRQcm90bz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSdW50aW1lU2VydmVyKFxuICBydW50aW1lOiBQaWNrPE5leHRqc1J1bnRpbWUsIFwiaGFuZGxlXCI+LFxuICBvcHRpb25zOiBSdW50aW1lU2VydmVyT3B0aW9ucyA9IHt9LFxuKTogUnVudGltZVNlcnZlciB7XG4gIC8vIGBoYW5kbGVgIHJlc29sdmVzIG9ubHkgb25jZSB0aGUgYHdhaXRVbnRpbGAgd29yayBhIHJlcXVlc3QgcmVnaXN0ZXJlZCDigJQgSVNSXG4gIC8vIHJldmFsaWRhdGlvbiwgbm90YWJseSDigJQgaGFzIHNldHRsZWQsIHdoaWNoIGlzIGFmdGVyIGl0cyByZXNwb25zZSBhbmQgaXRzXG4gIC8vIGNvbm5lY3Rpb24gYXJlIGRvbmUuIFRyYWNrZWQgc28gc2h1dGRvd24gY2FuIHdhaXQgZm9yIHRoYXQgdG9vLlxuICBjb25zdCBpbkZsaWdodCA9IG5ldyBTZXQ8UHJvbWlzZTx2b2lkPj4oKTtcblxuICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgaGFuZGxlZCA9IHNlcnZlKHJ1bnRpbWUsIHJlcSwgcmVzLCBvcHRpb25zKVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAvLyBgTmV4dGpzUnVudGltZS5oYW5kbGVgIGFuc3dlcnMgNTAwIGl0c2VsZiwgc28gcmVhY2hpbmcgdGhpcyBtZWFucyB0aGVcbiAgICAgICAgLy8gc2hlbGwncyBvd24gdHJhbnNsYXRpb24gZmFpbGVkLlxuICAgICAgICBjb25zb2xlLmVycm9yKFwiVGhlIGNvbnRhaW5lciBzaGVsbCBmYWlsZWQgdG8gaGFuZGxlIGEgcmVxdWVzdDpcIiwgZXJyb3IpO1xuICAgICAgICBpZiAoIXJlcy5oZWFkZXJzU2VudCkge1xuICAgICAgICAgIHJlcy53cml0ZUhlYWQoNTAwLCB7IFwiQ29udGVudC1UeXBlXCI6IFwidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOFwiIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJlcy5lbmQoXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIik7XG4gICAgICB9KVxuICAgICAgLmZpbmFsbHkoKCkgPT4gaW5GbGlnaHQuZGVsZXRlKGhhbmRsZWQpKTtcbiAgICBpbkZsaWdodC5hZGQoaGFuZGxlZCk7XG4gIH0pO1xuICBzZXJ2ZXIua2VlcEFsaXZlVGltZW91dCA9IEtFRVBfQUxJVkVfVElNRU9VVF9NUztcbiAgLy8gbXVzdCBleGNlZWQga2VlcEFsaXZlVGltZW91dCwgb3IgTm9kZSBjYW4gZHJvcCBhIGNvbm5lY3Rpb24gdGhhdCBqdXN0XG4gIC8vIHN0YXJ0ZWQgc2VuZGluZyBhIHJlcXVlc3QncyBoZWFkZXJzXG4gIHNlcnZlci5oZWFkZXJzVGltZW91dCA9IEtFRVBfQUxJVkVfVElNRU9VVF9NUyArIDFfMDAwO1xuXG4gIC8vIGBzZXJ2ZXIuY2xvc2VgIGFsb25lIGlzIG5vdCBlbm91Z2g6IGl0IGNhbGxzIGJhY2sgb25jZSB0aGUgY29ubmVjdGlvbnMgYXJlXG4gIC8vIGdvbmUsIGFuZCBhIHJldmFsaWRhdGlvbiBzdGlsbCBydW5uaW5nIGluIGB3YWl0VW50aWxgIHdvdWxkIGJlIGtpbGxlZFxuICAvLyBtaWQtd3JpdGUsIGxvc2luZyB0aGUgZnJlc2ggZW50cnkuXG4gIGNvbnN0IHNodXRkb3duID0gKCkgPT5cbiAgICBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgc2VydmVyLmNsb3NlKCgpID0+IHtcbiAgICAgICAgdm9pZCBQcm9taXNlLmFsbFNldHRsZWQoaW5GbGlnaHQpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gIHJldHVybiB7IHNlcnZlciwgc2h1dGRvd24gfTtcbn1cblxuLyoqXG4gKiBUaGUgcmVxdWVzdCdzIGhlYWRlcnMsIHdpdGggYHgtZm9yd2FyZGVkLXByb3RvYCBuYW1pbmcgdGhlIHZpZXdlcidzIHByb3RvY29sXG4gKiB3aGVuIHRoYXQgaXMga25vd24uXG4gKlxuICogQmVoaW5kIENsb3VkRnJvbnQgd2l0aG91dCBhIGNlcnRpZmljYXRlLCBDbG91ZEZyb250IHJlYWNoZXMgdGhlIEFMQiBvdmVyIHBsYWluXG4gKiBIVFRQLCBzbyB0aGUgQUxCJ3MgYHgtZm9yd2FyZGVkLXByb3RvYCBpcyBgaHR0cGAgZm9yIGFuIGFwcCBldmVyeSB2aWV3ZXJcbiAqIHJlYWNoZXMgb3ZlciBIVFRQUy4gVGhlIHJ1bnRpbWUgYnVpbGRzIGFic29sdXRlIFVSTHMgZnJvbSBpdCAtIGByZXF1ZXN0LnVybGAsXG4gKiBgcmVxLm5leHRVcmwub3JpZ2luYCwgYW5kIHRoZSBvcmlnaW4gTmV4dC5qcyBmb3J3YXJkcyBhIHNlcnZlciBhY3Rpb24gdG8sXG4gKiB3aGVyZSBDbG91ZEZyb250IHRoZW4gYW5zd2VyZWQgMzA3IGFuZCBgdGVzdC9lMmUvYXBwLWRpci9hY3Rpb24tZm9yd2FyZC1sb29wYFxuICogZmFpbGVkLiBDbG91ZEZyb250J3Mgb3duIGBjbG91ZGZyb250LWZvcndhcmRlZC1wcm90b2AgaXMgdGhlIHZpZXdlcidzLCBidXQgaXRcbiAqIGlzIHRydXN0ZWQgb25seSB3aGVuIGV2ZXJ5IHJlcXVlc3QgY29tZXMgdGhyb3VnaCBDbG91ZEZyb250OiBhbnl3aGVyZSBlbHNlIGFcbiAqIGNsaWVudCBjb3VsZCBzZW5kIGl0IHN0cmFpZ2h0IHRvIHRoZSBBTEIgYW5kIHBpY2sgdGhlIHNjaGVtZSBvZiBVUkxzIGEgY2FjaGVkXG4gKiBwYWdlIHRoZW4gc2VydmVzIHRvIGV2ZXJ5b25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlld2VySGVhZGVycyhcbiAgaGVhZGVyczogSW5jb21pbmdIdHRwSGVhZGVycyxcbiAgdHJ1c3RDbG91ZEZyb250UHJvdG86IGJvb2xlYW4gfCB1bmRlZmluZWQsXG4pOiBJbmNvbWluZ0h0dHBIZWFkZXJzIHtcbiAgY29uc3Qgdmlld2VyUHJvdG8gPSBoZWFkZXJzW1wiY2xvdWRmcm9udC1mb3J3YXJkZWQtcHJvdG9cIl07XG4gIGlmICghdHJ1c3RDbG91ZEZyb250UHJvdG8gfHwgdHlwZW9mIHZpZXdlclByb3RvICE9PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cbiAgcmV0dXJuIHsgLi4uaGVhZGVycywgXCJ4LWZvcndhcmRlZC1wcm90b1wiOiB2aWV3ZXJQcm90byB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzZXJ2ZShcbiAgcnVudGltZTogUGljazxOZXh0anNSdW50aW1lLCBcImhhbmRsZVwiPixcbiAgcmVxOiBJbmNvbWluZ01lc3NhZ2UsXG4gIHJlczogU2VydmVyUmVzcG9uc2UsXG4gIG9wdGlvbnM6IFJ1bnRpbWVTZXJ2ZXJPcHRpb25zLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IHJ1bnRpbWUuaGFuZGxlKFxuICAgIHtcbiAgICAgIG1ldGhvZDogcmVxLm1ldGhvZCA/PyBcIkdFVFwiLFxuICAgICAgdXJsOiByZXEudXJsID8/IFwiL1wiLFxuICAgICAgaGVhZGVyczogdmlld2VySGVhZGVycyhyZXEuaGVhZGVycywgb3B0aW9ucy50cnVzdENsb3VkRnJvbnRQcm90byksXG4gICAgICBib2R5OiBoYXNSZXF1ZXN0Qm9keShyZXEpID8gcmVxIDogdW5kZWZpbmVkLFxuICAgICAgcmVtb3RlQWRkcmVzczogcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzLFxuICAgICAgLy8gVExTIHRlcm1pbmF0ZXMgYXQgdGhlIEFMQiAoUmVnaW9uYWwpIG9yIENsb3VkRnJvbnQgKEdsb2JhbCk7IHRoZSBob3AgdG9cbiAgICAgIC8vIHRoaXMgY29udGFpbmVyIGlzIHBsYWludGV4dCBIVFRQLzEuMS5cbiAgICAgIGVuY3J5cHRlZDogZmFsc2UsXG4gICAgICBzaWduYWw6IGNsaWVudEFib3J0U2lnbmFsKHJlcSwgcmVzKSxcbiAgICB9LFxuICAgIG5ldyBOb2RlUmVzcG9uc2VTaW5rKHJlcyksXG4gICk7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_http_1 = require("node:http");
|
|
4
|
+
const node_server_1 = require("./node-server");
|
|
5
|
+
/** A real server around a stub runtime, and one request to it. */
|
|
6
|
+
async function withServer(handle, run) {
|
|
7
|
+
const { server, shutdown } = (0, node_server_1.createRuntimeServer)({ handle });
|
|
8
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
9
|
+
const { port } = server.address();
|
|
10
|
+
const get = () => new Promise((resolve, reject) => {
|
|
11
|
+
// No keep-alive agent, so the connection closes with the response and
|
|
12
|
+
// `server.close` is not left waiting on an idle socket.
|
|
13
|
+
const req = (0, node_http_1.request)({ port, host: "127.0.0.1", path: "/", agent: false }, (res) => {
|
|
14
|
+
let body = "";
|
|
15
|
+
res.setEncoding("utf-8");
|
|
16
|
+
res.on("data", (chunk) => (body += chunk));
|
|
17
|
+
res.on("end", () => resolve({ status: res.statusCode, body }));
|
|
18
|
+
});
|
|
19
|
+
req.on("error", reject);
|
|
20
|
+
req.end();
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
return await run(get, shutdown);
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
server.close();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
describe("viewerHeaders", () => {
|
|
30
|
+
// Global Containers without a certificate: CloudFront reaches the ALB over
|
|
31
|
+
// HTTP, so the ALB says `http` while the viewer used HTTPS.
|
|
32
|
+
const behindCloudFront = {
|
|
33
|
+
host: "d111.cloudfront.net",
|
|
34
|
+
"x-forwarded-proto": "http",
|
|
35
|
+
"cloudfront-forwarded-proto": "https",
|
|
36
|
+
};
|
|
37
|
+
it("takes the viewer's protocol from CloudFront when every request comes through it", () => {
|
|
38
|
+
expect((0, node_server_1.viewerHeaders)(behindCloudFront, true)["x-forwarded-proto"]).toBe("https");
|
|
39
|
+
});
|
|
40
|
+
it("ignores cloudfront-forwarded-proto a client could have sent the ALB itself", () => {
|
|
41
|
+
expect((0, node_server_1.viewerHeaders)(behindCloudFront, false)["x-forwarded-proto"]).toBe("http");
|
|
42
|
+
expect((0, node_server_1.viewerHeaders)(behindCloudFront, undefined)).toBe(behindCloudFront);
|
|
43
|
+
});
|
|
44
|
+
it("keeps x-forwarded-proto when CloudFront sent no protocol", () => {
|
|
45
|
+
const headers = { host: "alb.example.test", "x-forwarded-proto": "http" };
|
|
46
|
+
expect((0, node_server_1.viewerHeaders)(headers, true)).toBe(headers);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("hasRequestBody", () => {
|
|
50
|
+
const message = (method, headers = {}) => ({ method, headers });
|
|
51
|
+
it("is false for GET and HEAD, whatever their framing says", () => {
|
|
52
|
+
expect((0, node_server_1.hasRequestBody)(message("GET", { "content-length": "3" }))).toBe(false);
|
|
53
|
+
expect((0, node_server_1.hasRequestBody)(message("HEAD", { "transfer-encoding": "chunked" }))).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
it("is true only for a body that is actually framed", () => {
|
|
56
|
+
expect((0, node_server_1.hasRequestBody)(message("POST"))).toBe(false);
|
|
57
|
+
expect((0, node_server_1.hasRequestBody)(message("POST", { "content-length": "0" }))).toBe(true);
|
|
58
|
+
expect((0, node_server_1.hasRequestBody)(message("DELETE", { "transfer-encoding": "chunked" }))).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("createRuntimeServer", () => {
|
|
62
|
+
it("answers a plain 500 when the shell itself fails", async () => {
|
|
63
|
+
const error = jest.spyOn(console, "error").mockImplementation(() => { });
|
|
64
|
+
try {
|
|
65
|
+
const response = await withServer(async () => {
|
|
66
|
+
throw new Error("translation failed");
|
|
67
|
+
}, (get) => get());
|
|
68
|
+
expect(response).toEqual({ status: 500, body: "Internal Server Error" });
|
|
69
|
+
expect(String(error.mock.calls[0][0])).toMatch(/container shell failed/);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
error.mockRestore();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
// What an ECS rolling deploy does: SIGTERM while an ISR regeneration is still
|
|
76
|
+
// running in `waitUntil`, after its response has gone out.
|
|
77
|
+
it("shuts down only once in-flight waitUntil work has settled", async () => {
|
|
78
|
+
let release;
|
|
79
|
+
const waitUntilWork = new Promise((resolve) => (release = resolve));
|
|
80
|
+
const handle = async (_request, sink) => {
|
|
81
|
+
sink.begin({ statusCode: 200, headers: {}, cookies: [] }).end("ok");
|
|
82
|
+
await waitUntilWork;
|
|
83
|
+
};
|
|
84
|
+
await withServer(handle, async (get, shutdown) => {
|
|
85
|
+
expect(await get()).toEqual({ status: 200, body: "ok" });
|
|
86
|
+
let stopped = false;
|
|
87
|
+
const stopping = shutdown().then(() => (stopped = true));
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
89
|
+
expect(stopped).toBe(false);
|
|
90
|
+
release();
|
|
91
|
+
await stopping;
|
|
92
|
+
expect(stopped).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1zZXJ2ZXIudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydW50aW1lL2h0dHAvbm9kZS1zZXJ2ZXIudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUNBLHlDQUFtRDtBQUduRCwrQ0FJdUI7QUFJdkIsa0VBQWtFO0FBQ2xFLEtBQUssVUFBVSxVQUFVLENBQ3ZCLE1BQWMsRUFDZCxHQUdlO0lBRWYsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxJQUFBLGlDQUFtQixFQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM3RCxNQUFNLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM3RSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDLE9BQU8sRUFBaUIsQ0FBQztJQUNqRCxNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FDZixJQUFJLE9BQU8sQ0FBb0MsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDakUsc0VBQXNFO1FBQ3RFLHdEQUF3RDtRQUN4RCxNQUFNLEdBQUcsR0FBRyxJQUFBLG1CQUFXLEVBQ3JCLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQ3BELENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDTixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7WUFDZCxHQUFHLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pCLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQzNDLEdBQUcsQ0FB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QUFRLENBQUM7WUFDZixNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgSW5jb21pbmdNZXNzYWdlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHsgcmVxdWVzdCBhcyBodHRwUmVxdWVzdCB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB0eXBlIHsgQWRkcmVzc0luZm8gfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB0eXBlIHsgTmV4dGpzUnVudGltZSB9IGZyb20gXCIuLi9jb3JlXCI7XG5pbXBvcnQge1xuICBjcmVhdGVSdW50aW1lU2VydmVyLFxuICBoYXNSZXF1ZXN0Qm9keSxcbiAgdmlld2VySGVhZGVycyxcbn0gZnJvbSBcIi4vbm9kZS1zZXJ2ZXJcIjtcblxudHlwZSBIYW5kbGUgPSBOZXh0anNSdW50aW1lW1wiaGFuZGxlXCJdO1xuXG4vKiogQSByZWFsIHNlcnZlciBhcm91bmQgYSBzdHViIHJ1bnRpbWUsIGFuZCBvbmUgcmVxdWVzdCB0byBpdC4gKi9cbmFzeW5jIGZ1bmN0aW9uIHdpdGhTZXJ2ZXI8VD4oXG4gIGhhbmRsZTogSGFuZGxlLFxuICBydW46IChcbiAgICBnZXQ6ICgpID0+IFByb21pc2U8eyBzdGF0dXM/OiBudW1iZXI7IGJvZHk6IHN0cmluZyB9PixcbiAgICBzaHV0ZG93bjogKCkgPT4gUHJvbWlzZTx2b2lkPixcbiAgKSA9PiBQcm9taXNlPFQ+LFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IHsgc2VydmVyLCBzaHV0ZG93biB9ID0gY3JlYXRlUnVudGltZVNlcnZlcih7IGhhbmRsZSB9KTtcbiAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNlcnZlci5saXN0ZW4oMCwgXCIxMjcuMC4wLjFcIiwgcmVzb2x2ZSkpO1xuICBjb25zdCB7IHBvcnQgfSA9IHNlcnZlci5hZGRyZXNzKCkgYXMgQWRkcmVzc0luZm87XG4gIGNvbnN0IGdldCA9ICgpID0+XG4gICAgbmV3IFByb21pc2U8eyBzdGF0dXM/OiBudW1iZXI7IGJvZHk6IHN0cmluZyB9PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBObyBrZWVwLWFsaXZlIGFnZW50LCBzbyB0aGUgY29ubmVjdGlvbiBjbG9zZXMgd2l0aCB0aGUgcmVzcG9uc2UgYW5kXG4gICAgICAvLyBgc2VydmVyLmNsb3NlYCBpcyBub3QgbGVmdCB3YWl0aW5nIG9uIGFuIGlkbGUgc29ja2V0LlxuICAgICAgY29uc3QgcmVxID0gaHR0cFJlcXVlc3QoXG4gICAgICAgIHsgcG9ydCwgaG9zdDogXCIxMjcuMC4wLjFcIiwgcGF0aDogXCIvXCIsIGFnZW50OiBmYWxzZSB9LFxuICAgICAgICAocmVzKSA9PiB7XG4gICAgICAgICAgbGV0IGJvZHkgPSBcIlwiO1xuICAgICAgICAgIHJlcy5zZXRFbmNvZGluZyhcInV0Zi04XCIpO1xuICAgICAgICAgIHJlcy5vbihcImRhdGFcIiwgKGNodW5rKSA9PiAoYm9keSArPSBjaHVuaykpO1xuICAgICAgICAgIHJlcy5vbihcImVuZFwiLCAoKSA9PiByZXNvbHZlKHsgc3RhdHVzOiByZXMuc3RhdHVzQ29kZSwgYm9keSB9KSk7XG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgcmVxLm9uKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICAgIHJlcS5lbmQoKTtcbiAgICB9KTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcnVuKGdldCwgc2h1dGRvd24pO1xuICB9IGZpbmFsbHkge1xuICAgIHNlcnZlci5jbG9zZSgpO1xuICB9XG59XG5cbmRlc2NyaWJlKFwidmlld2VySGVhZGVyc1wiLCAoKSA9PiB7XG4gIC8vIEdsb2JhbCBDb250YWluZXJzIHdpdGhvdXQgYSBjZXJ0aWZpY2F0ZTogQ2xvdWRGcm9udCByZWFjaGVzIHRoZSBBTEIgb3ZlclxuICAvLyBIVFRQLCBzbyB0aGUgQUxCIHNheXMgYGh0dHBgIHdoaWxlIHRoZSB2aWV3ZXIgdXNlZCBIVFRQUy5cbiAgY29uc3QgYmVoaW5kQ2xvdWRGcm9udCA9IHtcbiAgICBob3N0OiBcImQxMTEuY2xvdWRmcm9udC5uZXRcIixcbiAgICBcIngtZm9yd2FyZGVkLXByb3RvXCI6IFwiaHR0cFwiLFxuICAgIFwiY2xvdWRmcm9udC1mb3J3YXJkZWQtcHJvdG9cIjogXCJodHRwc1wiLFxuICB9O1xuXG4gIGl0KFwidGFrZXMgdGhlIHZpZXdlcidzIHByb3RvY29sIGZyb20gQ2xvdWRGcm9udCB3aGVuIGV2ZXJ5IHJlcXVlc3QgY29tZXMgdGhyb3VnaCBpdFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHZpZXdlckhlYWRlcnMoYmVoaW5kQ2xvdWRGcm9udCwgdHJ1ZSlbXCJ4LWZvcndhcmRlZC1wcm90b1wiXSkudG9CZShcbiAgICAgIFwiaHR0cHNcIixcbiAgICApO1xuICB9KTtcblxuICBpdChcImlnbm9yZXMgY2xvdWRmcm9udC1mb3J3YXJkZWQtcHJvdG8gYSBjbGllbnQgY291bGQgaGF2ZSBzZW50IHRoZSBBTEIgaXRzZWxmXCIsICgpID0+IHtcbiAgICBleHBlY3Qodmlld2VySGVhZGVycyhiZWhpbmRDbG91ZEZyb250LCBmYWxzZSlbXCJ4LWZvcndhcmRlZC1wcm90b1wiXSkudG9CZShcbiAgICAgIFwiaHR0cFwiLFxuICAgICk7XG4gICAgZXhwZWN0KHZpZXdlckhlYWRlcnMoYmVoaW5kQ2xvdWRGcm9udCwgdW5kZWZpbmVkKSkudG9CZShiZWhpbmRDbG91ZEZyb250KTtcbiAgfSk7XG5cbiAgaXQoXCJrZWVwcyB4LWZvcndhcmRlZC1wcm90byB3aGVuIENsb3VkRnJvbnQgc2VudCBubyBwcm90b2NvbFwiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZGVycyA9IHsgaG9zdDogXCJhbGIuZXhhbXBsZS50ZXN0XCIsIFwieC1mb3J3YXJkZWQtcHJvdG9cIjogXCJodHRwXCIgfTtcbiAgICBleHBlY3Qodmlld2VySGVhZGVycyhoZWFkZXJzLCB0cnVlKSkudG9CZShoZWFkZXJzKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJoYXNSZXF1ZXN0Qm9keVwiLCAoKSA9PiB7XG4gIGNvbnN0IG1lc3NhZ2UgPSAobWV0aG9kOiBzdHJpbmcsIGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fSkgPT5cbiAgICAoeyBtZXRob2QsIGhlYWRlcnMgfSkgYXMgdW5rbm93biBhcyBJbmNvbWluZ01lc3NhZ2U7XG5cbiAgaXQoXCJpcyBmYWxzZSBmb3IgR0VUIGFuZCBIRUFELCB3aGF0ZXZlciB0aGVpciBmcmFtaW5nIHNheXNcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChoYXNSZXF1ZXN0Qm9keShtZXNzYWdlKFwiR0VUXCIsIHsgXCJjb250ZW50LWxlbmd0aFwiOiBcIjNcIiB9KSkpLnRvQmUoXG4gICAgICBmYWxzZSxcbiAgICApO1xuICAgIGV4cGVjdChcbiAgICAgIGhhc1JlcXVlc3RCb2R5KG1lc3NhZ2UoXCJIRUFEXCIsIHsgXCJ0cmFuc2Zlci1lbmNvZGluZ1wiOiBcImNodW5rZWRcIiB9KSksXG4gICAgKS50b0JlKGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoXCJpcyB0cnVlIG9ubHkgZm9yIGEgYm9keSB0aGF0IGlzIGFjdHVhbGx5IGZyYW1lZFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KGhhc1JlcXVlc3RCb2R5KG1lc3NhZ2UoXCJQT1NUXCIpKSkudG9CZShmYWxzZSk7XG4gICAgZXhwZWN0KGhhc1JlcXVlc3RCb2R5KG1lc3NhZ2UoXCJQT1NUXCIsIHsgXCJjb250ZW50LWxlbmd0aFwiOiBcIjBcIiB9KSkpLnRvQmUoXG4gICAgICB0cnVlLFxuICAgICk7XG4gICAgZXhwZWN0KFxuICAgICAgaGFzUmVxdWVzdEJvZHkobWVzc2FnZShcIkRFTEVURVwiLCB7IFwidHJhbnNmZXItZW5jb2RpbmdcIjogXCJjaHVua2VkXCIgfSkpLFxuICAgICkudG9CZSh0cnVlKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJjcmVhdGVSdW50aW1lU2VydmVyXCIsICgpID0+IHtcbiAgaXQoXCJhbnN3ZXJzIGEgcGxhaW4gNTAwIHdoZW4gdGhlIHNoZWxsIGl0c2VsZiBmYWlsc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXJyb3IgPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwiZXJyb3JcIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB3aXRoU2VydmVyKFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidHJhbnNsYXRpb24gZmFpbGVkXCIpO1xuICAgICAgICB9LFxuICAgICAgICAoZ2V0KSA9PiBnZXQoKSxcbiAgICAgICk7XG4gICAgICBleHBlY3QocmVzcG9uc2UpLnRvRXF1YWwoeyBzdGF0dXM6IDUwMCwgYm9keTogXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIiB9KTtcbiAgICAgIGV4cGVjdChTdHJpbmcoZXJyb3IubW9jay5jYWxsc1swXVswXSkpLnRvTWF0Y2goL2NvbnRhaW5lciBzaGVsbCBmYWlsZWQvKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgZXJyb3IubW9ja1Jlc3RvcmUoKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIFdoYXQgYW4gRUNTIHJvbGxpbmcgZGVwbG95IGRvZXM6IFNJR1RFUk0gd2hpbGUgYW4gSVNSIHJlZ2VuZXJhdGlvbiBpcyBzdGlsbFxuICAvLyBydW5uaW5nIGluIGB3YWl0VW50aWxgLCBhZnRlciBpdHMgcmVzcG9uc2UgaGFzIGdvbmUgb3V0LlxuICBpdChcInNodXRzIGRvd24gb25seSBvbmNlIGluLWZsaWdodCB3YWl0VW50aWwgd29yayBoYXMgc2V0dGxlZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgbGV0IHJlbGVhc2UhOiAoKSA9PiB2b2lkO1xuICAgIGNvbnN0IHdhaXRVbnRpbFdvcmsgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gKHJlbGVhc2UgPSByZXNvbHZlKSk7XG4gICAgY29uc3QgaGFuZGxlOiBIYW5kbGUgPSBhc3luYyAoX3JlcXVlc3QsIHNpbmspID0+IHtcbiAgICAgIHNpbmsuYmVnaW4oeyBzdGF0dXNDb2RlOiAyMDAsIGhlYWRlcnM6IHt9LCBjb29raWVzOiBbXSB9KS5lbmQoXCJva1wiKTtcbiAgICAgIGF3YWl0IHdhaXRVbnRpbFdvcms7XG4gICAgfTtcbiAgICBhd2FpdCB3aXRoU2VydmVyKGhhbmRsZSwgYXN5bmMgKGdldCwgc2h1dGRvd24pID0+IHtcbiAgICAgIGV4cGVjdChhd2FpdCBnZXQoKSkudG9FcXVhbCh7IHN0YXR1czogMjAwLCBib2R5OiBcIm9rXCIgfSk7XG5cbiAgICAgIGxldCBzdG9wcGVkID0gZmFsc2U7XG4gICAgICBjb25zdCBzdG9wcGluZyA9IHNodXRkb3duKCkudGhlbigoKSA9PiAoc3RvcHBlZCA9IHRydWUpKTtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDIwKSk7XG4gICAgICBleHBlY3Qoc3RvcHBlZCkudG9CZShmYWxzZSk7XG5cbiAgICAgIHJlbGVhc2UoKTtcbiAgICAgIGF3YWl0IHN0b3BwaW5nO1xuICAgICAgZXhwZWN0KHN0b3BwZWQpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The container shell's {@link ResponseSink}: the head goes to a real
|
|
3
|
+
* `node:http` `ServerResponse`, which is then the stream the body is piped into.
|
|
4
|
+
*
|
|
5
|
+
* Its own module rather than inline in `server.mts` so it can be tested without
|
|
6
|
+
* starting the server that module starts on import.
|
|
7
|
+
*/
|
|
8
|
+
import type { ServerResponse } from "node:http";
|
|
9
|
+
import type { Writable } from "node:stream";
|
|
10
|
+
import type { ResponseHead } from "./response";
|
|
11
|
+
import type { ResponseSink } from "./sink";
|
|
12
|
+
export declare class NodeResponseSink implements ResponseSink {
|
|
13
|
+
private readonly res;
|
|
14
|
+
constructor(res: ServerResponse);
|
|
15
|
+
begin(head: ResponseHead): Writable;
|
|
16
|
+
}
|