fix(nuxt): let router handle internal redirects within middleware (#18445)

This commit is contained in:
Daniel Roe 2023-01-23 11:18:33 +00:00 committed by GitHub
parent c5d6db7fd0
commit de4086f6ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import type { NuxtError } from './error' import type { NuxtError } from './error'
import { createError } from './error' import { createError } from './error'
import { useState } from './state' import { useState } from './state'
import { setResponseStatus } from './ssr'
export const useRouter = () => { export const useRouter = () => {
return useNuxtApp()?.$router as Router return useNuxtApp()?.$router as Router
@ -97,8 +98,15 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
if (process.server) { if (process.server) {
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
if (nuxtApp.ssrContext && nuxtApp.ssrContext.event) { if (nuxtApp.ssrContext && nuxtApp.ssrContext.event) {
// Let vue-router handle internal redirects within middleware
// to prevent the navigation happening after response is sent
if (isProcessingMiddleware() && !isExternal) {
setResponseStatus(options?.redirectCode || 302)
return to
}
const redirectLocation = isExternal ? toPath : joinURL(useRuntimeConfig().app.baseURL, router.resolve(to).fullPath || '/') const redirectLocation = isExternal ? toPath : joinURL(useRuntimeConfig().app.baseURL, router.resolve(to).fullPath || '/')
return nuxtApp.callHook('app:redirected').then(() => sendRedirect(nuxtApp.ssrContext!.event, redirectLocation, options?.redirectCode || 302)) return nuxtApp.callHook('app:redirected')
.then(() => sendRedirect(nuxtApp.ssrContext!.event, redirectLocation, options?.redirectCode || 302))
} }
} }

View File

@ -1,7 +1,7 @@
import { reactive, h, isReadonly } from 'vue' import { reactive, h, isReadonly } from 'vue'
import { parseURL, stringifyParsedURL, parseQuery, stringifyQuery, withoutBase, isEqual, joinURL } from 'ufo' import { parseURL, stringifyParsedURL, parseQuery, stringifyQuery, withoutBase, isEqual, joinURL } from 'ufo'
import { createError } from 'h3' import { createError } from 'h3'
import { defineNuxtPlugin, clearError, navigateTo, showError, useRuntimeConfig, useState } from '..' import { defineNuxtPlugin, clearError, navigateTo, showError, useRuntimeConfig, useState, useRequestEvent } from '..'
import { callWithNuxt } from '../nuxt' import { callWithNuxt } from '../nuxt'
// @ts-ignore // @ts-ignore
import { globalMiddleware } from '#build/middleware' import { globalMiddleware } from '#build/middleware'
@ -250,7 +250,9 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
await router.replace(initialURL) await router.replace(initialURL)
if (!isEqual(route.fullPath, initialURL)) { if (!isEqual(route.fullPath, initialURL)) {
await callWithNuxt(nuxtApp, navigateTo, [route.fullPath]) const event = await callWithNuxt(nuxtApp, useRequestEvent)
const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 }
await callWithNuxt(nuxtApp, navigateTo, [route.fullPath, options])
} }
}) })

View File

@ -12,7 +12,7 @@ import {
import { createError } from 'h3' import { createError } from 'h3'
import { withoutBase, isEqual } from 'ufo' import { withoutBase, isEqual } from 'ufo'
import type NuxtPage from '../page' import type NuxtPage from '../page'
import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, showError, clearError, navigateTo, useError, useState } from '#app' import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, showError, clearError, navigateTo, useError, useState, useRequestEvent } from '#app'
// @ts-ignore // @ts-ignore
import _routes from '#build/routes' import _routes from '#build/routes'
// @ts-ignore // @ts-ignore
@ -179,7 +179,9 @@ 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)) {
await callWithNuxt(nuxtApp, navigateTo, [currentURL]) const event = await callWithNuxt(nuxtApp, useRequestEvent)
const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 }
await callWithNuxt(nuxtApp, navigateTo, [currentURL, options])
} }
} }
}) })