fix(nuxt): respect redirects which differ only by trailing slash (#18593)

Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
Mathieu Magalhaes 2023-02-16 18:26:15 +01:00 committed by GitHub
parent e2fc6f267d
commit f5a3d7968c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 3 deletions

View File

@ -176,7 +176,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
})]) })])
} else if (process.server) { } else if (process.server) {
const currentURL = to.fullPath || '/' const currentURL = to.fullPath || '/'
if (!isEqual(currentURL, initialURL)) { if (!isEqual(currentURL, initialURL, { trailingSlash: true })) {
const event = await callWithNuxt(nuxtApp, useRequestEvent) const event = await callWithNuxt(nuxtApp, useRequestEvent)
const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 } const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 }
await callWithNuxt(nuxtApp, navigateTo, [currentURL, options]) await callWithNuxt(nuxtApp, navigateTo, [currentURL, options])

View File

@ -321,9 +321,17 @@ describe('legacy async data', () => {
describe('navigate', () => { describe('navigate', () => {
it('should redirect to index with navigateTo', async () => { it('should redirect to index with navigateTo', async () => {
const { headers } = await fetch('/navigate-to/', { redirect: 'manual' }) const { headers, status } = await fetch('/navigate-to/', { redirect: 'manual' })
expect(headers.get('location')).toEqual('/') expect(headers.get('location')).toEqual('/')
expect(status).toEqual(301)
})
it('respects redirects + headers in middleware', async () => {
const res = await fetch('/navigate-some-path/', { redirect: 'manual', headers: { 'trailing-slash': 'true' } })
expect(res.headers.get('location')).toEqual('/navigate-some-path')
expect(res.status).toEqual(307)
expect(await res.text()).toMatchInlineSnapshot('"<!DOCTYPE html><html><head><meta http-equiv=\\"refresh\\" content=\\"0; url=/navigate-some-path\\"></head></html>"')
}) })
}) })

View File

@ -1,5 +1,10 @@
import { withoutTrailingSlash } from 'ufo'
export default defineNuxtRouteMiddleware(async (to) => { export default defineNuxtRouteMiddleware(async (to) => {
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
if (useRequestHeaders(['trailing-slash'])['trailing-slash'] && to.fullPath.endsWith('/')) {
return navigateTo(withoutTrailingSlash(to.fullPath), { redirectCode: 307 })
}
if (to.path.startsWith('/redirect/')) { if (to.path.startsWith('/redirect/')) {
await new Promise(resolve => setTimeout(resolve, 100)) await new Promise(resolve => setTimeout(resolve, 100))
return navigateTo(to.path.slice('/redirect/'.length - 1)) return navigateTo(to.path.slice('/redirect/'.length - 1))

View File

@ -3,5 +3,5 @@
</template> </template>
<script setup> <script setup>
await navigateTo('/', { replace: true }) await navigateTo('/', { replace: true, redirectCode: 301 })
</script> </script>