未验证 提交 6ff3a63a 编写于 作者: J Jan Potoms 提交者: GitHub

Fix link to file url behavior with trailingSlash (#14681)

Avoid trailing slashes on urls that look like files. The redirect for `trailingSlash: true` will now look like:

```
Redirects

┌ source: /:path*/:file.:ext/
├ destination: /:path*/:file.:ext
└ permanent: true

┌ source: /:path*/:notfile([^/.]+)
├ destination: /:path*/:notfile/
└ permanent: true
```

The default still looks like:

```
Redirects

┌ source: /:path+/
├ destination: /:path+
└ permanent: true
```
After this gets merged, I have a few optimizations planned on the normalization code that should reduce the client bundle a little and that consolidates the `trailingSlash` and `exportTrailingSlash` options
上级 2ad0b5ba
......@@ -346,17 +346,26 @@ export default async function loadCustomRoutes(
])
redirects.unshift(
config.experimental.trailingSlash
? {
source: '/:path+',
destination: '/:path+/',
permanent: true,
}
: {
source: '/:path+/',
destination: '/:path+',
permanent: true,
}
...(config.experimental.trailingSlash
? [
{
source: '/:path*/:file.:ext/',
destination: '/:path*/:file.:ext',
permanent: true,
},
{
source: '/:path*/:notfile([^/.]+)',
destination: '/:path*/:notfile/',
permanent: true,
},
]
: [
{
source: '/:path+/',
destination: '/:path+',
permanent: true,
},
])
)
return {
......
......@@ -2,11 +2,19 @@ export function normalizeTrailingSlash(
path: string,
requireSlash?: boolean
): string {
if (path === '/') {
return path
} else if (path.endsWith('/')) {
return requireSlash ? path : path.slice(0, -1)
if (requireSlash) {
if (!path.endsWith('/') && !/\.[^/]+$/.test(path)) {
return path + '/'
} else if (/\.[^/]+\/$/.test(path)) {
return path.slice(0, -1)
} else {
return path
}
} else {
return requireSlash ? path + '/' : path
if (path.endsWith('/') && path !== '/') {
return path.slice(0, -1)
} else {
return path
}
}
}
......@@ -118,6 +118,7 @@ function testWithoutTrailingSlash() {
testShouldRedirect([
['/about/', '/about'],
['/catch-all/hello/world/', '/catch-all/hello/world'],
['/catch-all/hello.world/', '/catch-all/hello.world'],
])
testShouldResolve([
......@@ -138,6 +139,8 @@ function testWithoutTrailingSlash() {
['/about/', '/about'],
['/about?hello=world', '/about?hello=world'],
['/about/?hello=world', '/about?hello=world'],
['/catch-all/hello/', '/catch-all/hello'],
['/catch-all/hello.world/', '/catch-all/hello.world'],
])
}
......@@ -145,6 +148,7 @@ function testWithTrailingSlash() {
testShouldRedirect([
['/about', '/about/'],
['/catch-all/hello/world', '/catch-all/hello/world/'],
['/catch-all/hello.world/', '/catch-all/hello.world'],
])
testShouldResolve([
......@@ -165,6 +169,8 @@ function testWithTrailingSlash() {
['/about/', '/about/'],
['/about?hello=world', '/about/?hello=world'],
['/about/?hello=world', '/about/?hello=world'],
['/catch-all/hello/', '/catch-all/hello/'],
['/catch-all/hello.world/', '/catch-all/hello.world'],
])
}
......@@ -273,8 +279,13 @@ describe('Trailing slashes', () => {
expect.objectContaining({
redirects: expect.arrayContaining([
expect.objectContaining({
source: '/:path+',
destination: '/:path+/',
source: '/:path*/:file.:ext/',
destination: '/:path*/:file.:ext',
statusCode: 308,
}),
expect.objectContaining({
source: '/:path*/:notfile([^/.]+)',
destination: '/:path*/:notfile/',
statusCode: 308,
}),
]),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册