Redirect URLs containing uppercase characters to lowercase (#266)

* Add tests for normalizeURL

* Redirect requests containing uppercase in pathname to lowercase via normalizeURL

* Fix typo
This commit is contained in:
Johan Preynat
2024-03-15 11:24:41 +01:00
committed by GitHub
parent a21673e4c1
commit e462ac837e
3 changed files with 30 additions and 3 deletions
+27 -1
View File
@@ -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'),
);
});
})
+2 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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}`);