fix(core): prevent 404 when accessing /page.html (#7184)

This commit is contained in:
Joshua Chen 2022-04-22 23:44:11 +08:00 committed by GitHub
parent 4e4aa6add7
commit c4e92c89e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 18 deletions

View file

@ -12,6 +12,7 @@ process.env.TZ = 'UTC';
const ignorePatterns = [
'/node_modules/',
'__fixtures__',
'__mocks__',
'/testUtils.ts',
'/packages/docusaurus/lib',
'/packages/docusaurus-logger/lib',

View file

@ -0,0 +1,30 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export default [
{
path: '/page.html',
exact: true,
component: '',
},
{
path: '/docs',
exact: false,
component: '',
routes: [
{
path: '/docs/installation',
exact: true,
component: '',
},
],
},
{
path: '*',
component: '',
},
];

View file

@ -43,6 +43,33 @@ describe('normalizeLocation', () => {
});
});
it('removes html extension', () => {
expect(
normalizeLocation({
pathname: '/docs/installation.html',
}),
).toEqual({
pathname: '/docs/installation',
});
expect(
normalizeLocation({
pathname: '/docs/introduction/foo.html',
search: '',
hash: '#bar',
}),
).toEqual({
pathname: '/docs/introduction/foo',
search: '',
hash: '#bar',
});
});
it('does not strip extension if the route location has one', () => {
expect(normalizeLocation({pathname: '/page.html'})).toEqual({
pathname: '/page.html',
});
});
it('leaves pathnames untouched', () => {
const replaceMock = jest.spyOn(String.prototype, 'replace');
@ -72,18 +99,6 @@ describe('normalizeLocation', () => {
});
expect(replaceMock).toBeCalledTimes(1);
expect(
normalizeLocation({
pathname: '/docs/introduction/foo.html',
search: '',
hash: '#bar',
}),
).toEqual({
pathname: '/docs/introduction/foo.html',
search: '',
hash: '#bar',
});
expect(
normalizeLocation({
pathname: '/',

View file

@ -5,23 +5,33 @@
* LICENSE file in the root directory of this source tree.
*/
import {matchRoutes} from 'react-router-config';
import routes from '@generated/routes';
import type {Location} from 'history';
// Memoize previously normalized pathnames.
const pathnames: {[rawPathname: string]: string} = {};
const pathnames = new Map<string, string>();
export default function normalizeLocation<T extends Location>(location: T): T {
if (pathnames[location.pathname]) {
if (pathnames.has(location.pathname)) {
return {
...location,
pathname: pathnames[location.pathname],
pathname: pathnames.get(location.pathname),
};
}
const pathname =
location.pathname.trim().replace(/\/index\.html$/, '') || '/';
// If the location was registered with an `.html` extension, we don't strip it
// away, or it will render to a 404 page.
const matchedRoutes = matchRoutes(routes, location.pathname);
if (matchedRoutes.some(({route}) => route.exact === true)) {
pathnames.set(location.pathname, location.pathname);
return location;
}
pathnames[location.pathname] = pathname;
const pathname =
location.pathname.trim().replace(/(?:\/index)?\.html$/, '') || '/';
pathnames.set(location.pathname, pathname);
return {
...location,

View file

@ -1 +1,5 @@
---
slug: dummy.html
---
# Just a dummy page