feat: add trailingSlash middleware

This commit is contained in:
Arvid Norlin
2025-05-12 12:01:47 +02:00
parent 2cdd086ef3
commit c22cd62d21
3 changed files with 35 additions and 4 deletions

View File

@@ -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 });

View File

@@ -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,

View File

@@ -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("/")
}