@opennextjs/aws 3.1.6 → 3.2.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.
- package/README.md +27 -22
- package/dist/adapters/binary.js +2 -0
- package/dist/adapters/cache.d.ts +4 -2
- package/dist/adapters/cache.js +14 -8
- package/dist/adapters/config/util.d.ts +2 -2
- package/dist/adapters/image-optimization-adapter.d.ts +2 -2
- package/dist/adapters/middleware.js +5 -52
- package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +7 -4
- package/dist/adapters/plugins/image-optimization/image-optimization.js +2 -3
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +3 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.js +4 -7
- package/dist/adapters/warmer-function.js +2 -67
- package/dist/build/buildNextApp.d.ts +3 -0
- package/dist/build/buildNextApp.js +19 -0
- package/dist/build/bundleNextServer.js +2 -2
- package/dist/build/compileCache.d.ts +9 -0
- package/dist/build/compileCache.js +30 -0
- package/dist/build/compileConfig.d.ts +17 -3
- package/dist/build/compileConfig.js +56 -34
- package/dist/build/compileTagCacheProvider.d.ts +2 -0
- package/dist/build/compileTagCacheProvider.js +26 -0
- package/dist/build/copyTracedFiles.js +2 -2
- package/dist/build/createAssets.d.ts +11 -0
- package/dist/build/createAssets.js +161 -0
- package/dist/build/createImageOptimizationBundle.d.ts +2 -0
- package/dist/build/createImageOptimizationBundle.js +82 -0
- package/dist/build/createMiddleware.d.ts +10 -0
- package/dist/build/createMiddleware.js +47 -0
- package/dist/build/createRevalidationBundle.d.ts +2 -0
- package/dist/build/createRevalidationBundle.js +35 -0
- package/dist/build/createServerBundle.d.ts +2 -2
- package/dist/build/createServerBundle.js +35 -39
- package/dist/build/createWarmerBundle.d.ts +2 -0
- package/dist/build/createWarmerBundle.js +44 -0
- package/dist/build/edge/createEdgeBundle.d.ts +6 -8
- package/dist/build/edge/createEdgeBundle.js +11 -15
- package/dist/build/helper.d.ts +22 -5
- package/dist/build/helper.js +42 -11
- package/dist/build/installDeps.d.ts +2 -0
- package/dist/build/installDeps.js +46 -0
- package/dist/build/utils.d.ts +5 -0
- package/dist/build/utils.js +22 -0
- package/dist/build/validateConfig.d.ts +1 -1
- package/dist/build.d.ts +0 -4
- package/dist/build.js +26 -486
- package/dist/core/createGenericHandler.js +5 -5
- package/dist/core/createMainHandler.d.ts +3 -3
- package/dist/core/createMainHandler.js +5 -5
- package/dist/core/requestHandler.d.ts +2 -2
- package/dist/core/requestHandler.js +2 -2
- package/dist/core/resolve.d.ts +13 -4
- package/dist/core/resolve.js +30 -5
- package/dist/core/routing/cacheInterceptor.d.ts +1 -1
- package/dist/core/routing/i18n/index.d.ts +1 -1
- package/dist/core/routing/i18n/index.js +3 -0
- package/dist/core/routing/matcher.d.ts +2 -1
- package/dist/core/routing/matcher.js +13 -6
- package/dist/core/routing/middleware.d.ts +6 -2
- package/dist/core/routing/middleware.js +13 -7
- package/dist/core/routing/util.d.ts +3 -2
- package/dist/core/routing/util.js +16 -7
- package/dist/core/routingHandler.d.ts +1 -1
- package/dist/core/routingHandler.js +1 -1
- package/dist/helpers/withCloudflare.d.ts +1 -1
- package/dist/helpers/withSST.d.ts +1 -1
- package/dist/http/openNextResponse.d.ts +10 -2
- package/dist/http/openNextResponse.js +27 -0
- package/dist/http/request.d.ts +1 -0
- package/dist/http/util.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v1.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v1.js +2 -2
- package/dist/{converters → overrides/converters}/aws-apigw-v2.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v2.js +4 -4
- package/dist/{converters → overrides/converters}/aws-cloudfront.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-cloudfront.js +6 -7
- package/dist/{converters → overrides/converters}/dummy.d.ts +1 -1
- package/dist/overrides/converters/edge.d.ts +9 -0
- package/dist/{converters → overrides/converters}/edge.js +6 -3
- package/dist/{converters → overrides/converters}/node.d.ts +1 -1
- package/dist/{converters → overrides/converters}/node.js +1 -1
- package/dist/overrides/converters/sqs-revalidate.d.ts +4 -0
- package/dist/overrides/imageLoader/dummy.d.ts +3 -0
- package/dist/overrides/imageLoader/dummy.js +8 -0
- package/dist/overrides/imageLoader/host.d.ts +1 -1
- package/dist/overrides/imageLoader/s3.d.ts +1 -1
- package/dist/overrides/incrementalCache/dummy.d.ts +3 -0
- package/dist/overrides/incrementalCache/dummy.js +13 -0
- package/dist/{cache/incremental → overrides/incrementalCache}/s3-lite.d.ts +1 -1
- package/dist/{cache/incremental → overrides/incrementalCache}/s3.d.ts +1 -1
- package/dist/{cache/incremental → overrides/incrementalCache}/types.d.ts +1 -1
- package/dist/overrides/originResolver/dummy.d.ts +3 -0
- package/dist/overrides/originResolver/dummy.js +7 -0
- package/dist/overrides/originResolver/pattern-env.d.ts +3 -0
- package/dist/overrides/originResolver/pattern-env.js +39 -0
- package/dist/overrides/queue/dummy.d.ts +3 -0
- package/dist/overrides/queue/dummy.js +7 -0
- package/dist/{queue → overrides/queue}/sqs-lite.d.ts +1 -1
- package/dist/{queue → overrides/queue}/sqs-lite.js +3 -3
- package/dist/{queue → overrides/queue}/sqs.d.ts +1 -1
- package/dist/{queue → overrides/queue}/sqs.js +1 -1
- package/dist/overrides/tagCache/dummy.d.ts +3 -0
- package/dist/overrides/tagCache/dummy.js +17 -0
- package/dist/{cache/tag → overrides/tagCache}/dynamodb-lite.d.ts +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb-lite.js +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb.d.ts +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb.js +1 -1
- package/dist/overrides/warmer/aws-lambda.d.ts +3 -0
- package/dist/overrides/warmer/aws-lambda.js +59 -0
- package/dist/overrides/warmer/dummy.d.ts +3 -0
- package/dist/overrides/warmer/dummy.js +7 -0
- package/dist/overrides/wrappers/aws-lambda-streaming.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/aws-lambda-streaming.js +1 -1
- package/dist/overrides/wrappers/aws-lambda.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/cloudflare.d.ts +2 -2
- package/dist/{wrappers → overrides/wrappers}/cloudflare.js +1 -1
- package/dist/overrides/wrappers/dummy.d.ts +7 -0
- package/dist/overrides/wrappers/dummy.js +6 -0
- package/dist/overrides/wrappers/node.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/node.js +1 -1
- package/dist/plugins/edge.d.ts +5 -4
- package/dist/plugins/edge.js +27 -29
- package/dist/plugins/replacement.d.ts +2 -2
- package/dist/plugins/replacement.js +4 -5
- package/dist/plugins/resolve.d.ts +4 -2
- package/dist/plugins/resolve.js +32 -20
- package/dist/types/aws-lambda.d.ts +3 -2
- package/dist/{cache/next-types.d.ts → types/cache.d.ts} +1 -0
- package/dist/types/next-types.d.ts +3 -1
- package/dist/types/open-next.d.ts +44 -13
- package/package.json +2 -2
- package/dist/adapters/plugins/without-routing/requestHandler.d.ts +0 -2
- package/dist/adapters/plugins/without-routing/requestHandler.js +0 -10
- package/dist/converters/edge.d.ts +0 -6
- package/dist/converters/sqs-revalidate.d.ts +0 -4
- package/dist/wrappers/aws-lambda-streaming.d.ts +0 -7
- package/dist/wrappers/aws-lambda.d.ts +0 -7
- package/dist/wrappers/node.d.ts +0 -7
- /package/dist/{converters → overrides/converters}/dummy.js +0 -0
- /package/dist/{converters → overrides/converters}/sqs-revalidate.js +0 -0
- /package/dist/{converters → overrides/converters}/utils.d.ts +0 -0
- /package/dist/{converters → overrides/converters}/utils.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/s3-lite.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/s3.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/types.js +0 -0
- /package/dist/{queue → overrides/queue}/types.d.ts +0 -0
- /package/dist/{cache/tag → overrides/queue}/types.js +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/constants.d.ts +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/constants.js +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/types.d.ts +0 -0
- /package/dist/{queue → overrides/tagCache}/types.js +0 -0
- /package/dist/{wrappers → overrides/wrappers}/aws-lambda.js +0 -0
- /package/dist/{cache/next-types.js → types/cache.js} +0 -0
package/dist/core/resolve.js
CHANGED
|
@@ -3,7 +3,7 @@ export async function resolveConverter(converter) {
|
|
|
3
3
|
return converter();
|
|
4
4
|
}
|
|
5
5
|
else {
|
|
6
|
-
const m_1 = await import(`../converters/aws-apigw-v2.js`);
|
|
6
|
+
const m_1 = await import(`../overrides/converters/aws-apigw-v2.js`);
|
|
7
7
|
// @ts-expect-error
|
|
8
8
|
return m_1.default;
|
|
9
9
|
}
|
|
@@ -14,7 +14,7 @@ export async function resolveWrapper(wrapper) {
|
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
16
16
|
// This will be replaced by the bundler
|
|
17
|
-
const m_1 = await import("../wrappers/aws-lambda.js");
|
|
17
|
+
const m_1 = await import("../overrides/wrappers/aws-lambda.js");
|
|
18
18
|
// @ts-expect-error
|
|
19
19
|
return m_1.default;
|
|
20
20
|
}
|
|
@@ -31,7 +31,7 @@ export async function resolveTagCache(tagCache) {
|
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
// This will be replaced by the bundler
|
|
34
|
-
const m_1 = await import("../
|
|
34
|
+
const m_1 = await import("../overrides/tagCache/dynamodb.js");
|
|
35
35
|
return m_1.default;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -46,7 +46,7 @@ export async function resolveQueue(queue) {
|
|
|
46
46
|
return queue();
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
|
-
const m_1 = await import("../queue/sqs.js");
|
|
49
|
+
const m_1 = await import("../overrides/queue/sqs.js");
|
|
50
50
|
return m_1.default;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -61,7 +61,7 @@ export async function resolveIncrementalCache(incrementalCache) {
|
|
|
61
61
|
return incrementalCache();
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
64
|
-
const m_1 = await import("../
|
|
64
|
+
const m_1 = await import("../overrides/incrementalCache/s3.js");
|
|
65
65
|
return m_1.default;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -79,3 +79,28 @@ export async function resolveImageLoader(imageLoader) {
|
|
|
79
79
|
return m_1.default;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* @returns
|
|
84
|
+
* @__PURE__
|
|
85
|
+
*/
|
|
86
|
+
export async function resolveOriginResolver(originResolver) {
|
|
87
|
+
if (typeof originResolver === "function") {
|
|
88
|
+
return originResolver();
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const m_1 = await import("../overrides/originResolver/pattern-env.js");
|
|
92
|
+
return m_1.default;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* @__PURE__
|
|
97
|
+
*/
|
|
98
|
+
export async function resolveWarmerInvoke(warmer) {
|
|
99
|
+
if (typeof warmer === "function") {
|
|
100
|
+
return warmer();
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const m_1 = await import("../overrides/warmer/aws-lambda.js");
|
|
104
|
+
return m_1.default;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { InternalEvent, InternalResult } from "../../types/open-next";
|
|
1
|
+
import type { InternalEvent, InternalResult } from "../../types/open-next";
|
|
2
2
|
export declare function cacheInterceptor(event: InternalEvent): Promise<InternalEvent | InternalResult>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { InternalEvent } from "../../../types/open-next";
|
|
1
|
+
import type { InternalEvent } from "../../../types/open-next";
|
|
2
2
|
export declare function localizePath(internalEvent: InternalEvent): string;
|
|
@@ -13,6 +13,9 @@ function getLocaleFromCookie(cookies) {
|
|
|
13
13
|
: undefined;
|
|
14
14
|
}
|
|
15
15
|
function detectLocale(internalEvent, i18n) {
|
|
16
|
+
if (i18n.localeDetection === false) {
|
|
17
|
+
return i18n.defaultLocale;
|
|
18
|
+
}
|
|
16
19
|
const cookiesLocale = getLocaleFromCookie(internalEvent.cookies);
|
|
17
20
|
const preferredLocale = acceptLanguage(internalEvent.headers["accept-language"], i18n?.locales);
|
|
18
21
|
debug({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import type { Header, PrerenderManifest, RedirectDefinition, RewriteDefinition } from "../../types/next-types";
|
|
3
|
-
import { InternalEvent, InternalResult } from "../../types/open-next";
|
|
4
|
+
import type { InternalEvent, InternalResult } from "../../types/open-next";
|
|
4
5
|
export declare function addNextConfigHeaders(event: InternalEvent, configHeaders?: Header[] | undefined): Record<string, string | undefined>;
|
|
5
6
|
export declare function handleRewrites<T extends RewriteDefinition>(event: InternalEvent, rewrites: T[]): {
|
|
6
7
|
internalEvent: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextConfig } from "../../adapters/config/index";
|
|
2
|
-
import { compile, match
|
|
2
|
+
import { compile, match } from "path-to-regexp";
|
|
3
3
|
import { emptyReadableStream, toReadableStream } from "../../utils/stream";
|
|
4
4
|
import { debug } from "../../adapters/logger";
|
|
5
5
|
import { localizePath } from "./i18n";
|
|
@@ -122,10 +122,16 @@ export function handleRewrites(event, rewrites) {
|
|
|
122
122
|
const { pathname, protocol, hostname, queryString } = getUrlParts(rewrite.destination, isExternalRewrite);
|
|
123
123
|
// We need to use a localized path if the rewrite is not locale specific
|
|
124
124
|
const pathToUse = rewrite.locale === false ? rawPath : localizedRawPath;
|
|
125
|
+
// We need to encode the "+" character with its UTF-8 equivalent "%20" to avoid 2 issues:
|
|
126
|
+
// 1. The compile function from path-to-regexp will throw an error if it finds a "+" character.
|
|
127
|
+
// https://github.com/pillarjs/path-to-regexp?tab=readme-ov-file#unexpected--or-
|
|
128
|
+
// 2. The convertToQueryString function will replace the "+" character with %2B instead of %20.
|
|
129
|
+
// %2B does not get interpreted as a space in the URL thus breaking the query string.
|
|
130
|
+
const encodePlusQueryString = queryString.replaceAll("+", "%20");
|
|
125
131
|
debug("urlParts", { pathname, protocol, hostname, queryString });
|
|
126
132
|
const toDestinationPath = compile(escapeRegex(pathname ?? "") ?? "");
|
|
127
133
|
const toDestinationHost = compile(escapeRegex(hostname ?? "") ?? "");
|
|
128
|
-
const toDestinationQuery = compile(escapeRegex(
|
|
134
|
+
const toDestinationQuery = compile(escapeRegex(encodePlusQueryString ?? "") ?? "");
|
|
129
135
|
let params = {
|
|
130
136
|
// params for the source
|
|
131
137
|
...getParamsFromSource(match(escapeRegex(rewrite?.source) ?? ""))(pathToUse),
|
|
@@ -139,7 +145,7 @@ export function handleRewrites(event, rewrites) {
|
|
|
139
145
|
}, {}),
|
|
140
146
|
};
|
|
141
147
|
const isUsingParams = Object.keys(params).length > 0;
|
|
142
|
-
let rewrittenQuery =
|
|
148
|
+
let rewrittenQuery = encodePlusQueryString;
|
|
143
149
|
let rewrittenHost = hostname;
|
|
144
150
|
let rewrittenPath = pathname;
|
|
145
151
|
if (isUsingParams) {
|
|
@@ -149,7 +155,7 @@ export function handleRewrites(event, rewrites) {
|
|
|
149
155
|
}
|
|
150
156
|
rewrittenUrl = isExternalRewrite
|
|
151
157
|
? `${protocol}//${rewrittenHost}${rewrittenPath}`
|
|
152
|
-
:
|
|
158
|
+
: `${rewrittenPath}`;
|
|
153
159
|
// Should we merge the query params or use only the ones from the rewrite?
|
|
154
160
|
finalQuery = {
|
|
155
161
|
...query,
|
|
@@ -244,8 +250,9 @@ export function fixDataPage(internalEvent, buildId) {
|
|
|
244
250
|
};
|
|
245
251
|
}
|
|
246
252
|
if (rawPath.startsWith(dataPattern) && rawPath.endsWith(".json")) {
|
|
247
|
-
|
|
248
|
-
|
|
253
|
+
const newPath = rawPath
|
|
254
|
+
.slice(dataPattern.length, -".json".length)
|
|
255
|
+
.replace(/^\/index$/, "/");
|
|
249
256
|
query.__nextDataReq = "1";
|
|
250
257
|
return {
|
|
251
258
|
...internalEvent,
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { InternalEvent, InternalResult } from "../../types/open-next.js";
|
|
1
|
+
import type { InternalEvent, InternalResult } from "../../types/open-next.js";
|
|
2
2
|
type MiddlewareOutputEvent = InternalEvent & {
|
|
3
3
|
responseHeaders?: Record<string, string | string[]>;
|
|
4
4
|
externalRewrite?: boolean;
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
type Middleware = (request: Request) => Response | Promise<Response>;
|
|
7
|
+
type MiddlewareLoader = () => Promise<{
|
|
8
|
+
default: Middleware;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function handleMiddleware(internalEvent: InternalEvent, middlewareLoader?: MiddlewareLoader): Promise<MiddlewareOutputEvent | InternalResult>;
|
|
7
11
|
export {};
|
|
@@ -11,12 +11,16 @@ import { localizePath } from "./i18n/index.js";
|
|
|
11
11
|
import { convertBodyToReadableStream, convertToQueryString, getMiddlewareMatch, isExternal, } from "./util.js";
|
|
12
12
|
const middlewareManifest = MiddlewareManifest;
|
|
13
13
|
const middleMatch = getMiddlewareMatch(middlewareManifest);
|
|
14
|
+
function defaultMiddlewareLoader() {
|
|
15
|
+
// @ts-expect-error - This is bundled
|
|
16
|
+
return import("./middleware.mjs");
|
|
17
|
+
}
|
|
14
18
|
// NOTE: As of Nextjs 13.4.13+, the middleware is handled outside the next-server.
|
|
15
19
|
// OpenNext will run the middleware in a sandbox and set the appropriate req headers
|
|
16
20
|
// and res.body prior to processing the next-server.
|
|
17
21
|
// @returns undefined | res.end()
|
|
18
22
|
// if res.end() is return, the parent needs to return and not process next server
|
|
19
|
-
export async function handleMiddleware(internalEvent) {
|
|
23
|
+
export async function handleMiddleware(internalEvent, middlewareLoader = defaultMiddlewareLoader) {
|
|
20
24
|
const { query } = internalEvent;
|
|
21
25
|
const normalizedPath = localizePath(internalEvent);
|
|
22
26
|
// We only need the normalizedPath to check if the middleware should run
|
|
@@ -26,15 +30,17 @@ export async function handleMiddleware(internalEvent) {
|
|
|
26
30
|
// We bypass the middleware if the request is internal
|
|
27
31
|
if (internalEvent.headers["x-isr"])
|
|
28
32
|
return internalEvent;
|
|
33
|
+
// Retrieve the protocol:
|
|
34
|
+
// - In lambda, the url only contains the rawPath and the query - default to https
|
|
35
|
+
// - In cloudflare, the protocol is usually http in dev and https in production
|
|
36
|
+
const protocol = internalEvent.url.startsWith("http://") ? "http:" : "https:";
|
|
29
37
|
const host = internalEvent.headers.host
|
|
30
|
-
?
|
|
38
|
+
? `${protocol}//${internalEvent.headers.host}`
|
|
31
39
|
: "http://localhost:3000";
|
|
32
40
|
const initialUrl = new URL(normalizedPath, host);
|
|
33
41
|
initialUrl.search = convertToQueryString(query);
|
|
34
42
|
const url = initialUrl.toString();
|
|
35
|
-
|
|
36
|
-
// @ts-expect-error - This is bundled
|
|
37
|
-
const middleware = await import("./middleware.mjs");
|
|
43
|
+
const middleware = await middlewareLoader();
|
|
38
44
|
const result = await middleware.default({
|
|
39
45
|
geo: {
|
|
40
46
|
city: internalEvent.headers["x-open-next-city"],
|
|
@@ -93,7 +99,7 @@ export async function handleMiddleware(internalEvent) {
|
|
|
93
99
|
resHeaders.location =
|
|
94
100
|
responseHeaders
|
|
95
101
|
.get("location")
|
|
96
|
-
?.replace("http://localhost:3000",
|
|
102
|
+
?.replace("http://localhost:3000", `${protocol}//${internalEvent.headers.host}`) ?? resHeaders.location;
|
|
97
103
|
// res.setHeader("Location", location);
|
|
98
104
|
return {
|
|
99
105
|
body: emptyReadableStream(),
|
|
@@ -153,7 +159,7 @@ export async function handleMiddleware(internalEvent) {
|
|
|
153
159
|
responseHeaders: resHeaders,
|
|
154
160
|
url: newUrl,
|
|
155
161
|
rawPath: rewritten
|
|
156
|
-
? newUrl ?? internalEvent.rawPath
|
|
162
|
+
? (newUrl ?? internalEvent.rawPath)
|
|
157
163
|
: internalEvent.rawPath,
|
|
158
164
|
type: internalEvent.type,
|
|
159
165
|
headers: { ...internalEvent.headers, ...reqHeaders },
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
import type { OutgoingHttpHeaders } from "node:http";
|
|
4
5
|
import type { IncomingMessage, StreamCreator } from "../../http/index.js";
|
|
5
6
|
import { OpenNextNodeResponse } from "../../http/openNextResponse.js";
|
|
6
7
|
import type { MiddlewareManifest } from "../../types/next-types";
|
|
7
|
-
import { InternalEvent, InternalResult } from "../../types/open-next.js";
|
|
8
|
+
import type { InternalEvent, InternalResult } from "../../types/open-next.js";
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
10
11
|
* @__PURE__
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { Readable } from "node:stream";
|
|
3
|
-
import { BuildId, HtmlPages } from "../../adapters/config/index.js";
|
|
3
|
+
import { BuildId, HtmlPages, NextConfig } from "../../adapters/config/index.js";
|
|
4
4
|
import { OpenNextNodeResponse } from "../../http/openNextResponse.js";
|
|
5
5
|
import { parseHeaders } from "../../http/util.js";
|
|
6
6
|
import { isBinaryContentType } from "../../adapters/binary.js";
|
|
@@ -37,7 +37,7 @@ export function getUrlParts(url, isExternal) {
|
|
|
37
37
|
const match = url.match(regex);
|
|
38
38
|
return {
|
|
39
39
|
hostname: "",
|
|
40
|
-
pathname: match?.[1]
|
|
40
|
+
pathname: match?.[1] ? `/${match[1]}` : url,
|
|
41
41
|
protocol: "",
|
|
42
42
|
queryString: match?.[2] ?? "",
|
|
43
43
|
};
|
|
@@ -50,7 +50,7 @@ export function getUrlParts(url, isExternal) {
|
|
|
50
50
|
return {
|
|
51
51
|
protocol: match[1] ?? "https:",
|
|
52
52
|
hostname: match[2],
|
|
53
|
-
pathname: match[3],
|
|
53
|
+
pathname: match[3] ?? "",
|
|
54
54
|
queryString: match[4]?.slice(1) ?? "",
|
|
55
55
|
};
|
|
56
56
|
}
|
|
@@ -84,13 +84,16 @@ export function convertRes(res) {
|
|
|
84
84
|
* @__PURE__
|
|
85
85
|
*/
|
|
86
86
|
export function convertToQueryString(query) {
|
|
87
|
+
// URLSearchParams is a representation of the PARSED query.
|
|
88
|
+
// So we must decode the value before appending it to the URLSearchParams.
|
|
89
|
+
// https://stackoverflow.com/a/45516812
|
|
87
90
|
const urlQuery = new URLSearchParams();
|
|
88
91
|
Object.entries(query).forEach(([key, value]) => {
|
|
89
92
|
if (Array.isArray(value)) {
|
|
90
|
-
value.forEach((entry) => urlQuery.append(key, entry));
|
|
93
|
+
value.forEach((entry) => urlQuery.append(key, decodeURIComponent(entry)));
|
|
91
94
|
}
|
|
92
95
|
else {
|
|
93
|
-
urlQuery.append(key, value);
|
|
96
|
+
urlQuery.append(key, decodeURIComponent(value));
|
|
94
97
|
}
|
|
95
98
|
});
|
|
96
99
|
const queryString = urlQuery.toString();
|
|
@@ -237,6 +240,9 @@ var CommonHeaders;
|
|
|
237
240
|
export function fixCacheHeaderForHtmlPages(rawPath, headers) {
|
|
238
241
|
// We don't want to cache error pages
|
|
239
242
|
if (rawPath === "/404" || rawPath === "/500") {
|
|
243
|
+
if (process.env.OPEN_NEXT_DANGEROUSLY_SET_ERROR_HEADERS === "true") {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
240
246
|
headers[CommonHeaders.CACHE_CONTROL] =
|
|
241
247
|
"private, no-cache, no-store, max-age=0, must-revalidate";
|
|
242
248
|
return;
|
|
@@ -268,7 +274,9 @@ export function fixSWRCacheHeader(headers) {
|
|
|
268
274
|
* @__PURE__
|
|
269
275
|
*/
|
|
270
276
|
export function addOpenNextHeader(headers) {
|
|
271
|
-
|
|
277
|
+
if (NextConfig.poweredByHeader) {
|
|
278
|
+
headers["X-OpenNext"] = "1";
|
|
279
|
+
}
|
|
272
280
|
if (globalThis.openNextDebug) {
|
|
273
281
|
headers["X-OpenNext-Version"] = globalThis.openNextVersion;
|
|
274
282
|
headers["X-OpenNext-RequestId"] = globalThis.__als.getStore()?.requestId;
|
|
@@ -383,7 +391,8 @@ export function fixISRHeaders(headers) {
|
|
|
383
391
|
// 31536000 is the default s-maxage value for SSG pages
|
|
384
392
|
if (sMaxAge && sMaxAge !== 31536000) {
|
|
385
393
|
const remainingTtl = Math.max(sMaxAge - age, 1);
|
|
386
|
-
headers[CommonHeaders.CACHE_CONTROL] =
|
|
394
|
+
headers[CommonHeaders.CACHE_CONTROL] =
|
|
395
|
+
`s-maxage=${remainingTtl}, stale-while-revalidate=2592000`;
|
|
387
396
|
}
|
|
388
397
|
}
|
|
389
398
|
if (headers[CommonHeaders.NEXT_CACHE] !== "STALE")
|
|
@@ -30,7 +30,7 @@ function applyMiddlewareHeaders(eventHeaders, middlewareHeaders, setPrefix = tru
|
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
export default async function routingHandler(event) {
|
|
33
|
-
const nextHeaders = addNextConfigHeaders(event, ConfigHeaders)
|
|
33
|
+
const nextHeaders = addNextConfigHeaders(event, ConfigHeaders);
|
|
34
34
|
let internalEvent = fixDataPage(event, BuildId);
|
|
35
35
|
if ("statusCode" in internalEvent) {
|
|
36
36
|
return internalEvent;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FunctionOptions, OpenNextConfig, RouteTemplate, SplittedFunctionOptions } from "../types/open-next";
|
|
1
|
+
import type { FunctionOptions, OpenNextConfig, RouteTemplate, SplittedFunctionOptions } from "../types/open-next";
|
|
2
2
|
type CloudflareCompatibleFunction<Placement extends "regional" | "global"> = Placement extends "regional" ? FunctionOptions & {
|
|
3
3
|
placement: "regional";
|
|
4
4
|
} : {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FunctionOptions, OpenNextConfig, RouteTemplate } from "../types/open-next";
|
|
1
|
+
import type { FunctionOptions, OpenNextConfig, RouteTemplate } from "../types/open-next";
|
|
2
2
|
type SSTCompatibleFunction = FunctionOptions & {
|
|
3
3
|
override?: {
|
|
4
4
|
wrapper?: "aws-lambda-streaming" | "aws-lambda";
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
/// <reference types="node" />
|
|
5
|
+
/// <reference types="node" />
|
|
5
6
|
import type { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, ServerResponse } from "http";
|
|
6
|
-
import { Socket } from "net";
|
|
7
|
-
import {
|
|
7
|
+
import type { Socket } from "net";
|
|
8
|
+
import type { TransformCallback, Writable } from "stream";
|
|
9
|
+
import { Transform } from "stream";
|
|
8
10
|
export interface StreamCreator {
|
|
9
11
|
writeHeaders(prelude: {
|
|
10
12
|
statusCode: number;
|
|
@@ -65,6 +67,11 @@ export declare class OpenNextNodeResponse extends Transform implements ServerRes
|
|
|
65
67
|
private _internalWrite;
|
|
66
68
|
_transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
|
|
67
69
|
_flush(callback: TransformCallback): void;
|
|
70
|
+
/**
|
|
71
|
+
* New method in Node 18.15+
|
|
72
|
+
* There are probably not used right now in Next.js, but better be safe than sorry
|
|
73
|
+
*/
|
|
74
|
+
setHeaders(headers: Headers | Map<string, number | string | readonly string[]>): this;
|
|
68
75
|
/**
|
|
69
76
|
* Next specific methods
|
|
70
77
|
* On earlier versions of next.js, those methods are mandatory to make everything work
|
|
@@ -75,4 +82,5 @@ export declare class OpenNextNodeResponse extends Transform implements ServerRes
|
|
|
75
82
|
body(value: string): this;
|
|
76
83
|
onClose(callback: () => void): void;
|
|
77
84
|
redirect(destination: string, statusCode: number): this;
|
|
85
|
+
private fixHeadersForError;
|
|
78
86
|
}
|
|
@@ -141,6 +141,7 @@ export class OpenNextNodeResponse extends Transform {
|
|
|
141
141
|
: [...initialCookies, ...this._cookies];
|
|
142
142
|
}
|
|
143
143
|
this.fixHeaders(this.headers);
|
|
144
|
+
this.fixHeadersForError();
|
|
144
145
|
// We need to fix the set-cookie header here
|
|
145
146
|
this.headers[SET_COOKIE_HEADER] = this._cookies;
|
|
146
147
|
const parsedHeaders = parseHeaders(this.headers);
|
|
@@ -206,6 +207,7 @@ export class OpenNextNodeResponse extends Transform {
|
|
|
206
207
|
getFixedHeaders() {
|
|
207
208
|
// Do we want to apply this on writeHead?
|
|
208
209
|
this.fixHeaders(this.headers);
|
|
210
|
+
this.fixHeadersForError();
|
|
209
211
|
// This way we ensure that the cookies are correct
|
|
210
212
|
this.headers[SET_COOKIE_HEADER] = this._cookies;
|
|
211
213
|
return this.headers;
|
|
@@ -243,6 +245,16 @@ export class OpenNextNodeResponse extends Transform {
|
|
|
243
245
|
}
|
|
244
246
|
callback();
|
|
245
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* New method in Node 18.15+
|
|
250
|
+
* There are probably not used right now in Next.js, but better be safe than sorry
|
|
251
|
+
*/
|
|
252
|
+
setHeaders(headers) {
|
|
253
|
+
headers.forEach((value, key) => {
|
|
254
|
+
this.setHeader(key, Array.isArray(value) ? value : value.toString());
|
|
255
|
+
});
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
246
258
|
/**
|
|
247
259
|
* Next specific methods
|
|
248
260
|
* On earlier versions of next.js, those methods are mandatory to make everything work
|
|
@@ -278,4 +290,19 @@ export class OpenNextNodeResponse extends Transform {
|
|
|
278
290
|
//TODO: test to see if we need to call end here
|
|
279
291
|
return this;
|
|
280
292
|
}
|
|
293
|
+
// For some reason, next returns the 500 error page with some cache-control headers
|
|
294
|
+
// We need to fix that
|
|
295
|
+
fixHeadersForError() {
|
|
296
|
+
if (process.env.OPEN_NEXT_DANGEROUSLY_SET_ERROR_HEADERS === "true") {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// We only check for 404 and 500 errors
|
|
300
|
+
// The rest should be errors that are handled by the user and they should set the cache headers themselves
|
|
301
|
+
if (this.statusCode === 404 || this.statusCode === 500) {
|
|
302
|
+
// For some reason calling this.setHeader("Cache-Control", "no-cache, no-store, must-revalidate") does not work here
|
|
303
|
+
// The function is not even called, i'm probably missing something obvious
|
|
304
|
+
this.headers["cache-control"] =
|
|
305
|
+
"private, no-cache, no-store, max-age=0, must-revalidate";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
281
308
|
}
|
package/dist/http/request.d.ts
CHANGED
package/dist/http/util.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import http from "node:http";
|
|
1
|
+
import type http from "node:http";
|
|
2
2
|
export declare const parseHeaders: (headers?: http.OutgoingHttpHeader[] | http.OutgoingHttpHeaders) => Record<string, string>;
|
|
3
3
|
export declare const convertHeader: (header: http.OutgoingHttpHeader) => string;
|
|
4
4
|
export declare function parseCookies(cookies?: string | string[]): string[] | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fromReadableStream } from "
|
|
2
|
-
import { debug } from "
|
|
1
|
+
import { fromReadableStream } from "../../utils/stream";
|
|
2
|
+
import { debug } from "../../adapters/logger";
|
|
3
3
|
import { removeUndefinedFromQuery } from "./utils";
|
|
4
4
|
function normalizeAPIGatewayProxyEventHeaders(event) {
|
|
5
5
|
event.multiValueHeaders;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseCookies } from "
|
|
2
|
-
import { fromReadableStream } from "
|
|
3
|
-
import { debug } from "
|
|
4
|
-
import { convertToQuery } from "
|
|
1
|
+
import { parseCookies } from "../../http/util";
|
|
2
|
+
import { fromReadableStream } from "../../utils/stream";
|
|
3
|
+
import { debug } from "../../adapters/logger";
|
|
4
|
+
import { convertToQuery } from "../../core/routing/util";
|
|
5
5
|
import { removeUndefinedFromQuery } from "./utils";
|
|
6
6
|
// Not sure which one is reallly needed as this is not documented anywhere but server actions redirect are not working without this, it causes a 500 error from cloudfront itself with a 'x-amzErrortype: InternalFailure' header
|
|
7
7
|
const CloudFrontBlacklistedHeaders = [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseCookies } from "
|
|
2
|
-
import { fromReadableStream } from "
|
|
3
|
-
import { debug } from "
|
|
4
|
-
import { convertRes, convertToQuery, convertToQueryString, createServerResponse, proxyRequest, } from "
|
|
1
|
+
import { parseCookies } from "../../http/util";
|
|
2
|
+
import { fromReadableStream } from "../../utils/stream";
|
|
3
|
+
import { debug } from "../../adapters/logger";
|
|
4
|
+
import { convertRes, convertToQuery, convertToQueryString, createServerResponse, proxyRequest, } from "../../core/routing/util";
|
|
5
5
|
const CloudFrontBlacklistedHeaders = [
|
|
6
6
|
// Disallowed headers, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html#function-restrictions-disallowed-headers
|
|
7
7
|
"connection",
|
|
@@ -100,11 +100,9 @@ function convertToCloudfrontHeaders(headers, directResponse) {
|
|
|
100
100
|
return cloudfrontHeaders;
|
|
101
101
|
}
|
|
102
102
|
async function convertToCloudFrontRequestResult(result, originalRequest) {
|
|
103
|
-
let responseHeaders = result.type === "middleware"
|
|
104
|
-
? result.internalEvent.headers
|
|
105
|
-
: result.headers;
|
|
106
103
|
if (result.type === "middleware") {
|
|
107
104
|
const { method, clientIp, origin } = originalRequest.Records[0].cf.request;
|
|
105
|
+
const responseHeaders = result.internalEvent.headers;
|
|
108
106
|
// Handle external rewrite
|
|
109
107
|
if (result.isExternalRewrite) {
|
|
110
108
|
const serverResponse = createServerResponse(result.internalEvent, {});
|
|
@@ -154,6 +152,7 @@ async function convertToCloudFrontRequestResult(result, originalRequest) {
|
|
|
154
152
|
return response;
|
|
155
153
|
}
|
|
156
154
|
const body = await fromReadableStream(result.body, result.isBase64Encoded);
|
|
155
|
+
const responseHeaders = result.headers;
|
|
157
156
|
const response = {
|
|
158
157
|
status: result.statusCode.toString(),
|
|
159
158
|
statusDescription: "OK",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Converter, InternalEvent, InternalResult } from "../../types/open-next";
|
|
2
|
+
import type { MiddlewareOutputEvent } from "../../core/routingHandler";
|
|
3
|
+
declare global {
|
|
4
|
+
var __dangerous_ON_edge_converter_returns_request: boolean | undefined;
|
|
5
|
+
}
|
|
6
|
+
declare const converter: Converter<InternalEvent, InternalResult | ({
|
|
7
|
+
type: "middleware";
|
|
8
|
+
} & MiddlewareOutputEvent)>;
|
|
9
|
+
export default converter;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
|
-
import { parseCookies } from "
|
|
2
|
+
import { parseCookies } from "../../http/util";
|
|
3
3
|
const converter = {
|
|
4
4
|
convertFrom: async (event) => {
|
|
5
5
|
const searchParams = new URL(event.url).searchParams;
|
|
@@ -52,7 +52,7 @@ const converter = {
|
|
|
52
52
|
url = `https://${result.internalEvent.headers.host}${url}`;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
const
|
|
55
|
+
const request = new Request(url, {
|
|
56
56
|
body: result.internalEvent.body,
|
|
57
57
|
method: result.internalEvent.method,
|
|
58
58
|
headers: {
|
|
@@ -60,12 +60,15 @@ const converter = {
|
|
|
60
60
|
"x-forwarded-host": result.internalEvent.headers.host,
|
|
61
61
|
},
|
|
62
62
|
});
|
|
63
|
+
if (globalThis.__dangerous_ON_edge_converter_returns_request === true) {
|
|
64
|
+
return request;
|
|
65
|
+
}
|
|
63
66
|
const cfCache = (result.isISR ||
|
|
64
67
|
result.internalEvent.rawPath.startsWith("/_next/image")) &&
|
|
65
68
|
process.env.DISABLE_CACHE !== "true"
|
|
66
69
|
? { cacheEverything: true }
|
|
67
70
|
: {};
|
|
68
|
-
return fetch(
|
|
71
|
+
return fetch(request, {
|
|
69
72
|
// This is a hack to make sure that the response is cached by Cloudflare
|
|
70
73
|
// See https://developers.cloudflare.com/workers/examples/cache-using-fetch/#caching-html-resources
|
|
71
74
|
// @ts-expect-error - This is a Cloudflare specific option
|