-
-
Save vwall/1ae9a2603d8deac216678b97554eb4b2 to your computer and use it in GitHub Desktop.
Nuxt 3 Server API catch-all w/ caching, retries, and request/response logging (with total elapsed time)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Here's my current implementation of a Nuxt 3 server API catch-all with caching, retries, and request/response logging with total elapsed time: | |
// Place in: /server/api/[...].ts | |
import LRU from 'lru-cache'; | |
import { getCookie } from 'h3'; | |
const config = useRuntimeConfig(); | |
const cache = new LRU({ | |
max: 100, | |
ttl: 1000 * 60 * 60, // One hour | |
}); | |
export default defineEventHandler(async event => { | |
let startTime: number; | |
let duration: number; | |
const abortController = new AbortController(); | |
let timer = null; | |
const method = useMethod(event); | |
const params = useQuery(event); | |
const body = method === 'GET' ? undefined : await useBody(event); | |
const token = getCookie(event, 'auth._token.local'); | |
if (!cache.get(event.req.url)) { | |
const response = $fetch(event.req.url, { | |
baseURL: config.baseUrl, | |
params, | |
method, | |
body, | |
retry: 10, | |
signal: abortController.signal, | |
headers: { | |
Authorization: `${token}`, | |
}, | |
// Log request | |
async onRequest({ request, options }) { | |
timer = setTimeout(() => { | |
abortController.abort(); | |
console.log(`Retrying request to: ${request}`); | |
}, 2500); // Abort request in 2.5s. | |
startTime = new Date().getTime(); | |
options.headers = new Headers(options.headers); | |
options.headers.set('starttime', `${new Date().getTime()}`); | |
await console.log( | |
`%c[${new Date().toLocaleTimeString()}] %cSSR-Request: %c${request}`, | |
'color: gray', | |
'color: orange', | |
'color: white', | |
); | |
}, | |
// Log response | |
async onResponse({ request, response }) { | |
if (timer) { | |
clearTimeout(timer); // clear timer | |
} | |
const currentTime = new Date().getTime(); | |
duration = currentTime - startTime; | |
await console.log( | |
`✔️%cSSR-Response: ${request} - ${response.status} %c(${duration}ms)`, | |
'color: orange', | |
'color: white', | |
); | |
}, | |
// Log error | |
async onResponseError({ error }) { | |
await console.error('%cSSR-Error', error, | |
'color: white; background: red;', | |
); | |
}, | |
}); | |
// Set response to cache | |
cache.set(event.req.url, response); | |
return response; | |
} | |
// Log a cache hit to a given request URL | |
console.log(`%c[SSR] Cache hit: ${event.req.url}`, 'color: orange'); | |
return cache.get(event.req.url); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment