diff --git a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts index d27ac56bb269..b441b39eaebf 100644 --- a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts +++ b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts @@ -813,15 +813,15 @@ describe('createServeRequestHandler', () => { ).resolves.toBe('500 Internal Server Error'); }); - // TODO fix: answer 400, like other ".." segments going above the root - it('redirects ".." segments that reach the name of the fake root', async () => { + // Like other ".." segments going above the root + it('answers 400 to ".." segments that reach the name of the fake root', async () => { await expect( serveRequest( {baseUrl: '/', trailingSlash: undefined}, '/../__docusaurus_root__/file.html', {asIs: true}, ), - ).resolves.toBe('301 /file → 200 file.html'); + ).resolves.toBe('400 Bad Request'); }); // Browsers send the baseUrl percent-encoded: "/caf%C3%A9/" diff --git a/packages/docusaurus/src/commands/serve/requestHandler.ts b/packages/docusaurus/src/commands/serve/requestHandler.ts index c8cb6fabd3b1..f40df5088ab1 100644 --- a/packages/docusaurus/src/commands/serve/requestHandler.ts +++ b/packages/docusaurus/src/commands/serve/requestHandler.ts @@ -159,7 +159,20 @@ async function getRedirectLocation( // Like parseURLPath(), but undefined when ".." segments go above the root // It also keeps "//host/path" as a path instead of parsing another host function parseRootURLPath(url: string): URLPath | undefined { - const fakeRoot = '/__docusaurus_root__'; + // ".." segments going above the root can reach the name of a fake root, + // like "/../__docusaurus_root__/file", but not the names of 2 fake roots + const urlPath = parseFakeRootURLPath(url, '/__docusaurus_root__'); + const otherUrlPath = parseFakeRootURLPath(url, '/__docusaurus_other_root__'); + if (urlPath === undefined || otherUrlPath === undefined) { + return undefined; + } + return urlPath; +} + +function parseFakeRootURLPath( + url: string, + fakeRoot: string, +): URLPath | undefined { const {pathname, search} = parseURLPath(`.${url}`, `${fakeRoot}/`); if (!pathname.startsWith(`${fakeRoot}/`)) { return undefined;