Skip to content

Commit 2f338b9

Browse files
authoredNov 24, 2024··
fix: improve prerendering error debugging (#281)
1 parent 001c345 commit 2f338b9

File tree

1 file changed

+54
-29
lines changed

1 file changed

+54
-29
lines changed
 

‎src/runtime/server/og-image/context.ts

+54-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { H3Error, H3Event } from 'h3'
2+
import type { FetchResponse, FetchOptions } from 'ofetch'
23
import type {
34
OgImageOptions,
45
OgImageRenderEventContext,
@@ -19,6 +20,7 @@ import { decodeObjectHtmlEntities } from '../util/encoding'
1920
import { createNitroRouteRuleMatcher } from '../util/kit'
2021
import { normaliseOptions } from '../util/options'
2122
import { useChromiumRenderer, useSatoriRenderer } from './instances'
23+
import {logger} from "#og-image/server/util/logger";
2224

2325
export function resolvePathCacheKey(e: H3Event, path?: string) {
2426
const siteConfig = e.context.siteConfig.get()
@@ -64,9 +66,9 @@ export async function resolveContext(e: H3Event): Promise<H3Error | OgImageRende
6466
const key = resolvePathCacheKey(e, basePath)
6567
let options: OgImageOptions | null | undefined = queryParams.options as OgImageOptions
6668
if (!options) {
67-
if (import.meta.prerender)
68-
options = await prerenderOptionsCache?.getItem(key)
69-
69+
if (import.meta.prerender) {
70+
options = await prerenderOptionsCache!.getItem(key)
71+
}
7072
if (!options) {
7173
const payload = await fetchPathHtmlAndExtractOptions(e, basePath, key)
7274
if (payload instanceof Error)
@@ -189,6 +191,24 @@ export function extractAndNormaliseOgImageOptions(html: string): OgImageOptions
189191
return payload
190192
}
191193

194+
function handleNon200Response(res: FetchResponse<string>, path: string) {
195+
let errorDescription
196+
// if its a redirect let's get the redirect path
197+
if (res.status >= 300 && res.status < 400) {
198+
errorDescription = `${res.status} redirected to ${res.headers.get('location') || 'unknown'}`
199+
}
200+
else if (res.status >= 400) {
201+
// try get the error message from the response
202+
errorDescription = `${res.status} error: ${res.statusText}`
203+
}
204+
if (errorDescription) {
205+
return createError({
206+
statusCode: 500,
207+
statusMessage: `[Nuxt OG Image] Failed to parse \`${path}\` for og-image extraction. ${errorDescription}`,
208+
})
209+
}
210+
}
211+
192212
// TODO caching
193213
async function fetchPathHtmlAndExtractOptions(e: H3Event, path: string, key: string): Promise<H3Error | OgImageOptions> {
194214
const cachedHtmlPayload = await htmlPayloadCache.getItem(key)
@@ -198,41 +218,46 @@ async function fetchPathHtmlAndExtractOptions(e: H3Event, path: string, key: str
198218
// extract the payload from the original path
199219
let _payload: string | null = null
200220
let html: string
201-
try {
202-
html = await e.$fetch(path, {
203-
// follow redirects
204-
redirect: 'follow',
205-
headers: {
206-
accept: 'text/html',
207-
},
208-
})
209-
_payload = getPayloadFromHtml(html)
210-
// fallback to globalThis.fetch
211-
if (!_payload) {
212-
const fallbackHtml = await globalThis.$fetch(path, {
213-
// follow redirects
214-
redirect: 'follow',
215-
headers: {
216-
accept: 'text/html',
217-
},
218-
})
219-
_payload = getPayloadFromHtml(fallbackHtml)
220-
if (_payload) {
221-
html = fallbackHtml
222-
}
221+
const fetchOptions: FetchOptions = {
222+
// follow redirects
223+
redirect: 'follow',
224+
ignoreResponseError: true,
225+
headers: {
226+
accept: 'text/html',
227+
},
228+
} as const
229+
const htmlRes = await e.fetch(path, fetchOptions)
230+
const err = handleNon200Response(htmlRes, path)
231+
if (err) {
232+
logger.warn(err)
233+
}
234+
html = await htmlRes.text()
235+
_payload = getPayloadFromHtml(html)
236+
// fallback to globalThis.fetch
237+
if (!_payload) {
238+
const fallbackHtmlRes = await globalThis.$fetch.raw(path, fetchOptions)
239+
const err = handleNon200Response(fallbackHtmlRes, path)
240+
if (err) {
241+
return err
242+
}
243+
const fallbackHtml = await fallbackHtmlRes.text()
244+
_payload = getPayloadFromHtml(fallbackHtml)
245+
if (_payload) {
246+
html = fallbackHtml
223247
}
224248
}
225-
catch (err) {
249+
250+
if (!html) {
226251
return createError({
227252
statusCode: 500,
228-
statusMessage: `[Nuxt OG Image] Failed to read the path ${path} for og-image extraction. ${err.message}.`,
253+
statusMessage: `[Nuxt OG Image] Failed to read the path ${path} for og-image extraction, returning no HTML.`,
229254
})
230255
}
231256

232-
if (!_payload || !html) {
257+
if (!_payload) {
233258
return createError({
234259
statusCode: 500,
235-
statusMessage: `[Nuxt OG Image] Got invalid response from ${path} for og-image extraction.`,
260+
statusMessage: `[Nuxt OG Image] HTML response from ${path} is missing the #nuxt-og-image-options script tag. Check you have used defined an og image for this page.`,
236261
})
237262
}
238263

0 commit comments

Comments
 (0)
Please sign in to comment.