Skip to content

Commit e462ac8

Browse files
authored
Redirect URLs containing uppercase characters to lowercase (#266)
* Add tests for normalizeURL * Redirect requests containing uppercase in pathname to lowercase via normalizeURL * Fix typo
1 parent a21673e commit e462ac8

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

src/lib/middleware.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect } from 'bun:test';
22

3-
import { getURLLookupAlternatives } from './middleware';
3+
import { getURLLookupAlternatives, normalizeURL } from './middleware';
44

55
describe('getURLLookupAlternatives', () => {
66
it('should return all URLs up to the root', () => {
@@ -104,3 +104,29 @@ describe('getURLLookupAlternatives', () => {
104104
]);
105105
});
106106
});
107+
108+
describe('normalizeURL', () => {
109+
it('should remove trailing slashes', () => {
110+
expect(normalizeURL(new URL('https://docs.mycompany.com/hello/'))).toEqual(
111+
new URL('https://docs.mycompany.com/hello'),
112+
);
113+
});
114+
115+
it('should remove duplicate slashes', () => {
116+
expect(normalizeURL(new URL('https://docs.mycompany.com//hello//there'))).toEqual(
117+
new URL('https://docs.mycompany.com/hello/there'),
118+
);
119+
});
120+
121+
it('should convert uppercase characters in the path to lowercase', () => {
122+
expect(normalizeURL(new URL('https://docs.mycompany.com/Hello/My/pAge'))).toEqual(
123+
new URL('https://docs.mycompany.com/hello/my/page'),
124+
);
125+
});
126+
127+
it('should not affect uppercase characters in querystring parameters', () => {
128+
expect(normalizeURL(new URL('https://docs.mycompany.com/Hello/My/pAge?Q=MySearch'))).toEqual(
129+
new URL('https://docs.mycompany.com/hello/my/page?Q=MySearch'),
130+
);
131+
});
132+
})

src/lib/middleware.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ export function getURLLookupAlternatives(input: URL) {
9090

9191
/**
9292
* Normalize a URL to remove duplicate slashes and trailing slashes
93+
* and transform the pathname to lowercase.
9394
*/
9495
export function normalizeURL(url: URL) {
9596
const result = new URL(url);
96-
result.pathname = url.pathname.replace(/\/{2,}/g, '/').replace(/\/$/, '');
97+
result.pathname = url.pathname.replace(/\/{2,}/g, '/').replace(/\/$/, '').toLowerCase();
9798
return result;
9899
}

src/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export async function middleware(request: NextRequest) {
140140
revision: resolved.revision,
141141
});
142142

143-
// Because of how Next will encode, we need to encode ourselves the pathname before reriting to it.
143+
// Because of how Next will encode, we need to encode ourselves the pathname before rewriting to it.
144144
const rewritePathname = normalizePathname(encodePathname(resolved.pathname));
145145

146146
console.log(`${request.method} (${resolved.space}) ${rewritePathname}`);

0 commit comments

Comments
 (0)