Skip to content

Commit 37f536a

Browse files
alexieremiafago
andauthored
improve: LDP-2496: Add server error handling (#225)
* improve: custom-fetch-instance: Add helper and include query in server routes * improve: LDP-2496: Add server error logging * custom-fetch-instance: Add useCeApi helper * custom-fetch-instance: Improve code * custom-fetch-instance: Add dist * custom-fetch-instance: Remove query and add dist * LDP-2496: Add handling for 5xx errors in * LDP-2496: Improve code and add dist * LDP-2496: Rename to serverLogLevel and remove 5xx handling * LDP-2496: Add dist * LDP-2496: Update message * LDP-2496: Improve error status * LDP-2496: Add special case for fetch failed * try fix error handling * LDP-2496: Move error handling to pageErrorHandler * LDP-2496: Fix tests * LDP-2496: Remove dist --------- Co-authored-by: Wolfgang Ziegler <[email protected]>
1 parent 5f7b885 commit 37f536a

File tree

4 files changed

+56
-6
lines changed

4 files changed

+56
-6
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ is added automatically to requests. Defaults to `false`.
9797

9898
- `passThroughHeaders`: Response headers to pass through from Drupal to the client. Defaults to ['cache-control', 'content-language', 'set-cookie', 'x-drupal-cache', 'x-drupal-dynamic-cache']. Note: This is only available in SSR mode.
9999

100+
- `serverLogLevel`: The log level to use for server-side logging. Defaults to 'info'. Options:
101+
- false: The server plugin will not be loaded, keeps the default Nuxt error logging.
102+
- 'info': Log all server requests and errors.
103+
- 'error': Log only errors.
104+
100105
## Overriding options with environment variables
101106

102107
Runtime config values can be overridden with environment variables via `NUXT_PUBLIC_` prefix. Supported runtime overrides:

src/module.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { fileURLToPath } from 'url'
2-
import { defineNuxtModule, addPlugin, createResolver, addImportsDir, addServerHandler, addServerImports, addImports } from '@nuxt/kit'
2+
import { defineNuxtModule, addPlugin, addServerPlugin, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit'
33
import { defu } from 'defu'
44
import type { NuxtOptionsWithDrupalCe } from './types'
55

@@ -18,6 +18,7 @@ export interface ModuleOptions {
1818
serverApiProxy: boolean,
1919
passThroughHeaders?: string[],
2020
exposeAPIRouteRules?: boolean,
21+
serverLogLevel?: boolean | 'info' | 'error',
2122
}
2223

2324
export default defineNuxtModule<ModuleOptions>({
@@ -41,6 +42,7 @@ export default defineNuxtModule<ModuleOptions>({
4142
addRequestFormat: false,
4243
serverApiProxy: true,
4344
passThroughHeaders: ['cache-control', 'content-language', 'set-cookie', 'x-drupal-cache', 'x-drupal-dynamic-cache'],
45+
serverLogLevel: 'info'
4446
},
4547
setup (options, nuxt) {
4648
const nuxtOptions = nuxt.options as NuxtOptionsWithDrupalCe
@@ -58,6 +60,9 @@ export default defineNuxtModule<ModuleOptions>({
5860
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
5961
nuxt.options.build.transpile.push(runtimeDir)
6062
addPlugin(resolve(runtimeDir, 'plugin'))
63+
if (options.serverLogLevel) {
64+
addServerPlugin(resolve(runtimeDir, 'server/plugins/errorLogger'))
65+
}
6166
addImportsDir(resolve(runtimeDir, 'composables/useDrupalCe'))
6267

6368
nuxt.options.runtimeConfig.public.drupalCe = defu(nuxt.options.runtimeConfig.public.drupalCe ?? {}, options)

src/runtime/composables/useDrupalCe/index.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const useDrupalCe = () => {
5151
const useFetchOptions = processFetchOptions(fetchOptions)
5252

5353
return $fetch.create({
54-
...useFetchOptions
54+
...useFetchOptions,
5555
})
5656
}
5757

@@ -262,9 +262,27 @@ const menuErrorHandler = (error: Record<string, any>) => {
262262
})
263263
}
264264

265-
const pageErrorHandler = (error: Record<string, any>, context: Record<string, any>) => {
266-
if (error.value && (!error.value?.data?.content || context.config.customErrorPages)) {
267-
throw createError({ statusCode: error.value.statusCode, statusMessage: error.value.message, data: error.value.data, fatal: true })
265+
const pageErrorHandler = (error: Record<string, any>, context?: Record<string, any>) => {
266+
const errorData = error.value.data
267+
if (error.value && (!errorData?.content || context?.config.customErrorPages)) {
268+
// At the moment, Nuxt API proxy does not provide a nice error when the backend is not reachable. Handle it better.
269+
// See https://github.com/nuxt/nuxt/issues/22645
270+
if (error.value.statusCode === 500 && errorData.message === 'fetch failed' && !errorData.statusMessage) {
271+
throw createError({
272+
statusCode: 503,
273+
statusMessage: 'Unable to reach backend.',
274+
data: errorData,
275+
fatal: true
276+
})
277+
}
278+
throw createError({
279+
statusCode: error.value.statusCode,
280+
statusMessage: error.value.message,
281+
data: error.value.data,
282+
fatal: true
283+
})
284+
}
285+
if (context) {
286+
callWithNuxt(context.nuxtApp, setResponseStatus, [error.value.statusCode])
268287
}
269-
callWithNuxt(context.nuxtApp, setResponseStatus, [error.value.statusCode])
270288
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { getRequestURL } from 'h3'
2+
import { useRuntimeConfig, defineNitroPlugin } from '#imports'
3+
4+
export default defineNitroPlugin((nitro: any) => {
5+
const { ceApiEndpoint, serverLogLevel } = useRuntimeConfig().public.drupalCe
6+
7+
if (serverLogLevel === 'error' || serverLogLevel === 'info') {
8+
nitro.hooks.hook('error', (error: any, { event }: any) => {
9+
const url = getRequestURL(event)
10+
const fullUrl = url.origin + url.pathname + url.search
11+
console.error(`[${event?.node.req.method}] ${fullUrl} - ${error}`)
12+
})
13+
}
14+
15+
// Log every request when serverLogLevel is set to info.
16+
if (serverLogLevel === 'info') {
17+
nitro.hooks.hook('request', (event: any) => {
18+
const origin = getRequestURL(event).origin
19+
console.log(`[${event.node.req.method}] ${origin + event.node.req.url}`)
20+
})
21+
}
22+
})

0 commit comments

Comments
 (0)