diff --git a/apps/scandic-redirect/netlify/functions/redirect.mts b/apps/scandic-redirect/netlify/functions/redirect.mts index 17ae8b956..139fdee08 100644 --- a/apps/scandic-redirect/netlify/functions/redirect.mts +++ b/apps/scandic-redirect/netlify/functions/redirect.mts @@ -22,8 +22,9 @@ export default async (req: Request) => { data.shift(); } data.push(chunk.toString()); - - const re = new RegExp(`"${body.pathname}":"([^"]+)"`); + // Since we strip trailing slash (in the trailingSlash middleware) before entering this middleware, + // we need check matching paths both including and excluding trailing slash. + const re = new RegExp(`"${body.pathname}\/?":"([^"]+)"`); const match = data.join("").match(re); if (match?.[1]) { @@ -46,10 +47,14 @@ export default async (req: Request) => { ); if (redirectUrl) { - if (redirectUrl === body.pathname) { + // Make sure to exclude trailing slash in the redirectUrl to avoid an extra middleware roundtrip + const redirectUrlWithoutTrailingSlash = redirectUrl.endsWith("/") + ? redirectUrl.slice(0, -1) + : redirectUrl; + if (redirectUrlWithoutTrailingSlash === body.pathname) { return new Response("Not Found", { status: 404 }); } - return new Response(redirectUrl); + return new Response(redirectUrlWithoutTrailingSlash); } } return new Response("Not Found", { status: 404 }); diff --git a/apps/scandic-web/middleware.ts b/apps/scandic-web/middleware.ts index ee0a9b76f..19d32a382 100644 --- a/apps/scandic-web/middleware.ts +++ b/apps/scandic-web/middleware.ts @@ -15,6 +15,7 @@ import * as handleAuth from "@/middlewares/handleAuth" import * as myPages from "@/middlewares/myPages" import * as redirect from "@/middlewares/redirect" import * as sasXScandic from "@/middlewares/sasXScandic" +import * as trailingSlash from "@/middlewares/trailingSlash" import { getDefaultRequestHeaders } from "@/middlewares/utils" import * as webView from "@/middlewares/webView" import { findLang } from "@/utils/languages" @@ -49,6 +50,7 @@ export const middleware: NextMiddleware = async (request, event) => { // Note that the order of middlewares is important since that is the order they are matched by. const middlewares = [ + trailingSlash, currentWebLogin, currentWebLoginEmail, currentWebLogout, diff --git a/apps/scandic-web/middlewares/trailingSlash.ts b/apps/scandic-web/middlewares/trailingSlash.ts new file mode 100644 index 000000000..5bb2fb7cd --- /dev/null +++ b/apps/scandic-web/middlewares/trailingSlash.ts @@ -0,0 +1,24 @@ +import { type NextMiddleware, NextResponse } from "next/server" + +import { getPublicNextURL } from "@/server/utils" + +import { getDefaultRequestHeaders } from "./utils" + +import type { MiddlewareMatcher } from "@/types/middleware" + +export const middleware: NextMiddleware = async (request) => { + const headers = getDefaultRequestHeaders(request) + + const newUrl = new URL( + request.nextUrl.pathname.slice(0, -1), + getPublicNextURL(request) + ) + + return NextResponse.redirect(newUrl, { + headers, + }) +} + +export const matcher: MiddlewareMatcher = (request) => { + return request.nextUrl.pathname.endsWith("/") +}