Skip to content

Commit 9c4211d

Browse files
authoredDec 19, 2022
Add support for middleware (#10)
* Add support for middleware * Update README.md
1 parent 84d84b6 commit 9c4211d

File tree

5 files changed

+72
-131
lines changed

5 files changed

+72
-131
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ OpenNext aims to support all Next.js 13 features. Some features are work in prog
2424
- [x] Static site generation (SSG)
2525
- [x] Server-side rendering (SSR)
2626
- [x] Incremental static regeneration (ISR)
27+
- [x] Middleware
2728
- [ ] Image optimization (work in progress)
28-
- [ ] Middleware (work in progress)
2929

3030
## Quick start
3131

‎cli/assets/middleware-adapter.js

+43-115
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,13 @@ Object.assign(globalThis, {
88
});
99
const index = await (() => import("./middleware.js"))();
1010

11-
// TODO
12-
//console.log(self);
13-
//handler({
14-
// Records: [
15-
// {
16-
// cf: {
17-
// request: {
18-
// uri: "https://sst.dev/_next/data/5fCVTp6Xr7VQpZ-m8Wxxq/middleware-redirect.json",
19-
// method: "GET",
20-
// headers: {
21-
// host: [{ value: "sst.dev" }]
22-
// },
23-
// querystring: "",
24-
// },
25-
// }
26-
// }
27-
// ]
28-
//}).then((res) => console.log(JSON.stringify(res, null, 2)));
29-
3011
export async function handler(event) {
3112
// Convert CloudFront request to Node request
3213
const request = event.Records[0].cf.request;
3314
const { uri, method, headers, querystring, body } = request;
3415
console.log(uri);
3516
console.log(request);
17+
console.log(request.headers);
3618
const requestHeaders = new Headers();
3719
for (const [key, values] of Object.entries(headers)) {
3820
for (const { value } of values) {
@@ -59,112 +41,58 @@ export async function handler(event) {
5941
waitUntil: () => {},
6042
});
6143

62-
// Build headers
63-
(response.headers.get("x-middleware-override-headers") || "")
64-
.split(",")
65-
.forEach(key => {
66-
headers[key] = [{
67-
key,
68-
value: response.headers.get(`x-middleware-request-${key}`)
69-
}];
70-
});
71-
44+
// WORKAROUND (AWS): pass middleware headers to server
7245
if (response.headers.get("x-middleware-next") === "1") {
73-
headers["x-wahaha"] = [{ key: "x-wahaha", value: "wahaha" }];
74-
headers["wahaha"] = [{ key: "wahaha", value: "wahaha" }];
46+
console.log("== getMiddlewareHeaders ==", response.headers);
47+
headers["x-op-middleware-request-headers"] = [{
48+
key: "x-op-middleware-request-headers",
49+
value: getMiddlewareRequestHeaders(response),
50+
}];
51+
headers["x-op-middleware-response-headers"] = [{
52+
key: "x-op-middleware-response-headers",
53+
value: getMiddlewareResponseHeaders(response),
54+
}];
7555
console.log("== conitnue to origin ==", request)
7656
return request;
7757
}
7858

79-
console.log("== do not hit origin ==", {
59+
console.log("== do not hit origin ==", response, {
8060
status: response.status,
81-
headers,
61+
headers: httpHeadersToCfHeaders(response.headers),
8262
});
8363
return {
8464
status: response.status,
85-
headers,
86-
}
65+
headers: httpHeadersToCfHeaders(response.headers),
66+
};
8767
}
8868

89-
/**
90-
* middleware-fetch
91-
*
92-
* nextresponse [response] {
93-
size: 0,
94-
[symbol(body internals)]: {
95-
body: null,
96-
stream: null,
97-
boundary: null,
98-
disturbed: false,
99-
error: null
100-
},
101-
[symbol(response internals)]: {
102-
type: 'default',
103-
url: undefined,
104-
status: 200,
105-
statustext: '',
106-
headers: { 'x-middleware-next': '1' },
107-
counter: undefined,
108-
highwatermark: undefined
109-
},
110-
[Symbol(internal response)]: {
111-
cookies: ResponseCookies { _parsed: Map(0) {}, _headers: [Object] },
112-
url: undefined
113-
}
114-
}
115-
*/
116-
/**
117-
* middleware-set-header
118-
*
119-
* NextResponse [Response] {
120-
size: 0,
121-
[Symbol(Body internals)]: {
122-
body: null,
123-
stream: null,
124-
boundary: null,
125-
disturbed: false,
126-
error: null
127-
},
128-
[Symbol(Response internals)]: {
129-
type: 'default',
130-
url: undefined,
131-
status: 200,
132-
statusText: '',
133-
headers: {
134-
'x-hello-from-middleware2': 'hello',
135-
'x-middleware-next': '1',
136-
'x-middleware-override-headers': 'x-hello-from-middleware1',
137-
'x-middleware-request-x-hello-from-middleware1': 'hello'
138-
},
139-
counter: undefined,
140-
highWaterMark: undefined
141-
},
142-
[Symbol(internal response)]: {
143-
cookies: ResponseCookies { _parsed: Map(0) {}, _headers: [Object] },
144-
url: undefined
145-
}
69+
function getMiddlewareRequestHeaders(response) {
70+
const headers = {};
71+
(response.headers.get("x-middleware-override-headers") || "")
72+
.split(",")
73+
.forEach(key => {
74+
headers[key] = response.headers.get(`x-middleware-request-${key}`)
75+
});
76+
console.log("== getMiddlewareRequestHeaders ==", headers);
77+
return JSON.stringify(headers);
14678
}
147-
*/
148-
/**
149-
* middleware-redirect
150-
*
151-
* Response {
152-
size: 0,
153-
[Symbol(Body internals)]: {
154-
body: null,
155-
stream: null,
156-
boundary: null,
157-
disturbed: false,
158-
error: null
159-
},
160-
[Symbol(Response internals)]: {
161-
type: 'default',
162-
url: '',
163-
status: 307,
164-
statusText: '',
165-
headers: { location: 'https://sst.dev/ssr' },
166-
counter: undefined,
167-
highWaterMark: undefined
168-
}
79+
80+
function getMiddlewareResponseHeaders(response) {
81+
const headers = {};
82+
response.headers.forEach((value, key) => {
83+
if (!key.startsWith("x-middleware-")) {
84+
headers[key] = value;
85+
}
86+
});
87+
console.log("== getMiddlewareResponseHeaders ==", headers);
88+
return JSON.stringify(headers);
16989
}
170-
*/
90+
91+
function httpHeadersToCfHeaders(httpHeaders) {
92+
const headers = {};
93+
httpHeaders.forEach((value, key) => {
94+
headers[key] = [{ key, value }];
95+
});
96+
console.log("== responseHeadersToCloudFrontHeaders ==", headers);
97+
return headers;
98+
}

‎cli/assets/server-adapter.cjs

+13
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,26 @@ export const handler = async (event) => {
111111
console.log(event)
112112
console.log(event.rawPath)
113113

114+
// WORKAROUND (AWS): pass middleware headers to server
115+
const middlewareRequestHeaders = JSON.parse(
116+
event.headers["x-op-middleware-request-headers"] || "{}"
117+
);
118+
event.headers = { ...event.headers, ...middlewareRequestHeaders };
119+
114120
const response = await server(event);
115121

116122
// Handle cache response headers not set for HTML pages
117123
const htmlPages = loadHtmlPages();
118124
if (htmlPages.includes(event.rawPath) && !response.headers["cache-control"]) {
119125
response.headers["cache-control"] = "public, max-age=0, s-maxage=31536000, must-revalidate";
120126
}
127+
128+
// WORKAROUND (AWS): pass middleware headers to server
129+
const middlewareResponseHeaders = JSON.parse(
130+
event.headers["x-op-middleware-response-headers"] || "{}"
131+
);
132+
response.headers = { ...response.headers, ...middlewareResponseHeaders };
133+
121134
console.log({ after: response });
122135

123136
return response;

‎cli/src/build.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function createMiddlewareBundle(src: string) {
8282
fs.mkdirSync(outputPath, { recursive: true });
8383

8484
// Create the middleware code
85-
const buildTempPath = path.resolve(__dirname, "../.middleware-build");
85+
const buildTempPath = path.join(outputDir, "../.middleware-build");
8686
fs.mkdirSync(buildTempPath, { recursive: true });
8787
fs.writeFileSync(path.join(buildTempPath, "middleware.js"), src);
8888
fs.copyFileSync(

‎cli/yarn.lock

+14-14
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,9 @@
322322
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
323323

324324
"@types/node@^18.11.10":
325-
version "18.11.13"
326-
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.13.tgz#dff34f226ec1ac0432ae3b136ec5552bd3b9c0fe"
327-
integrity sha512-IASpMGVcWpUsx5xBOrxMj7Bl8lqfuTY7FKAnPmu5cHkfQVWF8GulWS1jbRqA934qZL35xh5xN/+Xe/i26Bod4w==
325+
version "18.11.15"
326+
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.15.tgz#de0e1fbd2b22b962d45971431e2ae696643d3f5d"
327+
integrity sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==
328328

329329
"@types/normalize-package-data@^2.4.0":
330330
version "2.4.1"
@@ -337,14 +337,14 @@
337337
integrity sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==
338338

339339
"@vercel/build-utils@^5.7.0":
340-
version "5.7.0"
341-
resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-5.7.0.tgz#73f5b66ee970a2712cfea62a19e04f6869c589f5"
342-
integrity sha512-hOcb7HxYza5LtZLcmh9VkShV3hLaLlZarLBqQmMR/oTlvgIybeW6LjrPpFiu2hCCf9VbkdBR1OFmDh8EydFswQ==
340+
version "5.7.1"
341+
resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-5.7.1.tgz#985c927e8af265e73fa693c52a8e61447e030162"
342+
integrity sha512-JilBlPlqwH/d4dbRLyxbhr4y3Yb41cfyypGyCFOpdgXo1ie3v2wkNZWNyWpDHSocSS4PpdIGJ1OdnzULd2fdBQ==
343343

344344
"@vercel/next@^3.3.2":
345-
version "3.3.2"
346-
resolved "https://registry.yarnpkg.com/@vercel/next/-/next-3.3.2.tgz#3ce397805a378c7a7f88049356117dd2b09bd6aa"
347-
integrity sha512-J44LvZK6NKFCv+MgsUekz2jAAVn0Eqekr0KDigEcXjs9T1rIM54qyWXIsUiCJuPBgTVoL1Ejh9OzWACwvXKJpw==
345+
version "3.3.3"
346+
resolved "https://registry.yarnpkg.com/@vercel/next/-/next-3.3.3.tgz#224454a70a85535cbb35d4e95fd93d5d4cf81b46"
347+
integrity sha512-o7wAhAn5dc4Aou05LsmFvQjtbmC3K++8Y3wIfASVqNNpD9cLa76OcVY1XazxujhlNIWCQi+KOv9fr/BPRZDj8Q==
348348

349349
ansi-colors@^4.1.1, ansi-colors@^4.1.3:
350350
version "4.1.3"
@@ -933,7 +933,7 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
933933
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
934934
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
935935

936-
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
936+
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
937937
version "1.1.3"
938938
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
939939
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
@@ -1060,11 +1060,11 @@ indent-string@^4.0.0:
10601060
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
10611061

10621062
internal-slot@^1.0.3:
1063-
version "1.0.3"
1064-
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
1065-
integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
1063+
version "1.0.4"
1064+
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3"
1065+
integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==
10661066
dependencies:
1067-
get-intrinsic "^1.1.0"
1067+
get-intrinsic "^1.1.3"
10681068
has "^1.0.3"
10691069
side-channel "^1.0.4"
10701070

0 commit comments

Comments
 (0)
Please sign in to comment.