diff --git a/.changeset/serious-islands-double.md b/.changeset/serious-islands-double.md new file mode 100644 index 000000000..e922d8eb7 --- /dev/null +++ b/.changeset/serious-islands-double.md @@ -0,0 +1,6 @@ +--- +'@shopify/remix-oxygen': patch +'@shopify/mini-oxygen': patch +--- + +Prevent infinite redirects when a double slash exists in the URL diff --git a/packages/mini-oxygen/src/vite/utils.ts b/packages/mini-oxygen/src/vite/utils.ts index 3763fddfa..4b52e3944 100644 --- a/packages/mini-oxygen/src/vite/utils.ts +++ b/packages/mini-oxygen/src/vite/utils.ts @@ -10,13 +10,12 @@ import type {ViteDevServer} from 'vite'; */ export function toURL(req: string | IncomingMessage = '/', origin?: string) { const isRequest = typeof req !== 'string'; - const pathname = (isRequest ? req.url : req) || '/'; + let pathname = (isRequest ? req.url : req) || '/'; return new URL( - pathname, - origin || + (origin || (isRequest && req.headers.host && `http://${req.headers.host}`) || - 'http://example.com', + 'http://example.com') + pathname, ); } diff --git a/packages/remix-oxygen/src/server.ts b/packages/remix-oxygen/src/server.ts index 93e20797d..c6ed82b00 100644 --- a/packages/remix-oxygen/src/server.ts +++ b/packages/remix-oxygen/src/server.ts @@ -33,6 +33,17 @@ export function createRequestHandler({ }); } + const url = new URL(request.url); + + if (url.pathname.includes('//')) { + return new Response(null, { + status: 301, + headers: { + location: url.pathname.replace(/\/+/g, '/'), + }, + }); + } + const context = getLoadContext ? ((await getLoadContext(request)) as AppLoadContext) : undefined;