cdk-nextjs 0.6.2 → 0.7.1

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