From 4311ce79f631a2599b233ead94642bf8cfc6f46e Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 25 Oct 2022 16:15:13 +0200 Subject: [PATCH 1/3] fix(nuxt): allow responding with custom headers from `error.vue` --- packages/nuxt/src/core/runtime/nitro/error.ts | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/error.ts b/packages/nuxt/src/core/runtime/nitro/error.ts index 309ae741526..e5b3ee82034 100644 --- a/packages/nuxt/src/core/runtime/nitro/error.ts +++ b/packages/nuxt/src/core/runtime/nitro/error.ts @@ -1,7 +1,8 @@ import { withQuery } from 'ufo' import type { NitroErrorHandler } from 'nitropack' import type { H3Error } from 'h3' -import { getRequestHeaders } from 'h3' +import { getRequestHeaders, H3Response } from 'h3' +import { useNitroApp } from '#internal/nitro' import { normalizeError, isJsonRequest } from '#internal/nitro/utils' export default async function errorhandler (error: H3Error, event) { @@ -46,14 +47,15 @@ export default async function errorhandler (error: H3Error, // HTML response (via SSR) const isErrorPage = event.req.url?.startsWith('/__nuxt_error') - let html = !isErrorPage - ? await $fetch(withQuery('/__nuxt_error', errorObject), { - headers: getRequestHeaders(event) as HeadersInit + const res = !isErrorPage + ? await useNitroApp().localFetch(withQuery('/__nuxt_error', errorObject), { + headers: getRequestHeaders(event) as Record, + redirect: 'manual' }).catch(() => null) : null // Fallback to static rendered error page - if (!html) { + if (!res) { const { template } = process.dev // @ts-ignore ? await import('@nuxt/ui-templates/templates/error-dev.mjs') @@ -63,9 +65,13 @@ export default async function errorhandler (error: H3Error, // TODO: Support `message` in template (errorObject as any).description = errorObject.message } - html = template(errorObject) + event.res.setHeader('Content-Type', 'text/html;charset=UTF-8') + return event.res.end(template(errorObject)) } - event.res.setHeader('Content-Type', 'text/html;charset=UTF-8') - event.res.end(html) + event.respondWith(new H3Response(await res.text(), { + headers: res.headers, + status: res.status, + statusText: res.statusText + })) } From 86ccbe6607602aee8c5be6fb485c1dbccf73a02a Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 25 Oct 2022 16:23:56 +0200 Subject: [PATCH 2/3] fix: respect error status code + message --- packages/nuxt/src/core/runtime/nitro/error.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/error.ts b/packages/nuxt/src/core/runtime/nitro/error.ts index e5b3ee82034..cc3b8487623 100644 --- a/packages/nuxt/src/core/runtime/nitro/error.ts +++ b/packages/nuxt/src/core/runtime/nitro/error.ts @@ -71,7 +71,7 @@ export default async function errorhandler (error: H3Error, event.respondWith(new H3Response(await res.text(), { headers: res.headers, - status: res.status, - statusText: res.statusText + status: res.status === 200 ? errorObject.statusCode : res.status, + statusText: res.statusText || errorObject.statusMessage })) } From f9a203363fa96a7bc7d8a6902c84a36d0a223adb Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 25 Oct 2022 18:07:43 +0200 Subject: [PATCH 3/3] refactor: remove use of `respondWith` --- packages/nuxt/src/core/runtime/nitro/error.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/error.ts b/packages/nuxt/src/core/runtime/nitro/error.ts index cc3b8487623..d282491426c 100644 --- a/packages/nuxt/src/core/runtime/nitro/error.ts +++ b/packages/nuxt/src/core/runtime/nitro/error.ts @@ -1,7 +1,6 @@ import { withQuery } from 'ufo' import type { NitroErrorHandler } from 'nitropack' -import type { H3Error } from 'h3' -import { getRequestHeaders, H3Response } from 'h3' +import { H3Error, setResponseHeader, getRequestHeaders } from 'h3' import { useNitroApp } from '#internal/nitro' import { normalizeError, isJsonRequest } from '#internal/nitro/utils' @@ -66,12 +65,21 @@ export default async function errorhandler (error: H3Error, (errorObject as any).description = errorObject.message } event.res.setHeader('Content-Type', 'text/html;charset=UTF-8') - return event.res.end(template(errorObject)) + event.res.end(template(errorObject)) + return + } + + for (const [header, value] of res.headers.entries()) { + setResponseHeader(event, header, value) + } + + if (res.status && res.status !== 200) { + event.res.statusCode = res.status + } + + if (res.statusText) { + event.res.statusMessage = res.statusText } - event.respondWith(new H3Response(await res.text(), { - headers: res.headers, - status: res.status === 200 ? errorObject.statusCode : res.status, - statusText: res.statusText || errorObject.statusMessage - })) + event.res.end(await res.text()) }