Skip to content

Commit

Permalink
LDP-2496: Add handling for 5xx errors in
Browse files Browse the repository at this point in the history
  • Loading branch information
vloss3 committed Apr 22, 2024
1 parent 882dd7e commit ca96ffe
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default defineNuxtModule<ModuleOptions>({
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
addPlugin(resolve(runtimeDir, 'plugin'))
addServerPlugin(resolve(runtimeDir, 'server/plugins/errorHandler'))
addServerPlugin(resolve(runtimeDir, 'server/plugins/errorLogger'))
addImportsDir(resolve(runtimeDir, 'composables/useDrupalCe'))

nuxt.options.runtimeConfig.public.drupalCe = defu(nuxt.options.runtimeConfig.public.drupalCe ?? {}, options)
Expand Down
95 changes: 73 additions & 22 deletions src/runtime/composables/useDrupalCe/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { callWithNuxt } from '#app'
import { defu } from 'defu'
import { appendResponseHeader } from 'h3'
import type { UseFetchOptions } from '#app'
import type { $Fetch, NitroFetchRequest } from 'nitropack'
import { getDrupalBaseUrl, getMenuBaseUrl } from './server'
import { useRuntimeConfig, useState, useFetch, navigateTo, createError, h, resolveComponent, setResponseStatus, useNuxtApp, useRequestHeaders, ref, watch } from '#imports'

Expand All @@ -25,9 +26,72 @@ export const useDrupalCe = () => {
if (config.fetchProxyHeaders) {
fetchOptions.headers = defu(fetchOptions.headers ?? {}, useRequestHeaders(config.fetchProxyHeaders))
}

// If fetchOptions.query._content_format is undefined, use config.addRequestContentFormat.
// If fetchOptions.query._content_format is false, keep that.
fetchOptions.query = fetchOptions.query ?? {}

fetchOptions.query._content_format = fetchOptions.query._content_format ?? config.addRequestContentFormat
if (!fetchOptions.query._content_format) {
// Remove _content_format if set to a falsy value (e.g. fetchOptions.query._content_format was set to false)
delete fetchOptions.query._content_format
}

if (config.addRequestFormat) {
fetchOptions.query._format = 'custom_elements'
}
return fetchOptions
}

/**
* Custom $fetch instance
* @param fetchOptions UseFetchOptions<any>
*/
const $ceApi = (fetchOptions: UseFetchOptions<any> = {}): $Fetch<unknown, NitroFetchRequest> => {
const useFetchOptions = processFetchOptions(fetchOptions)

useFetchOptions.onResponseError = ({ response }) => {
const data = response._data
/**
* Nuxt 5xx fetch errors should be handled as 404 errors, 5xx errors are reserved for Drupal errors.
* Using data.stack to determine if the error is a Nuxt error.
*/
if (data.stack !== undefined && data.statusCode && data.statusCode.toString().startsWith('5')) {
const error = ref({
statusCode: 404,
statusMessage: 'Page not found',
data: data.message
})
return pageErrorHandler(error)
}
}

return $fetch.create({
...useFetchOptions,
})
}

/**
* Fetch data from Drupal ce-API endpoint using $ceApi
* @param path Path of the Drupal ce-API endpoint to fetch
* @param fetchOptions UseFetchOptions<any>
* @param passThroughHeaders Whether to pass through headers from Drupal to the client
*/
const useCeApi = (path: string | Ref<string>, fetchOptions: UseFetchOptions<any> = {}, doPassThroughHeaders?: boolean): Promise<any> => {
const nuxtApp = useNuxtApp()
fetchOptions.onResponse = (context) => {
if (doPassThroughHeaders && config.passThroughHeaders && import.meta.server) {
const headersObject = Object.fromEntries([...context.response.headers.entries()])
passThroughHeaders(nuxtApp, headersObject)
}
}

return useFetch(path, {
...fetchOptions,
$fetch: $ceApi(fetchOptions)
})
}

/**
* Returns the API endpoint with localization (if available)
*/
Expand Down Expand Up @@ -68,25 +132,8 @@ export const useDrupalCe = () => {
title: ''
}))
useFetchOptions.key = `page-${path}`
useFetchOptions = processFetchOptions(useFetchOptions)
useFetchOptions.query = useFetchOptions.query ?? {}

useFetchOptions.onResponse = (context) => {
if (config.passThroughHeaders && import.meta.server) {
const headersObject = Object.fromEntries([...context.response.headers.entries()])
passThroughHeaders(nuxtApp, headersObject)
}
}

if (config.addRequestContentFormat) {
useFetchOptions.query._content_format = config.addRequestContentFormat
}

if (config.addRequestFormat) {
useFetchOptions.query._format = 'custom_elements'
}

const { data: page, error } = await useFetch(path, useFetchOptions)
const { data: page, error } = await useCeApi(path, useFetchOptions, true)

if (page?.value?.redirect) {
await callWithNuxt(nuxtApp, navigateTo, [
Expand Down Expand Up @@ -146,7 +193,7 @@ export const useDrupalCe = () => {
}
}

const { data: menu, error } = await useFetch(menuPath, useFetchOptions)
const { data: menu, error } = await useCeApi(menuPath, useFetchOptions)

if (error.value) {
overrideErrorHandler ? overrideErrorHandler(error) : menuErrorHandler(error)
Expand Down Expand Up @@ -197,6 +244,8 @@ export const useDrupalCe = () => {
}

return {
$ceApi,
useCeApi,
fetchPage,
fetchMenu,
getMessages,
Expand Down Expand Up @@ -229,9 +278,11 @@ const menuErrorHandler = (error: Record<string, any>) => {
})
}

const pageErrorHandler = (error: Record<string, any>, context: Record<string, any>) => {
if (error.value && (!error.value?.data?.content || context.config.customErrorPages)) {
const pageErrorHandler = (error: Record<string, any>, context?: Record<string, any>) => {
if (error.value && (!error.value?.data?.content || context?.config.customErrorPages)) {
throw createError({ statusCode: error.value.statusCode, statusMessage: error.value.message, data: error.value.data, fatal: true })
}
callWithNuxt(context.nuxtApp, setResponseStatus, [error.value.statusCode])
if (context) {
callWithNuxt(context.nuxtApp, setResponseStatus, [error.value.statusCode])
}
}
File renamed without changes.

0 comments on commit ca96ffe

Please sign in to comment.