Skip to content

Commit 4adaa0b

Browse files
authored
fix(nitro): redirect without sending response in render hook (#3922)
1 parent 635b69c commit 4adaa0b

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

src/runtime/server/plugin.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { localeDetector } from '#internal/i18n-locale-detector.mjs'
1313
import { resolveRootRedirect, useI18nDetection, useRuntimeI18n } from '../shared/utils'
1414
import { isFunction } from '@intlify/shared'
1515

16-
import { type H3Event, getRequestURL, sendRedirect, setCookie } from 'h3'
16+
import { type H3Event, getRequestURL, sanitizeStatusCode, setCookie } from 'h3'
1717
import type { CoreOptions } from '@intlify/core'
1818
import { useDetectors } from '../shared/detection'
1919
import { domainFromLocale } from '../shared/domain'
@@ -40,6 +40,19 @@ function* detect(
4040
yield { locale: detection.fallbackLocale, source: 'fallback' }
4141
}
4242

43+
// Adapted from H3 v1
44+
// https://github.com/h3js/h3/blob/24231b9c448aa852b15b889c53253a783f67a126/src/utils/response.ts#L166-L179
45+
function createRedirectResponse(event: H3Event, dest: string, code: number) {
46+
event.node.res.setHeader('location', dest)
47+
event.node.res.statusCode = sanitizeStatusCode(code, event.node.res.statusCode)
48+
49+
return {
50+
headers: event.node.res.getHeaders() as Record<string, string>,
51+
statusCode: event.node.res.statusCode,
52+
body: `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${dest.replace(/"/g, '%22')}"></head></html>`,
53+
}
54+
}
55+
4356
export default defineNitroPlugin(async (nitro) => {
4457
const runtimeI18n = useRuntimeI18n()
4558
const rootRedirect = resolveRootRedirect(runtimeI18n.rootRedirect)
@@ -147,8 +160,9 @@ export default defineNitroPlugin(async (nitro) => {
147160
await initializeI18nContext(event)
148161
})
149162

150-
nitro.hooks.hook('render:before', async ({ event }) => {
163+
nitro.hooks.hook('render:before', async (context) => {
151164
if (!__I18N_SERVER_REDIRECT__) { return }
165+
const { event } = context
152166

153167
const ctx = import.meta.prerender && !event.context.nuxtI18n ? await initializeI18nContext(event) : useI18nContext(event)
154168
const url = getRequestURL(event)
@@ -166,7 +180,7 @@ export default defineNitroPlugin(async (nitro) => {
166180
if (resolved.path && resolved.path !== url.pathname) {
167181
ctx.detectLocale = resolved.locale
168182
detection.useCookie && setCookie(event, detection.cookieKey, resolved.locale, cookieOptions)
169-
await sendRedirect(
183+
context.response = createRedirectResponse(
170184
event,
171185
joinURL(baseUrlGetter(event, ctx.vueI18nOptions!.defaultLocale), resolved.path + url.search),
172186
resolved.code,

0 commit comments

Comments
 (0)