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