Skip to content

Commit

Permalink
Add support for middleware (#10)
Browse files Browse the repository at this point in the history
* Add support for middleware

* Update README.md
  • Loading branch information
fwang committed Dec 19, 2022
1 parent 84d84b6 commit 9c4211d
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 131 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ OpenNext aims to support all Next.js 13 features. Some features are work in prog
- [x] Static site generation (SSG)
- [x] Server-side rendering (SSR)
- [x] Incremental static regeneration (ISR)
- [x] Middleware
- [ ] Image optimization (work in progress)
- [ ] Middleware (work in progress)

## Quick start

Expand Down
158 changes: 43 additions & 115 deletions cli/assets/middleware-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,13 @@ Object.assign(globalThis, {
});
const index = await (() => import("./middleware.js"))();

// TODO
//console.log(self);
//handler({
// Records: [
// {
// cf: {
// request: {
// uri: "https://sst.dev/_next/data/5fCVTp6Xr7VQpZ-m8Wxxq/middleware-redirect.json",
// method: "GET",
// headers: {
// host: [{ value: "sst.dev" }]
// },
// querystring: "",
// },
// }
// }
// ]
//}).then((res) => console.log(JSON.stringify(res, null, 2)));

export async function handler(event) {
// Convert CloudFront request to Node request
const request = event.Records[0].cf.request;
const { uri, method, headers, querystring, body } = request;
console.log(uri);
console.log(request);
console.log(request.headers);
const requestHeaders = new Headers();
for (const [key, values] of Object.entries(headers)) {
for (const { value } of values) {
Expand All @@ -59,112 +41,58 @@ export async function handler(event) {
waitUntil: () => {},
});

// Build headers
(response.headers.get("x-middleware-override-headers") || "")
.split(",")
.forEach(key => {
headers[key] = [{
key,
value: response.headers.get(`x-middleware-request-${key}`)
}];
});

// WORKAROUND (AWS): pass middleware headers to server
if (response.headers.get("x-middleware-next") === "1") {
headers["x-wahaha"] = [{ key: "x-wahaha", value: "wahaha" }];
headers["wahaha"] = [{ key: "wahaha", value: "wahaha" }];
console.log("== getMiddlewareHeaders ==", response.headers);
headers["x-op-middleware-request-headers"] = [{
key: "x-op-middleware-request-headers",
value: getMiddlewareRequestHeaders(response),
}];
headers["x-op-middleware-response-headers"] = [{
key: "x-op-middleware-response-headers",
value: getMiddlewareResponseHeaders(response),
}];
console.log("== conitnue to origin ==", request)
return request;
}

console.log("== do not hit origin ==", {
console.log("== do not hit origin ==", response, {
status: response.status,
headers,
headers: httpHeadersToCfHeaders(response.headers),
});
return {
status: response.status,
headers,
}
headers: httpHeadersToCfHeaders(response.headers),
};
}

/**
* middleware-fetch
*
* nextresponse [response] {
size: 0,
[symbol(body internals)]: {
body: null,
stream: null,
boundary: null,
disturbed: false,
error: null
},
[symbol(response internals)]: {
type: 'default',
url: undefined,
status: 200,
statustext: '',
headers: { 'x-middleware-next': '1' },
counter: undefined,
highwatermark: undefined
},
[Symbol(internal response)]: {
cookies: ResponseCookies { _parsed: Map(0) {}, _headers: [Object] },
url: undefined
}
}
*/
/**
* middleware-set-header
*
* NextResponse [Response] {
size: 0,
[Symbol(Body internals)]: {
body: null,
stream: null,
boundary: null,
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
type: 'default',
url: undefined,
status: 200,
statusText: '',
headers: {
'x-hello-from-middleware2': 'hello',
'x-middleware-next': '1',
'x-middleware-override-headers': 'x-hello-from-middleware1',
'x-middleware-request-x-hello-from-middleware1': 'hello'
},
counter: undefined,
highWaterMark: undefined
},
[Symbol(internal response)]: {
cookies: ResponseCookies { _parsed: Map(0) {}, _headers: [Object] },
url: undefined
}
function getMiddlewareRequestHeaders(response) {
const headers = {};
(response.headers.get("x-middleware-override-headers") || "")
.split(",")
.forEach(key => {
headers[key] = response.headers.get(`x-middleware-request-${key}`)
});
console.log("== getMiddlewareRequestHeaders ==", headers);
return JSON.stringify(headers);
}
*/
/**
* middleware-redirect
*
* Response {
size: 0,
[Symbol(Body internals)]: {
body: null,
stream: null,
boundary: null,
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
type: 'default',
url: '',
status: 307,
statusText: '',
headers: { location: 'https://sst.dev/ssr' },
counter: undefined,
highWaterMark: undefined
}

function getMiddlewareResponseHeaders(response) {
const headers = {};
response.headers.forEach((value, key) => {
if (!key.startsWith("x-middleware-")) {
headers[key] = value;
}
});
console.log("== getMiddlewareResponseHeaders ==", headers);
return JSON.stringify(headers);
}
*/

function httpHeadersToCfHeaders(httpHeaders) {
const headers = {};
httpHeaders.forEach((value, key) => {
headers[key] = [{ key, value }];
});
console.log("== responseHeadersToCloudFrontHeaders ==", headers);
return headers;
}
13 changes: 13 additions & 0 deletions cli/assets/server-adapter.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,26 @@ export const handler = async (event) => {
console.log(event)
console.log(event.rawPath)

// WORKAROUND (AWS): pass middleware headers to server
const middlewareRequestHeaders = JSON.parse(
event.headers["x-op-middleware-request-headers"] || "{}"
);
event.headers = { ...event.headers, ...middlewareRequestHeaders };

const response = await server(event);

// Handle cache response headers not set for HTML pages
const htmlPages = loadHtmlPages();
if (htmlPages.includes(event.rawPath) && !response.headers["cache-control"]) {
response.headers["cache-control"] = "public, max-age=0, s-maxage=31536000, must-revalidate";
}

// WORKAROUND (AWS): pass middleware headers to server
const middlewareResponseHeaders = JSON.parse(
event.headers["x-op-middleware-response-headers"] || "{}"
);
response.headers = { ...response.headers, ...middlewareResponseHeaders };

console.log({ after: response });

return response;
Expand Down
2 changes: 1 addition & 1 deletion cli/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function createMiddlewareBundle(src: string) {
fs.mkdirSync(outputPath, { recursive: true });

// Create the middleware code
const buildTempPath = path.resolve(__dirname, "../.middleware-build");
const buildTempPath = path.join(outputDir, "../.middleware-build");
fs.mkdirSync(buildTempPath, { recursive: true });
fs.writeFileSync(path.join(buildTempPath, "middleware.js"), src);
fs.copyFileSync(
Expand Down
28 changes: 14 additions & 14 deletions cli/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,9 @@
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==

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

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

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

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

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

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

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

Expand Down

0 comments on commit 9c4211d

Please sign in to comment.