From e462ac837e54f95ee1055cb0283a35a642cf3da7 Mon Sep 17 00:00:00 2001 From: Johan Preynat Date: Fri, 15 Mar 2024 11:24:41 +0100 Subject: [PATCH] Redirect URLs containing uppercase characters to lowercase (#266) * Add tests for normalizeURL * Redirect requests containing uppercase in pathname to lowercase via normalizeURL * Fix typo --- src/lib/middleware.test.ts | 28 +++++++++++++++++++++++++++- src/lib/middleware.ts | 3 ++- src/middleware.ts | 2 +- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/lib/middleware.test.ts b/src/lib/middleware.test.ts index 81dc48fd0..a61f300ef 100644 --- a/src/lib/middleware.test.ts +++ b/src/lib/middleware.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'bun:test'; -import { getURLLookupAlternatives } from './middleware'; +import { getURLLookupAlternatives, normalizeURL } from './middleware'; describe('getURLLookupAlternatives', () => { it('should return all URLs up to the root', () => { @@ -104,3 +104,29 @@ describe('getURLLookupAlternatives', () => { ]); }); }); + +describe('normalizeURL', () => { + it('should remove trailing slashes', () => { + expect(normalizeURL(new URL('https://docs.mycompany.com/hello/'))).toEqual( + new URL('https://docs.mycompany.com/hello'), + ); + }); + + it('should remove duplicate slashes', () => { + expect(normalizeURL(new URL('https://docs.mycompany.com//hello//there'))).toEqual( + new URL('https://docs.mycompany.com/hello/there'), + ); + }); + + it('should convert uppercase characters in the path to lowercase', () => { + expect(normalizeURL(new URL('https://docs.mycompany.com/Hello/My/pAge'))).toEqual( + new URL('https://docs.mycompany.com/hello/my/page'), + ); + }); + + it('should not affect uppercase characters in querystring parameters', () => { + expect(normalizeURL(new URL('https://docs.mycompany.com/Hello/My/pAge?Q=MySearch'))).toEqual( + new URL('https://docs.mycompany.com/hello/my/page?Q=MySearch'), + ); + }); +}) \ No newline at end of file diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index 50b5a55e7..1359ce94d 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -90,9 +90,10 @@ export function getURLLookupAlternatives(input: URL) { /** * Normalize a URL to remove duplicate slashes and trailing slashes + * and transform the pathname to lowercase. */ export function normalizeURL(url: URL) { const result = new URL(url); - result.pathname = url.pathname.replace(/\/{2,}/g, '/').replace(/\/$/, ''); + result.pathname = url.pathname.replace(/\/{2,}/g, '/').replace(/\/$/, '').toLowerCase(); return result; } diff --git a/src/middleware.ts b/src/middleware.ts index be757aa01..5a347f70f 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -140,7 +140,7 @@ export async function middleware(request: NextRequest) { revision: resolved.revision, }); - // Because of how Next will encode, we need to encode ourselves the pathname before reriting to it. + // Because of how Next will encode, we need to encode ourselves the pathname before rewriting to it. const rewritePathname = normalizePathname(encodePathname(resolved.pathname)); console.log(`${request.method} (${resolved.space}) ${rewritePathname}`);