N
Nuxt3w ago
Felix

Nitro useStorage use Brotli encoded json data

I have a Nuxt server route that should deliver a 400kb Brotli encoded JSON object. The json file is delivered over a custom server api route, because I need to set some custom headers for cache management with etags and set the correct content-type header. How do I read the file correctly and make it fetchable by the user? This is my current code:
export default defineEventHandler(async (event) => {
const metadata = await useStorage<{ hash: string }>('assets:server').getItem(`character-parts-metadata.json`)
if (!metadata)
return new Response('Failed to get metadata', { status: 500 })

const ifNoneMatch = getRequestHeader(event, 'if-none-match')
if (ifNoneMatch === metadata.hash) {
setResponseStatus(event, 304)
return null
}

const characterParts = await useStorage<string>('assets:server').getItem(`character-parts.json.br`)
if (!characterParts)
return new Response('Failed to get character parts', { status: 500 })

setHeaders(event, {
'Content-Type': 'application/json',
'Content-Encoding': 'br',
'ETag': metadata.hash,
'Cache-Control': 'no-cache',
})

return characterParts
})
export default defineEventHandler(async (event) => {
const metadata = await useStorage<{ hash: string }>('assets:server').getItem(`character-parts-metadata.json`)
if (!metadata)
return new Response('Failed to get metadata', { status: 500 })

const ifNoneMatch = getRequestHeader(event, 'if-none-match')
if (ifNoneMatch === metadata.hash) {
setResponseStatus(event, 304)
return null
}

const characterParts = await useStorage<string>('assets:server').getItem(`character-parts.json.br`)
if (!characterParts)
return new Response('Failed to get character parts', { status: 500 })

setHeaders(event, {
'Content-Type': 'application/json',
'Content-Encoding': 'br',
'ETag': metadata.hash,
'Cache-Control': 'no-cache',
})

return characterParts
})
2 Replies
kapa.ai
kapa.ai3w ago
Hi @Felix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your approach to serving the Brotli-encoded JSON file using a custom Nuxt server route is generally correct. However, there are a few adjustments we can make to ensure the file is read and served correctly. Let's go through the code and make some improvements:
export default defineEventHandler(async (event) => {
const metadata = await useStorage<{ hash: string }>('assets:server').getItem(`character-parts-metadata.json`)
if (!metadata)
return new Response('Failed to get metadata', { status: 500 })

const ifNoneMatch = getRequestHeader(event, 'if-none-match')
if (ifNoneMatch === metadata.hash) {
setResponseStatus(event, 304)
return null
}

const characterParts = await useStorage<Buffer>('assets:server').getItemRaw(`character-parts.json.br`)
if (!characterParts)
return new Response('Failed to get character parts', { status: 500 })

setResponseHeaders(event, {
'Content-Type': 'application/json',
'Content-Encoding': 'br',
'ETag': metadata.hash,
'Cache-Control': 'no-cache',
})

return characterParts
})
export default defineEventHandler(async (event) => {
const metadata = await useStorage<{ hash: string }>('assets:server').getItem(`character-parts-metadata.json`)
if (!metadata)
return new Response('Failed to get metadata', { status: 500 })

const ifNoneMatch = getRequestHeader(event, 'if-none-match')
if (ifNoneMatch === metadata.hash) {
setResponseStatus(event, 304)
return null
}

const characterParts = await useStorage<Buffer>('assets:server').getItemRaw(`character-parts.json.br`)
if (!characterParts)
return new Response('Failed to get character parts', { status: 500 })

setResponseHeaders(event, {
'Content-Type': 'application/json',
'Content-Encoding': 'br',
'ETag': metadata.hash,
'Cache-Control': 'no-cache',
})

return characterParts
})
The main changes and explanations are: 1. We use getItemRaw instead of getItem to retrieve the Brotli-encoded file. This is because we want to get the raw buffer data, not a parsed JSON object. According to the unstorage documentation, getItemRaw is used to get the value of a key in storage in raw format.
const characterParts = await useStorage<Buffer>('assets:server').getItemRaw(`character-parts.json.br`)

const characterParts = await useStorage<Buffer>('assets:server').getItemRaw(`character-parts.json.br`)

2. We specify the type of characterParts as Buffer to correctly handle the binary data. 3. We use setResponseHeaders instead of setHeaders to set multiple headers at once. This is based on the h3 documentation. These changes should allow you to correctly read and serve the Brotli-encoded JSON file. The browser will receive the encoded data along with the correct headers, and it will handle the decoding on the client side. Remember that for this to work, the client must support Brotli decompression. Most modern browsers do, but you might want to consider providing a fallback for older browsers if necessary. Unstorage Documentation H3 Documentation ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@278150133932097536> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?