diff --git a/packages/bridge/package.json b/packages/bridge/package.json index d974054ba3..2be2d0815e 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -44,7 +44,7 @@ "magic-string": "^0.26.1", "mlly": "^0.5.1", "murmurhash-es": "^0.1.1", - "nitropack": "^0.2.6", + "nitropack": "^0.2.7", "node-fetch": "^3.2.3", "nuxi": "3.0.0", "ohash": "^0.1.0", diff --git a/packages/bridge/src/nitro.ts b/packages/bridge/src/nitro.ts index 4a37520fab..9be2d55a8d 100644 --- a/packages/bridge/src/nitro.ts +++ b/packages/bridge/src/nitro.ts @@ -69,6 +69,7 @@ export async function setupNitroBridge () { buildDir: resolve(nuxt.options.buildDir), scanDirs: nuxt.options._layers.map(layer => join(layer.config.srcDir, 'server')), renderer: resolve(distDir, 'runtime/nitro/renderer'), + errorHandler: resolve(distDir, 'runtime/nitro/error'), nodeModulesDirs: nuxt.options.modulesDir, handlers, devHandlers: [], @@ -116,9 +117,6 @@ export async function setupNitroBridge () { '#vue-renderer': resolve(distDir, 'runtime/nitro/vue2'), '#vue2-server-renderer': 'vue-server-renderer/' + (nuxt.options.dev ? 'build.dev.js' : 'build.prod.js'), - // Error renderer - '#nitro/error': resolve(distDir, 'runtime/nitro/error'), - // Paths '#paths': resolve(distDir, 'runtime/nitro/paths'), diff --git a/packages/nuxt3/package.json b/packages/nuxt3/package.json index 2e0ea68200..8756fcbc1f 100644 --- a/packages/nuxt3/package.json +++ b/packages/nuxt3/package.json @@ -50,7 +50,7 @@ "knitwork": "^0.1.1", "magic-string": "^0.26.1", "mlly": "^0.5.1", - "nitropack": "^0.2.6", + "nitropack": "^0.2.7", "nuxi": "3.0.0", "ohash": "^0.1.0", "ohmyfetch": "^0.4.15", diff --git a/packages/nuxt3/src/core/nitro.ts b/packages/nuxt3/src/core/nitro.ts index 2c43c169fc..cb69bbd27c 100644 --- a/packages/nuxt3/src/core/nitro.ts +++ b/packages/nuxt3/src/core/nitro.ts @@ -25,6 +25,7 @@ export async function initNitro (nuxt: Nuxt) { buildDir: nuxt.options.buildDir, scanDirs: nuxt.options._layers.map(layer => join(layer.config.srcDir, 'server')), renderer: resolve(distDir, 'core/runtime/nitro/renderer'), + errorHandler: resolve(distDir, 'core/runtime/nitro/error'), nodeModulesDirs: nuxt.options.modulesDir, handlers, devHandlers: [], @@ -77,9 +78,6 @@ export async function initNitro (nuxt: Nuxt) { // Renderer '#vue-renderer': resolve(distDir, 'core/runtime/nitro/vue3'), - // Error renderer - '#nitro/error': resolve(distDir, 'core/runtime/nitro/error'), - // Paths '#paths': resolve(distDir, 'core/runtime/nitro/paths'), diff --git a/packages/nuxt3/src/core/runtime/nitro/error.ts b/packages/nuxt3/src/core/runtime/nitro/error.ts index b7e30e2f87..fa5059bd71 100644 --- a/packages/nuxt3/src/core/runtime/nitro/error.ts +++ b/packages/nuxt3/src/core/runtime/nitro/error.ts @@ -1,10 +1,13 @@ -import type { CompatibilityEvent } from 'h3' import { withQuery } from 'ufo' +import type { NitroErrorHandler } from 'nitropack' +// @ts-ignore TODO import { normalizeError, isJsonRequest } from '#nitro/utils' -export default async function handleError (error: any, event: CompatibilityEvent) { - const { stack, statusCode, statusMessage, message } = normalizeError(error) +export default async function errorhandler (_error, event) { + // Parse and normalize error + const { stack, statusCode, statusMessage, message } = normalizeError(_error) + // Create an error object const errorObject = { url: event.req.url, statusCode, @@ -14,24 +17,30 @@ export default async function handleError (error: any, event: CompatibilityEvent ? `
${stack.map(i => `${i.text}`).join('\n')}
` : '' } - event.res.statusCode = error.statusCode || 500 - event.res.statusMessage = error.statusMessage || 'Internal Server Error' + + // Set response code and message + event.res.statusCode = errorObject.statusCode + event.res.statusMessage = errorObject.statusMessage // Console output - if (error.statusCode !== 404) { - console.error('[nuxt] [request error]', error.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) + if (errorObject.statusCode !== 404) { + console.error('[nuxt] [request error]', errorObject.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) } // JSON response if (isJsonRequest(event)) { event.res.setHeader('Content-Type', 'application/json') - return event.res.end(JSON.stringify(errorObject)) + event.res.end(JSON.stringify(errorObject)) + return } // HTML response const url = withQuery('/__nuxt_error', errorObject as any) - const html = await $fetch(url).catch(() => errorObject.statusMessage) + const html = await $fetch(url).catch((error) => { + console.error('[nitro] Error while generating error response', error) + return errorObject.statusMessage + }) event.res.setHeader('Content-Type', 'text/html;charset=UTF-8') - return event.res.end(html) + event.res.end(html) } diff --git a/test/basic.test.ts b/test/basic.test.ts index 02e859fee9..ba47d1fcca 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -155,14 +155,13 @@ describe('errors', () => { expect(res.status).toBe(500) const error = await res.json() delete error.stack - expect(error).toMatchInlineSnapshot(` - { - "message": "This is a custom error", - "statusCode": 500, - "statusMessage": "Internal Server Error", - "url": "/error", - } - `) + expect(error).toMatchObject({ + description: process.env.NUXT_TEST_DEV ? expect.stringContaining('
') : '',
+      message: 'This is a custom error',
+      statusCode: 500,
+      statusMessage: 'Internal Server Error',
+      url: '/error'
+    })
   })
 
   it('should render a HTML error page', async () => {
diff --git a/test/bridge.test.ts b/test/bridge.test.ts
index 58a47ff72b..3a7b9800a4 100644
--- a/test/bridge.test.ts
+++ b/test/bridge.test.ts
@@ -35,14 +35,13 @@ describe.skip('fixtures:bridge', async () => {
       expect(res.status).toBe(500)
       const error = await res.json()
       delete error.stack
-      expect(error).toMatchInlineSnapshot(`
-      {
-        "message": "This is a custom error",
-        "statusCode": 500,
-        "statusMessage": "Internal Server Error",
-        "url": "/error",
-      }
-    `)
+      expect(error).toMatchObject({
+        description: process.env.NUXT_TEST_DEV ? expect.stringContaining('
') : '',
+        message: 'This is a custom error',
+        statusCode: 500,
+        statusMessage: 'Internal Server Error',
+        url: '/error'
+      })
     })
 
     it('should render a HTML error page', async () => {
diff --git a/yarn.lock b/yarn.lock
index 8e444efa92..5311c8eebb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2620,7 +2620,7 @@ __metadata:
     magic-string: ^0.26.1
     mlly: ^0.5.1
     murmurhash-es: ^0.1.1
-    nitropack: ^0.2.6
+    nitropack: ^0.2.7
     node-fetch: ^3.2.3
     nuxi: 3.0.0
     nuxt: ^2
@@ -14547,9 +14547,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"nitropack@npm:^0.2.6":
-  version: 0.2.6
-  resolution: "nitropack@npm:0.2.6"
+"nitropack@npm:^0.2.7":
+  version: 0.2.7
+  resolution: "nitropack@npm:0.2.7"
   dependencies:
     "@cloudflare/kv-asset-handler": ^0.2.0
     "@netlify/functions": ^1.0.0
@@ -14603,7 +14603,7 @@ __metadata:
     rollup-plugin-terser: ^7.0.2
     rollup-plugin-visualizer: ^5.6.0
     scule: ^0.2.1
-    semver: ^7.3.6
+    semver: ^7.3.7
     serve-placeholder: ^2.0.1
     serve-static: ^1.15.0
     std-env: ^3.0.1
@@ -14615,7 +14615,7 @@ __metadata:
   bin:
     nitro: dist/cli.mjs
     nitropack: dist/cli.mjs
-  checksum: f932d6f8e648746f9d9b69aa14fe0231a125ffd0a9f8fb3f911d9ed559daa411b9add68a882f6d525c759fd1924edb054e4977628e4727d0160d2849b3503930
+  checksum: 99cf3b20325e3ef27c84ad9d991376fb352bad0bf880741b31534c872067c9d39247b9fe4887c151c3b8e3e0001db6abfdc1be7bde159a1d554c6c4c9747fedd
   languageName: node
   linkType: hard
 
@@ -15296,7 +15296,7 @@ __metadata:
     knitwork: ^0.1.1
     magic-string: ^0.26.1
     mlly: ^0.5.1
-    nitropack: ^0.2.6
+    nitropack: ^0.2.7
     nuxi: 3.0.0
     ohash: ^0.1.0
     ohmyfetch: ^0.4.15