@geostrategists/react-router-aws 2.2.1 → 2.3.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -60,6 +60,73 @@ export const handler = createAPIGatewayV2RequestHandler({
60
60
  > It does not allow tree-shaking and will include all gateway adapters in your bundle.
61
61
  > For optimal bundle size, always use the method specific to your gateway:
62
62
 
63
+ ### Request host & CSRF (`getHost`)
64
+
65
+ React Router derives the host used for its built-in cross-origin (CSRF) check on
66
+ action requests from the constructed request URL (`new URL(request.url).host`),
67
+ comparing it against the incoming `Origin` header. It is therefore important that
68
+ the adapter builds that host from a source you trust.
69
+
70
+ By default the adapters build the host from the `x-forwarded-host` header
71
+ (falling back to the `host`/`Host` header). The resolved value is always
72
+ sanitized (invalid characters stripped, port validated) before use.
73
+
74
+ If the default forwarded host is not the host the browser actually sees, use the
75
+ `getHost` option to derive it yourself. The most common case is a **Lambda
76
+ Function URL behind CloudFront**: `event.requestContext.domainName` is always the
77
+ internal `*.lambda-url.<region>.on.aws` host (and cannot be overridden), and
78
+ CloudFront does not forward the viewer's host to the origin — the managed
79
+ `AllViewerExceptHostHeader` policy (recommended for Function URL / API Gateway
80
+ origins) sets `Host` to the origin domain. So you must forward the viewer host
81
+ yourself, typically with a CloudFront Function on the viewer request that copies
82
+ it into a header, then read that header via `getHost`:
83
+
84
+ ```javascript
85
+ // CloudFront Function (viewer request): copy the viewer host into a custom header.
86
+ // Always overwrite (or delete) it so a client can't spoof x-viewer-host.
87
+ function handler(event) {
88
+ var host = event.request.headers.host;
89
+ if (host) {
90
+ event.request.headers["x-viewer-host"] = { value: host.value };
91
+ } else {
92
+ delete event.request.headers["x-viewer-host"];
93
+ }
94
+ return event.request;
95
+ }
96
+ ```
97
+
98
+ ```javascript
99
+ // lambda-handler.ts
100
+ import * as build from "virtual:react-router/server-build";
101
+ import { createFunctionURLRequestHandler } from "@geostrategists/react-router-aws";
102
+
103
+ export const handler = createFunctionURLRequestHandler({
104
+ build,
105
+ getHost: (event) => event.headers["x-viewer-host"],
106
+ });
107
+ ```
108
+
109
+ (If you copy the viewer host into `x-forwarded-host` instead, the default already
110
+ picks it up and `getHost` isn't needed.)
111
+
112
+ `getHost` receives the (correctly typed) gateway event and may return a host
113
+ string, or `undefined`/`null` to fall back to the default `x-forwarded-host`
114
+ behavior. It is supported by all handlers (API Gateway v1, API Gateway v2, Lambda
115
+ Function URL buffered & streaming, and ALB). For example, to prefer the
116
+ API Gateway request-context domain name: `getHost: (event) => event.requestContext.domainName`.
117
+
118
+ > [!IMPORTANT]
119
+ > The default currently uses the `x-forwarded-host` header, which is
120
+ > **client-controlled** and can be spoofed. Because that host drives React
121
+ > Router's CSRF check, trusting it should be a deliberate choice. To make the
122
+ > safe option the default (and to align with the upstream
123
+ > `@react-router/architect` adapter), the default **will change to the
124
+ > AWS-provided, non-spoofable request-context domain name
125
+ > (`event.requestContext.domainName`) in the next major version**. After that,
126
+ > relying on `x-forwarded-host` (or any other forwarded header) becomes an
127
+ > explicit opt-in via `getHost`. Setups where the request-context host is not the
128
+ > browser-facing host (e.g. Function URLs behind CloudFront) must set `getHost`.
129
+
63
130
  ### Streaming support for Lambda Function URLs
64
131
 
65
132
  React Router and React allow you to stream responses from the server to the client, reducing the TTFB (time to first byte)
package/dist/index.cjs ADDED
@@ -0,0 +1,352 @@
1
+ /**
2
+ * @geostrategists/react-router-aws v2.3.0-rc.0
3
+ *
4
+ * Copyright (c) Geostrategists Consulting GmbH
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ *
9
+ * @license MIT
10
+ */
11
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
12
+ let react_router = require("react-router");
13
+ let _react_router_node = require("@react-router/node");
14
+ let url = require("url");
15
+ //#region src/binaryTypes.ts
16
+ /**
17
+ * Common binary MIME types
18
+ * @see https://github.com/architect/functions/blob/45254fc1936a1794c185aac07e9889b241a2e5c6/src/http/helpers/binary-types.js
19
+ */
20
+ const binaryTypes = [
21
+ "application/octet-stream",
22
+ "application/epub+zip",
23
+ "application/msword",
24
+ "application/pdf",
25
+ "application/rtf",
26
+ "application/vnd.amazon.ebook",
27
+ "application/vnd.ms-excel",
28
+ "application/vnd.ms-powerpoint",
29
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
30
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
31
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
32
+ "font/otf",
33
+ "font/woff",
34
+ "font/woff2",
35
+ "image/avif",
36
+ "image/bmp",
37
+ "image/gif",
38
+ "image/jpeg",
39
+ "image/png",
40
+ "image/tiff",
41
+ "image/vnd.microsoft.icon",
42
+ "image/webp",
43
+ "audio/3gpp",
44
+ "audio/aac",
45
+ "audio/basic",
46
+ "audio/mpeg",
47
+ "audio/ogg",
48
+ "audio/wav",
49
+ "audio/webm",
50
+ "audio/x-aiff",
51
+ "audio/x-midi",
52
+ "audio/x-wav",
53
+ "video/3gpp",
54
+ "video/mp2t",
55
+ "video/mpeg",
56
+ "video/ogg",
57
+ "video/quicktime",
58
+ "video/webm",
59
+ "video/x-msvideo",
60
+ "application/java-archive",
61
+ "application/vnd.apple.installer+xml",
62
+ "application/x-7z-compressed",
63
+ "application/x-apple-diskimage",
64
+ "application/x-bzip",
65
+ "application/x-bzip2",
66
+ "application/x-gzip",
67
+ "application/x-java-archive",
68
+ "application/x-rar-compressed",
69
+ "application/x-tar",
70
+ "application/x-zip",
71
+ "application/zip"
72
+ ];
73
+ function isBinaryType(contentType) {
74
+ if (!contentType) return false;
75
+ const [test] = contentType.split(";");
76
+ return binaryTypes.includes(test);
77
+ }
78
+ //#endregion
79
+ //#region src/adapters/host.ts
80
+ /**
81
+ * Resolves the host used to build the `Request` URL from a raw host value
82
+ * (e.g. an `x-forwarded-host`/`host` header or an API Gateway domain name).
83
+ *
84
+ * React Router derives the host for its built-in cross-origin (CSRF) check on
85
+ * action requests from `new URL(request.url).host`, so the host constructed
86
+ * here must be trustworthy and well-formed. Invalid characters are stripped and
87
+ * the port is validated to avoid constructing a malformed URL (or leaking a
88
+ * spoofed host) from a garbled header value.
89
+ *
90
+ * Mirrors the hardening done by the upstream `@react-router/architect` adapter.
91
+ */
92
+ function resolveHost(rawHost) {
93
+ const [rawHostname = "", portStr] = (rawHost ?? "").split(":");
94
+ const hostname = rawHostname.split(/[\\/?#@]/)[0] || "localhost";
95
+ const hostPort = Number.parseInt(portStr ?? "", 10);
96
+ const port = Number.isSafeInteger(hostPort) ? hostPort : void 0;
97
+ return `${hostname}${port ? `:${port}` : ""}`;
98
+ }
99
+ //#endregion
100
+ //#region src/adapters/api-gateway-v1.ts
101
+ function createReactRouterRequestAPIGatewayV1(event, getHost) {
102
+ const host = resolveHost(getHost?.(event) ?? (event.headers["x-forwarded-host"] || event.headers.Host));
103
+ const scheme = event.headers["x-forwarded-proto"] || "http";
104
+ const rawQueryString = new url.URLSearchParams(event.queryStringParameters).toString();
105
+ const search = rawQueryString.length > 0 ? `?${rawQueryString}` : "";
106
+ const url$2 = new URL(event.path + search, `${scheme}://${host}`);
107
+ const isFormData = event.headers["content-type"]?.includes("multipart/form-data");
108
+ const controller = new AbortController();
109
+ return new Request(url$2.href, {
110
+ method: event.requestContext.httpMethod,
111
+ headers: createReactRouterHeadersAPIGatewayV1(event.headers),
112
+ signal: controller.signal,
113
+ body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body || void 0
114
+ });
115
+ }
116
+ function createReactRouterHeadersAPIGatewayV1(requestHeaders) {
117
+ const headers = new Headers();
118
+ for (const [header, value] of Object.entries(requestHeaders)) if (value) headers.append(header, value);
119
+ return headers;
120
+ }
121
+ async function sendReactRouterResponseAPIGatewayV1(nodeResponse) {
122
+ const isBase64Encoded = isBinaryType(nodeResponse.headers.get("Content-Type"));
123
+ let body;
124
+ if (nodeResponse.body) if (isBase64Encoded) body = await (0, _react_router_node.readableStreamToString)(nodeResponse.body, "base64");
125
+ else body = await nodeResponse.text();
126
+ return {
127
+ statusCode: nodeResponse.status,
128
+ headers: Object.fromEntries(nodeResponse.headers.entries()),
129
+ body: body || "",
130
+ isBase64Encoded
131
+ };
132
+ }
133
+ const apiGatewayV1Adapter = {
134
+ wrapHandler: (handler) => (e) => handler(e),
135
+ createReactRouterRequest: createReactRouterRequestAPIGatewayV1,
136
+ sendReactRouterResponse: sendReactRouterResponseAPIGatewayV1
137
+ };
138
+ //#endregion
139
+ //#region src/adapters/api-gateway-v2.ts
140
+ function createReactRouterRequestAPIGateywayV2(event, getHost) {
141
+ const host = resolveHost(getHost?.(event) ?? (event.headers["x-forwarded-host"] || event.headers.host));
142
+ const search = event.rawQueryString.length ? `?${event.rawQueryString}` : "";
143
+ const scheme = event.headers["x-forwarded-proto"] || "http";
144
+ const url = new URL(event.rawPath + search, `${scheme}://${host}`);
145
+ const isFormData = event.headers["content-type"]?.includes("multipart/form-data");
146
+ const controller = new AbortController();
147
+ return new Request(url.href, {
148
+ method: event.requestContext.http.method,
149
+ headers: createReactRouterHeadersAPIGatewayV2(event.headers, event.cookies),
150
+ signal: controller.signal,
151
+ body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body
152
+ });
153
+ }
154
+ function createReactRouterHeadersAPIGatewayV2(requestHeaders, requestCookies) {
155
+ const headers = new Headers();
156
+ for (const [header, value] of Object.entries(requestHeaders)) if (value) headers.append(header, value);
157
+ if (requestCookies) headers.append("Cookie", requestCookies.join("; "));
158
+ return headers;
159
+ }
160
+ function extractAPIGatewayV2ResponseMetadata(nodeResponse) {
161
+ const cookies = nodeResponse.headers.getSetCookie();
162
+ if (cookies.length) nodeResponse.headers.delete("Set-Cookie");
163
+ return {
164
+ statusCode: nodeResponse.status,
165
+ headers: Object.fromEntries(nodeResponse.headers.entries()),
166
+ cookies
167
+ };
168
+ }
169
+ async function sendReactRouterResponseAPIGatewayV2(nodeResponse) {
170
+ const result = extractAPIGatewayV2ResponseMetadata(nodeResponse);
171
+ result.isBase64Encoded = isBinaryType(nodeResponse.headers.get("Content-Type"));
172
+ if (nodeResponse.body) if (result.isBase64Encoded) result.body = await (0, _react_router_node.readableStreamToString)(nodeResponse.body, "base64");
173
+ else result.body = await nodeResponse.text();
174
+ return result;
175
+ }
176
+ const apiGatewayV2Adapter = {
177
+ wrapHandler: (handler) => (e) => handler(e),
178
+ createReactRouterRequest: createReactRouterRequestAPIGateywayV2,
179
+ sendReactRouterResponse: sendReactRouterResponseAPIGatewayV2
180
+ };
181
+ //#endregion
182
+ //#region src/adapters/application-load-balancer.ts
183
+ function createReactRouterRequestALB(event, getHost) {
184
+ const headers = event?.headers || {};
185
+ const host = resolveHost(getHost?.(event) ?? (headers["x-forwarded-host"] || headers.Host));
186
+ const scheme = headers["x-forwarded-proto"] || "http";
187
+ const rawQueryString = new url.URLSearchParams(event.queryStringParameters).toString();
188
+ const search = rawQueryString.length > 0 ? `?${rawQueryString}` : "";
189
+ const url$1 = new URL(event.path + search, `${scheme}://${host}`);
190
+ const isFormData = headers["content-type"]?.includes("multipart/form-data");
191
+ const controller = new AbortController();
192
+ return new Request(url$1.href, {
193
+ method: event.httpMethod,
194
+ headers: createReactRouterHeadersALB(headers),
195
+ signal: controller.signal,
196
+ body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body || void 0
197
+ });
198
+ }
199
+ function createReactRouterHeadersALB(requestHeaders) {
200
+ const headers = new Headers();
201
+ for (const [header, value] of Object.entries(requestHeaders)) if (value) headers.append(header, value);
202
+ return headers;
203
+ }
204
+ async function sendReactRouterResponseALB(nodeResponse) {
205
+ const isBase64Encoded = isBinaryType(nodeResponse.headers.get("Content-Type"));
206
+ let body;
207
+ if (nodeResponse.body) if (isBase64Encoded) body = await (0, _react_router_node.readableStreamToString)(nodeResponse.body, "base64");
208
+ else body = await nodeResponse.text();
209
+ return {
210
+ statusCode: nodeResponse.status,
211
+ headers: Object.fromEntries(nodeResponse.headers.entries()),
212
+ body: body || "",
213
+ isBase64Encoded
214
+ };
215
+ }
216
+ const applicationLoadBalancerAdapter = {
217
+ wrapHandler: (handler) => (e) => handler(e),
218
+ createReactRouterRequest: createReactRouterRequestALB,
219
+ sendReactRouterResponse: sendReactRouterResponseALB
220
+ };
221
+ //#endregion
222
+ //#region src/adapters/function-url-streaming.ts
223
+ const emptyStream = () => new ReadableStream({ start(controller) {
224
+ controller.enqueue("");
225
+ controller.close();
226
+ } });
227
+ const sendReactRouterResponseFunctionUrlStreaming = async (response, responseStream) => {
228
+ const metadata = extractAPIGatewayV2ResponseMetadata(response);
229
+ let body = response.body;
230
+ if (!body) body = emptyStream();
231
+ const httpResponseStream = awslambda.HttpResponseStream.from(responseStream, metadata);
232
+ await (0, _react_router_node.writeReadableStreamToWritable)(body, httpResponseStream);
233
+ };
234
+ const functionUrlStreamingAdapter = {
235
+ wrapHandler: awslambda.streamifyResponse,
236
+ createReactRouterRequest: createReactRouterRequestAPIGateywayV2,
237
+ sendReactRouterResponse: sendReactRouterResponseFunctionUrlStreaming
238
+ };
239
+ //#endregion
240
+ //#region src/server.ts
241
+ /**
242
+ * Returns a request handler for AWS API Gateway V1
243
+ *
244
+ */
245
+ /**
246
+ * Returns a request handler for AWS API Gateway V1 events.
247
+ *
248
+ * @param options - The handler options, including the React Router server build,
249
+ * optional getLoadContext function, and mode string.
250
+ * @returns An AWS API Gateway V1 handler compatible with APIGatewayProxyHandler.
251
+ */
252
+ function createAPIGatewayV1RequestHandler(options) {
253
+ return createRequestHandlerForAdapter(apiGatewayV1Adapter, options);
254
+ }
255
+ /**
256
+ * Returns a request handler for AWS API Gateway V2 events.
257
+ *
258
+ * @param options - The handler options, including the React Router server build,
259
+ * optional getLoadContext function, and mode string.
260
+ * @returns An AWS API Gateway V2 handler compatible with APIGatewayProxyHandlerV2.
261
+ */
262
+ function createAPIGatewayV2RequestHandler(options) {
263
+ return createRequestHandlerForAdapter(apiGatewayV2Adapter, options);
264
+ }
265
+ /**
266
+ * Returns a request handler for AWS Application Load Balancer events.
267
+ *
268
+ * @param options - The handler options, including the React Router server build,
269
+ * optional getLoadContext function, and mode string.
270
+ * @returns An AWS ALB handler compatible with ALBHandler.
271
+ */
272
+ function createALBRequestHandler(options) {
273
+ return createRequestHandlerForAdapter(applicationLoadBalancerAdapter, options);
274
+ }
275
+ /**
276
+ * Returns a request handler for AWS Lambda Function URL events (invoke mode BUFFERED).
277
+ *
278
+ * @param options - The handler options, including the React Router server build,
279
+ * optional getLoadContext function, and mode string.
280
+ * @returns An AWS Lambda Function URL handler compatible with Lambda Function URLs with InvokeMode BUFFERED.
281
+ */
282
+ function createFunctionURLRequestHandler(options) {
283
+ return createRequestHandlerForAdapter(apiGatewayV2Adapter, options);
284
+ }
285
+ /**
286
+ * Returns a request handler for AWS Lambda Function URL events (invoke mode RESPONSE_STREAM).
287
+ *
288
+ * @param options - The handler options, including the React Router server build,
289
+ * optional getLoadContext function, and mode string.
290
+ * @returns A streaming AWS Lambda Function URL handler compatible with Lambda Function URLs with InvokeMode RESPONSE_STREAM.
291
+ */
292
+ function createFunctionURLStreamingRequestHandler(options) {
293
+ return createRequestHandlerForAdapter(functionUrlStreamingAdapter, options);
294
+ }
295
+ function createRequestHandlerForAdapter(awsAdapter, { build, getLoadContext, mode = process.env.NODE_ENV, getHost }) {
296
+ const handleRequest = (0, react_router.createRequestHandler)(build, mode);
297
+ return awsAdapter.wrapHandler(async (event, res) => {
298
+ let request;
299
+ try {
300
+ request = awsAdapter.createReactRouterRequest(event, getHost);
301
+ } catch (e) {
302
+ return await awsAdapter.sendReactRouterResponse(new Response(`Bad Request: ${e instanceof Error ? e.message : e}`, { status: 400 }), res);
303
+ }
304
+ const loadContext = await getLoadContext?.(event);
305
+ const response = await handleRequest(request, loadContext);
306
+ return await awsAdapter.sendReactRouterResponse(response, res);
307
+ });
308
+ }
309
+ //#endregion
310
+ //#region src/legacy.ts
311
+ let AWSProxy = /* @__PURE__ */ function(AWSProxy) {
312
+ AWSProxy["APIGatewayV1"] = "APIGatewayV1";
313
+ AWSProxy["APIGatewayV2"] = "APIGatewayV2";
314
+ AWSProxy["ALB"] = "ALB";
315
+ AWSProxy["FunctionURL"] = "FunctionURL";
316
+ AWSProxy["FunctionURLStreaming"] = "FunctionURLStreaming";
317
+ return AWSProxy;
318
+ }({});
319
+ /**
320
+ * Returns a request handler for AWS that serves the response using React Router.
321
+ *
322
+ * @deprecated Use one of the gateway-specific create*RequestHandler methods instead for better tree-shaking.
323
+ * - `createAPIGatewayV1RequestHandler`
324
+ * - `createAPIGatewayV2RequestHandler`
325
+ * - `createALBRequestHandler`
326
+ * - `createFunctionURLRequestHandler`
327
+ * - `createFunctionURLStreamingRequestHandler`
328
+ */
329
+ function createRequestHandler(options) {
330
+ const { awsProxy = "APIGatewayV2", ...opts } = options;
331
+ switch (awsProxy) {
332
+ case "APIGatewayV1": return createAPIGatewayV1RequestHandler(opts);
333
+ case "APIGatewayV2": return createAPIGatewayV2RequestHandler(opts);
334
+ case "ALB": return createALBRequestHandler(opts);
335
+ case "FunctionURL": return createFunctionURLRequestHandler(opts);
336
+ case "FunctionURLStreaming": return createFunctionURLStreamingRequestHandler(opts);
337
+ default: return assertNever(awsProxy, `Unsupported buffered AWS Proxy type: ${awsProxy}`);
338
+ }
339
+ }
340
+ function assertNever(_x, message) {
341
+ throw new Error(message);
342
+ }
343
+ //#endregion
344
+ exports.AWSProxy = AWSProxy;
345
+ exports.createALBRequestHandler = createALBRequestHandler;
346
+ exports.createAPIGatewayV1RequestHandler = createAPIGatewayV1RequestHandler;
347
+ exports.createAPIGatewayV2RequestHandler = createAPIGatewayV2RequestHandler;
348
+ exports.createFunctionURLRequestHandler = createFunctionURLRequestHandler;
349
+ exports.createFunctionURLStreamingRequestHandler = createFunctionURLStreamingRequestHandler;
350
+ exports.createRequestHandler = createRequestHandler;
351
+
352
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["URLSearchParams","url","URLSearchParams","url"],"sources":["../src/binaryTypes.ts","../src/adapters/host.ts","../src/adapters/api-gateway-v1.ts","../src/adapters/api-gateway-v2.ts","../src/adapters/application-load-balancer.ts","../src/adapters/function-url-streaming.ts","../src/server.ts","../src/legacy.ts"],"sourcesContent":["// TODO: check if we can replace this with https://www.npmjs.com/package/mime-types\n\n/**\n * Common binary MIME types\n * @see https://github.com/architect/functions/blob/45254fc1936a1794c185aac07e9889b241a2e5c6/src/http/helpers/binary-types.js\n */\nconst binaryTypes = [\n \"application/octet-stream\",\n // Docs\n \"application/epub+zip\",\n \"application/msword\",\n \"application/pdf\",\n \"application/rtf\",\n \"application/vnd.amazon.ebook\",\n \"application/vnd.ms-excel\",\n \"application/vnd.ms-powerpoint\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n // Fonts\n \"font/otf\",\n \"font/woff\",\n \"font/woff2\",\n // Images\n \"image/avif\",\n \"image/bmp\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/tiff\",\n \"image/vnd.microsoft.icon\",\n \"image/webp\",\n // Audio\n \"audio/3gpp\",\n \"audio/aac\",\n \"audio/basic\",\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"audio/webm\",\n \"audio/x-aiff\",\n \"audio/x-midi\",\n \"audio/x-wav\",\n // Video\n \"video/3gpp\",\n \"video/mp2t\",\n \"video/mpeg\",\n \"video/ogg\",\n \"video/quicktime\",\n \"video/webm\",\n \"video/x-msvideo\",\n // Archives\n \"application/java-archive\",\n \"application/vnd.apple.installer+xml\",\n \"application/x-7z-compressed\",\n \"application/x-apple-diskimage\",\n \"application/x-bzip\",\n \"application/x-bzip2\",\n \"application/x-gzip\",\n \"application/x-java-archive\",\n \"application/x-rar-compressed\",\n \"application/x-tar\",\n \"application/x-zip\",\n \"application/zip\",\n];\n\nexport function isBinaryType(contentType: string | null | undefined): boolean {\n if (!contentType) {\n return false;\n }\n const [test] = contentType.split(\";\");\n return binaryTypes.includes(test);\n}\n","/**\n * Resolves the host used to build the `Request` URL from a raw host value\n * (e.g. an `x-forwarded-host`/`host` header or an API Gateway domain name).\n *\n * React Router derives the host for its built-in cross-origin (CSRF) check on\n * action requests from `new URL(request.url).host`, so the host constructed\n * here must be trustworthy and well-formed. Invalid characters are stripped and\n * the port is validated to avoid constructing a malformed URL (or leaking a\n * spoofed host) from a garbled header value.\n *\n * Mirrors the hardening done by the upstream `@react-router/architect` adapter.\n */\nexport function resolveHost(rawHost: string | undefined | null): string {\n const [rawHostname = \"\", portStr] = (rawHost ?? \"\").split(\":\");\n const hostname = rawHostname.split(/[\\\\/?#@]/)[0] || \"localhost\";\n const hostPort = Number.parseInt(portStr ?? \"\", 10);\n const port = Number.isSafeInteger(hostPort) ? hostPort : undefined;\n return `${hostname}${port ? `:${port}` : \"\"}`;\n}\n","import { readableStreamToString } from \"@react-router/node\";\nimport type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, APIGatewayProxyResult } from \"aws-lambda\";\nimport { URLSearchParams } from \"url\";\n\nimport { isBinaryType } from \"../binaryTypes\";\nimport { resolveHost } from \"./host\";\nimport type { GetHostFunction, ReactRouterAdapter } from \"./index\";\n\nfunction createReactRouterRequestAPIGatewayV1(\n event: APIGatewayProxyEvent,\n getHost?: GetHostFunction<APIGatewayProxyEvent>,\n): Request {\n const rawHost = getHost?.(event) ?? (event.headers[\"x-forwarded-host\"] || event.headers.Host);\n const host = resolveHost(rawHost);\n const scheme = event.headers[\"x-forwarded-proto\"] || \"http\";\n\n const rawQueryString = new URLSearchParams(event.queryStringParameters as Record<string, string>).toString();\n const search = rawQueryString.length > 0 ? `?${rawQueryString}` : \"\";\n const url = new URL(event.path + search, `${scheme}://${host}`);\n\n const isFormData = event.headers[\"content-type\"]?.includes(\"multipart/form-data\");\n // Note: No current way to abort these for AWS, but our router expects\n // requests to contain a signal, so it can detect aborted requests\n const controller = new AbortController();\n\n return new Request(url.href, {\n method: event.requestContext.httpMethod,\n headers: createReactRouterHeadersAPIGatewayV1(event.headers),\n signal: controller.signal,\n body:\n event.body && event.isBase64Encoded\n ? isFormData\n ? Buffer.from(event.body, \"base64\")\n : Buffer.from(event.body, \"base64\").toString()\n : event.body || undefined,\n });\n}\n\nfunction createReactRouterHeadersAPIGatewayV1(requestHeaders: APIGatewayProxyEventHeaders): Headers {\n const headers = new Headers();\n\n for (const [header, value] of Object.entries(requestHeaders)) {\n if (value) {\n headers.append(header, value);\n }\n }\n\n return headers;\n}\n\nasync function sendReactRouterResponseAPIGatewayV1(nodeResponse: Response): Promise<APIGatewayProxyResult> {\n const contentType = nodeResponse.headers.get(\"Content-Type\");\n const isBase64Encoded = isBinaryType(contentType);\n let body: string | undefined;\n\n if (nodeResponse.body) {\n if (isBase64Encoded) {\n body = await readableStreamToString(nodeResponse.body, \"base64\");\n } else {\n body = await nodeResponse.text();\n }\n }\n\n return {\n statusCode: nodeResponse.status,\n headers: Object.fromEntries(nodeResponse.headers.entries()),\n body: body || \"\",\n isBase64Encoded,\n };\n}\n\nexport type ApiGatewayV1Adapter = ReactRouterAdapter<APIGatewayProxyEvent, APIGatewayProxyResult>;\n\nexport const apiGatewayV1Adapter: ApiGatewayV1Adapter = {\n wrapHandler: (handler) => (e) => handler(e),\n createReactRouterRequest: createReactRouterRequestAPIGatewayV1,\n sendReactRouterResponse: sendReactRouterResponseAPIGatewayV1,\n};\n","import { readableStreamToString } from \"@react-router/node\";\nimport type {\n APIGatewayProxyEventHeaders,\n APIGatewayProxyEventV2,\n APIGatewayProxyStructuredResultV2,\n} from \"aws-lambda\";\n\nimport { isBinaryType } from \"../binaryTypes\";\nimport { resolveHost } from \"./host\";\nimport type { GetHostFunction, ReactRouterAdapter } from \"./index\";\n\nexport function createReactRouterRequestAPIGateywayV2(\n event: APIGatewayProxyEventV2,\n getHost?: GetHostFunction<APIGatewayProxyEventV2>,\n): Request {\n const rawHost = getHost?.(event) ?? (event.headers[\"x-forwarded-host\"] || event.headers.host);\n const host = resolveHost(rawHost);\n const search = event.rawQueryString.length ? `?${event.rawQueryString}` : \"\";\n const scheme = event.headers[\"x-forwarded-proto\"] || \"http\";\n\n const url = new URL(event.rawPath + search, `${scheme}://${host}`);\n const isFormData = event.headers[\"content-type\"]?.includes(\"multipart/form-data\");\n // Note: No current way to abort these for AWS, but our router expects\n // requests to contain a signal, so it can detect aborted requests\n const controller = new AbortController();\n\n return new Request(url.href, {\n method: event.requestContext.http.method,\n headers: createReactRouterHeadersAPIGatewayV2(event.headers, event.cookies),\n signal: controller.signal,\n body:\n event.body && event.isBase64Encoded\n ? isFormData\n ? Buffer.from(event.body, \"base64\")\n : Buffer.from(event.body, \"base64\").toString()\n : event.body,\n });\n}\n\nfunction createReactRouterHeadersAPIGatewayV2(\n requestHeaders: APIGatewayProxyEventHeaders,\n requestCookies?: string[],\n): Headers {\n const headers = new Headers();\n\n for (const [header, value] of Object.entries(requestHeaders)) {\n if (value) {\n headers.append(header, value);\n }\n }\n\n if (requestCookies) {\n headers.append(\"Cookie\", requestCookies.join(\"; \"));\n }\n\n return headers;\n}\n\nexport function extractAPIGatewayV2ResponseMetadata(nodeResponse: Response): {\n statusCode: number;\n headers: Record<string, string>;\n cookies: string[];\n} {\n // AWS API Gateway will send back set-cookies outside of response headers.\n const cookies = nodeResponse.headers.getSetCookie();\n if (cookies.length) {\n nodeResponse.headers.delete(\"Set-Cookie\");\n }\n\n return {\n statusCode: nodeResponse.status,\n headers: Object.fromEntries(nodeResponse.headers.entries()),\n cookies,\n };\n}\n\nasync function sendReactRouterResponseAPIGatewayV2(nodeResponse: Response): Promise<APIGatewayProxyStructuredResultV2> {\n const result: APIGatewayProxyStructuredResultV2 = extractAPIGatewayV2ResponseMetadata(nodeResponse);\n\n const contentType = nodeResponse.headers.get(\"Content-Type\");\n\n result.isBase64Encoded = isBinaryType(contentType);\n\n if (nodeResponse.body) {\n if (result.isBase64Encoded) {\n result.body = await readableStreamToString(nodeResponse.body, \"base64\");\n } else {\n result.body = await nodeResponse.text();\n }\n }\n\n return result;\n}\n\nexport type ApiGatewayV2Adapter = ReactRouterAdapter<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>;\n\nexport const apiGatewayV2Adapter: ApiGatewayV2Adapter = {\n wrapHandler: (handler) => (e) => handler(e),\n createReactRouterRequest: createReactRouterRequestAPIGateywayV2,\n sendReactRouterResponse: sendReactRouterResponseAPIGatewayV2,\n};\n","import { readableStreamToString } from \"@react-router/node\";\nimport type { ALBEvent, ALBEventHeaders, ALBResult } from \"aws-lambda\";\nimport { URLSearchParams } from \"url\";\n\nimport { isBinaryType } from \"../binaryTypes\";\nimport { resolveHost } from \"./host\";\nimport type { GetHostFunction, ReactRouterAdapter } from \"./index\";\n\nfunction createReactRouterRequestALB(event: ALBEvent, getHost?: GetHostFunction<ALBEvent>): Request {\n const headers = event?.headers || {};\n const host = resolveHost(getHost?.(event) ?? (headers[\"x-forwarded-host\"] || headers.Host));\n const scheme = headers[\"x-forwarded-proto\"] || \"http\";\n\n const rawQueryString = new URLSearchParams(event.queryStringParameters as Record<string, string>).toString();\n const search = rawQueryString.length > 0 ? `?${rawQueryString}` : \"\";\n const url = new URL(event.path + search, `${scheme}://${host}`);\n\n const isFormData = headers[\"content-type\"]?.includes(\"multipart/form-data\");\n\n // Note: No current way to abort these for AWS, but our router expects\n // requests to contain a signal, so it can detect aborted requests\n const controller = new AbortController();\n\n return new Request(url.href, {\n method: event.httpMethod,\n headers: createReactRouterHeadersALB(headers),\n signal: controller.signal,\n body:\n event.body && event.isBase64Encoded\n ? isFormData\n ? Buffer.from(event.body, \"base64\")\n : Buffer.from(event.body, \"base64\").toString()\n : event.body || undefined,\n });\n}\n\nfunction createReactRouterHeadersALB(requestHeaders: ALBEventHeaders): Headers {\n const headers = new Headers();\n\n for (const [header, value] of Object.entries(requestHeaders)) {\n if (value) {\n headers.append(header, value);\n }\n }\n\n return headers;\n}\n\nasync function sendReactRouterResponseALB(nodeResponse: Response): Promise<ALBResult> {\n const contentType = nodeResponse.headers.get(\"Content-Type\");\n const isBase64Encoded = isBinaryType(contentType);\n let body: string | undefined;\n\n if (nodeResponse.body) {\n if (isBase64Encoded) {\n body = await readableStreamToString(nodeResponse.body, \"base64\");\n } else {\n body = await nodeResponse.text();\n }\n }\n\n return {\n statusCode: nodeResponse.status,\n headers: Object.fromEntries(nodeResponse.headers.entries()),\n body: body || \"\",\n isBase64Encoded,\n };\n}\n\nexport type ApplicationLoadBalancerAdapter = ReactRouterAdapter<ALBEvent, ALBResult>;\n\nexport const applicationLoadBalancerAdapter: ApplicationLoadBalancerAdapter = {\n wrapHandler: (handler) => (e) => handler(e),\n createReactRouterRequest: createReactRouterRequestALB,\n sendReactRouterResponse: sendReactRouterResponseALB,\n};\n","import { writeReadableStreamToWritable } from \"@react-router/node\";\nimport type { LambdaFunctionURLEvent } from \"aws-lambda\";\nimport type { StreamifyHandler } from \"aws-lambda/handler\";\n\nimport { createReactRouterRequestAPIGateywayV2, extractAPIGatewayV2ResponseMetadata } from \"./api-gateway-v2\";\nimport type { ReactRouterAdapter } from \"./index\";\n\nconst emptyStream = () =>\n new ReadableStream({\n start(controller) {\n controller.enqueue(\"\");\n controller.close();\n },\n });\n\nconst sendReactRouterResponseFunctionUrlStreaming = async (\n response: Response,\n responseStream: awslambda.HttpResponseStream,\n) => {\n const metadata = extractAPIGatewayV2ResponseMetadata(response);\n\n let body = response.body;\n if (!body) {\n // Function URL needs a write to happen on the stream, otherwise it won't send headers.\n // See https://github.com/fastify/aws-lambda-fastify/issues/154#issuecomment-2614521719\n body = emptyStream();\n }\n\n const httpResponseStream = awslambda.HttpResponseStream.from(responseStream, metadata);\n\n await writeReadableStreamToWritable(body, httpResponseStream);\n};\n\nexport type FunctionUrlStreamingAdapter = ReactRouterAdapter<\n LambdaFunctionURLEvent,\n void,\n awslambda.HttpResponseStream,\n StreamifyHandler<LambdaFunctionURLEvent, void>\n>;\n\nexport const functionUrlStreamingAdapter: FunctionUrlStreamingAdapter = {\n wrapHandler: awslambda.streamifyResponse,\n createReactRouterRequest: createReactRouterRequestAPIGateywayV2,\n sendReactRouterResponse: sendReactRouterResponseFunctionUrlStreaming,\n};\n","import type {\n ALBEvent,\n ALBHandler,\n APIGatewayProxyEvent,\n APIGatewayProxyEventV2,\n APIGatewayProxyHandler,\n APIGatewayProxyHandlerV2,\n LambdaFunctionURLEvent,\n LambdaFunctionURLHandler,\n} from \"aws-lambda\";\nimport type { StreamifyHandler } from \"aws-lambda/handler\";\nimport {\n type AppLoadContext,\n createRequestHandler as createReactRouterRequestHandler,\n type RouterContextProvider,\n type ServerBuild,\n type UNSAFE_MiddlewareEnabled as MiddlewareEnabled,\n} from \"react-router\";\n\nimport type { GetHostFunction, ReactRouterAdapter } from \"./adapters\";\nimport { apiGatewayV1Adapter } from \"./adapters/api-gateway-v1\";\nimport { apiGatewayV2Adapter } from \"./adapters/api-gateway-v2\";\nimport { applicationLoadBalancerAdapter } from \"./adapters/application-load-balancer\";\nimport { functionUrlStreamingAdapter } from \"./adapters/function-url-streaming\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\n/**\n * A function that returns the value to use as `context` in route `loader` and\n * `action` functions.\n *\n * You can think of this as an escape hatch that allows you to pass\n * environment/platform-specific values through to your loader/action.\n */\nexport type GetLoadContextFunction<E> = (\n event: E,\n) => MiddlewareEnabled extends true ? MaybePromise<RouterContextProvider> : MaybePromise<AppLoadContext>;\n\nexport type CreateRequestHandlerArgs<T> = {\n build: ServerBuild;\n getLoadContext?: GetLoadContextFunction<T>;\n mode?: string;\n /**\n * Override how the host for the request URL is derived from the Lambda event.\n *\n * React Router uses the request URL host (`new URL(request.url).host`) for its\n * built-in cross-origin (CSRF) check on action requests, comparing it against\n * the incoming `Origin` header. The returned value is sanitized (invalid\n * characters stripped, port validated) before use.\n *\n * Return `undefined`/`null` to fall back to the default: the\n * `x-forwarded-host` header (falling back to the `host`/`Host` header).\n *\n * Use this when the default forwarded host is not the host the browser sees.\n * For example, a Lambda Function URL behind CloudFront cannot use its\n * request-context domain name (always the internal `*.lambda-url` host), and\n * CloudFront does not forward the viewer host by default. Forward it yourself\n * (e.g. a CloudFront Function copying the viewer `Host` into a custom header)\n * and read that header here:\n *\n * ```ts\n * createFunctionURLRequestHandler({\n * build,\n * getHost: (event) => event.headers[\"x-viewer-host\"],\n * });\n * ```\n *\n * @remarks\n * The default currently uses the `x-forwarded-host` header, which is\n * client-controlled and can be spoofed. Because that host drives the CSRF\n * check, trusting it should be deliberate: the default will change to the\n * AWS-provided, non-spoofable request-context domain name\n * (`event.requestContext.domainName`) in the next major version (aligning with\n * the upstream `@react-router/architect` adapter), after which relying on a\n * forwarded header becomes an explicit opt-in via `getHost`. Setups where the\n * request-context host is not the browser-facing host (e.g. Function URLs\n * behind CloudFront) must set `getHost`.\n */\n getHost?: GetHostFunction<T>;\n};\n\n/**\n * Returns a request handler for AWS API Gateway V1\n *\n */\n/**\n * Returns a request handler for AWS API Gateway V1 events.\n *\n * @param options - The handler options, including the React Router server build,\n * optional getLoadContext function, and mode string.\n * @returns An AWS API Gateway V1 handler compatible with APIGatewayProxyHandler.\n */\nexport function createAPIGatewayV1RequestHandler(\n options: CreateRequestHandlerArgs<APIGatewayProxyEvent>,\n): APIGatewayProxyHandler {\n return createRequestHandlerForAdapter(apiGatewayV1Adapter, options);\n}\n\n/**\n * Returns a request handler for AWS API Gateway V2 events.\n *\n * @param options - The handler options, including the React Router server build,\n * optional getLoadContext function, and mode string.\n * @returns An AWS API Gateway V2 handler compatible with APIGatewayProxyHandlerV2.\n */\nexport function createAPIGatewayV2RequestHandler(\n options: CreateRequestHandlerArgs<APIGatewayProxyEventV2>,\n): APIGatewayProxyHandlerV2 {\n return createRequestHandlerForAdapter(apiGatewayV2Adapter, options);\n}\n\n/**\n * Returns a request handler for AWS Application Load Balancer events.\n *\n * @param options - The handler options, including the React Router server build,\n * optional getLoadContext function, and mode string.\n * @returns An AWS ALB handler compatible with ALBHandler.\n */\nexport function createALBRequestHandler(options: CreateRequestHandlerArgs<ALBEvent>): ALBHandler {\n return createRequestHandlerForAdapter(applicationLoadBalancerAdapter, options);\n}\n\n/**\n * Returns a request handler for AWS Lambda Function URL events (invoke mode BUFFERED).\n *\n * @param options - The handler options, including the React Router server build,\n * optional getLoadContext function, and mode string.\n * @returns An AWS Lambda Function URL handler compatible with Lambda Function URLs with InvokeMode BUFFERED.\n */\nexport function createFunctionURLRequestHandler(\n options: CreateRequestHandlerArgs<LambdaFunctionURLEvent>,\n): LambdaFunctionURLHandler {\n return createRequestHandlerForAdapter(apiGatewayV2Adapter, options);\n}\n\n/**\n * Returns a request handler for AWS Lambda Function URL events (invoke mode RESPONSE_STREAM).\n *\n * @param options - The handler options, including the React Router server build,\n * optional getLoadContext function, and mode string.\n * @returns A streaming AWS Lambda Function URL handler compatible with Lambda Function URLs with InvokeMode RESPONSE_STREAM.\n */\nexport function createFunctionURLStreamingRequestHandler(\n options: CreateRequestHandlerArgs<LambdaFunctionURLEvent>,\n): StreamifyHandler<LambdaFunctionURLEvent, void> {\n return createRequestHandlerForAdapter(functionUrlStreamingAdapter, options);\n}\n\nfunction createRequestHandlerForAdapter<E, Ret, Res, H>(\n awsAdapter: ReactRouterAdapter<E, Ret, Res, H>,\n { build, getLoadContext, mode = process.env.NODE_ENV, getHost }: CreateRequestHandlerArgs<E>,\n) {\n const handleRequest = createReactRouterRequestHandler(build, mode);\n\n return awsAdapter.wrapHandler(async (event, res) => {\n let request: Request;\n\n try {\n request = awsAdapter.createReactRouterRequest(event, getHost);\n } catch (e: unknown) {\n return await awsAdapter.sendReactRouterResponse(\n new Response(`Bad Request: ${e instanceof Error ? e.message : e}`, { status: 400 }),\n res,\n );\n }\n\n const loadContext = await getLoadContext?.(event);\n\n const response = await handleRequest(request, loadContext);\n\n return await awsAdapter.sendReactRouterResponse(response, res);\n });\n}\n","import type { ALBEvent, APIGatewayProxyEvent, APIGatewayProxyEventV2, LambdaFunctionURLEvent } from \"aws-lambda\";\n\nimport type { ReactRouterAdapter } from \"./adapters\";\n/* eslint-disable @typescript-eslint/no-explicit-any -- we need the any in extends parameters */\nimport type { ApiGatewayV1Adapter } from \"./adapters/api-gateway-v1\";\nimport type { ApiGatewayV2Adapter } from \"./adapters/api-gateway-v2\";\nimport type { ApplicationLoadBalancerAdapter } from \"./adapters/application-load-balancer\";\nimport type { FunctionUrlStreamingAdapter } from \"./adapters/function-url-streaming\";\nimport type { CreateRequestHandlerArgs } from \"./server\";\nimport {\n createALBRequestHandler,\n createAPIGatewayV1RequestHandler,\n createAPIGatewayV2RequestHandler,\n createFunctionURLRequestHandler,\n createFunctionURLStreamingRequestHandler,\n} from \"./server\";\n\nexport enum AWSProxy {\n APIGatewayV1 = \"APIGatewayV1\",\n APIGatewayV2 = \"APIGatewayV2\",\n ALB = \"ALB\",\n FunctionURL = \"FunctionURL\",\n FunctionURLStreaming = \"FunctionURLStreaming\",\n}\n\nexport type InferAdapter<T extends AWSProxy> = T extends AWSProxy.APIGatewayV1\n ? ApiGatewayV1Adapter\n : T extends AWSProxy.APIGatewayV2 | AWSProxy.FunctionURL\n ? ApiGatewayV2Adapter\n : T extends AWSProxy.ALB\n ? ApplicationLoadBalancerAdapter\n : T extends AWSProxy.FunctionURLStreaming\n ? FunctionUrlStreamingAdapter\n : never;\n\ntype InferEventType<T extends AWSProxy> =\n InferAdapter<T> extends ReactRouterAdapter<infer E, any, any, any> ? E : never;\ntype InferHandlerType<T extends AWSProxy> =\n InferAdapter<T> extends ReactRouterAdapter<any, any, any, infer H> ? H : never;\n\n/**\n * Returns a request handler for AWS that serves the response using React Router.\n *\n * @deprecated Use one of the gateway-specific create*RequestHandler methods instead for better tree-shaking.\n * - `createAPIGatewayV1RequestHandler`\n * - `createAPIGatewayV2RequestHandler`\n * - `createALBRequestHandler`\n * - `createFunctionURLRequestHandler`\n * - `createFunctionURLStreamingRequestHandler`\n */\nexport function createRequestHandler<T extends AWSProxy>(\n options: CreateRequestHandlerArgs<InferEventType<T>> & {\n awsProxy?: T;\n },\n): InferHandlerType<T> {\n const { awsProxy = AWSProxy.APIGatewayV2 as T, ...opts } = options;\n switch (awsProxy) {\n case AWSProxy.APIGatewayV1:\n return createAPIGatewayV1RequestHandler(\n opts as CreateRequestHandlerArgs<APIGatewayProxyEvent>,\n ) as InferHandlerType<T>;\n case AWSProxy.APIGatewayV2:\n return createAPIGatewayV2RequestHandler(\n opts as CreateRequestHandlerArgs<APIGatewayProxyEventV2>,\n ) as InferHandlerType<T>;\n case AWSProxy.ALB:\n return createALBRequestHandler(opts as CreateRequestHandlerArgs<ALBEvent>) as InferHandlerType<T>;\n case AWSProxy.FunctionURL:\n return createFunctionURLRequestHandler(\n opts as CreateRequestHandlerArgs<LambdaFunctionURLEvent>,\n ) as InferHandlerType<T>;\n case AWSProxy.FunctionURLStreaming:\n return createFunctionURLStreamingRequestHandler(\n opts as CreateRequestHandlerArgs<LambdaFunctionURLEvent>,\n ) as InferHandlerType<T>;\n default:\n return assertNever(awsProxy, `Unsupported buffered AWS Proxy type: ${awsProxy}`);\n }\n}\n\nfunction assertNever(_x: never, message: string): never {\n throw new Error(message);\n}\n"],"mappings":"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"}