Skip to content

Commit 281957c

Browse files
committed
add normalizeLocationHeader
1 parent f0ffff5 commit 281957c

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

packages/open-next/src/core/routing/middleware.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
convertBodyToReadableStream,
1616
getMiddlewareMatch,
1717
isExternal,
18+
normalizeLocationHeader,
1819
} from "./util.js";
1920

2021
const middlewareManifest = MiddlewareManifest;
@@ -94,6 +95,15 @@ export async function handleMiddleware(
9495
url,
9596
body: convertBodyToReadableStream(internalEvent.method, internalEvent.body),
9697
} as unknown as Request);
98+
if (result.headers.has("Location")) {
99+
result.headers.set(
100+
"Location",
101+
normalizeLocationHeader(
102+
result.headers.get("Location") as string,
103+
internalEvent.url,
104+
),
105+
);
106+
}
97107
const statusCode = result.status;
98108

99109
/* Apply override headers from middleware

packages/open-next/src/core/routing/util.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,23 @@ export async function invalidateCDNOnRequest(
437437
]);
438438
}
439439
}
440+
441+
/**
442+
* Normalizes the Location header to either be a relative path or a full URL.
443+
* If the Location header is relative to the host, it will return a relative path.
444+
* If it is an absolute URL, it will return the full URL.
445+
* Both cases will ensure that the URL is properly encoded according to RFC
446+
*
447+
* @param location The Location header value
448+
* @param url The original request URL
449+
* @returns A normalized Location header value
450+
*/
451+
export function normalizeLocationHeader(location: string, url: string): string {
452+
const locationUrl = new URL(location);
453+
const host = new URL(url).host;
454+
if (locationUrl.host === host) {
455+
// If the location is relative to the host
456+
return locationUrl.href.replace(locationUrl.origin, "");
457+
}
458+
return locationUrl.href;
459+
}

packages/open-next/src/core/routingHandler.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
dynamicRouteMatcher,
2929
staticRouteMatcher,
3030
} from "./routing/routeMatcher";
31-
import { constructNextUrl } from "./routing/util";
31+
import { constructNextUrl, normalizeLocationHeader } from "./routing/util";
3232

3333
export const MIDDLEWARE_HEADER_PREFIX = "x-middleware-response-";
3434
export const MIDDLEWARE_HEADER_PREFIX_LEN = MIDDLEWARE_HEADER_PREFIX.length;
@@ -110,13 +110,13 @@ export default async function routingHandler(
110110
if (redirect) {
111111
// We need to encode the value in the Location header to make sure it is valid according to RFC
112112
// https://stackoverflow.com/a/7654605/16587222
113-
redirect.headers.Location = new URL(
113+
redirect.headers.Location = normalizeLocationHeader(
114114
redirect.headers.Location as string,
115-
).href;
115+
event.url,
116+
);
116117
debug("redirect", redirect);
117118
return redirect;
118119
}
119-
120120
const middlewareEventOrResult = await handleMiddleware(
121121
eventOrResult,
122122
// We need to pass the initial search without any decoding

0 commit comments

Comments
 (0)