Skip to content

defineCachedEventHandler serializes Buffer to JSON, breaking binary responses #3831

@onmax

Description

@onmax

TLDR:

Even the docs say:

Because the cached data is serialized to JSON, it is important that the cached function does not return anything that cannot be serialized, such as Symbols, Maps, Sets…

I think there is room for improvement adding serialization/deseralization to cache functions

Environment

  • Nitro version 2: latest (via Nuxt/NuxtHub v0.9.x)
  • Deployment: Cloudflare Workers

Describe the bug

When using defineCachedEventHandler to cache a binary response (like MVT tiles returned as Buffer), Nitro serializes the Buffer to JSON format {"type":"Buffer","data":[...]} when storing in cache.

When the cached response is served, this JSON is returned instead of the raw binary data, breaking clients that expect binary content.

Reproduction

Minimal repro: https://github.com/onmax/nitro-binary-cache-repro (main branch = bug, fix/patch = pnpm patch fix using base64 encoding). the fix is not backwards compatible.

Expected behavior

Binary responses should be properly stored and retrieved from cache, maintaining their binary format.

Possible solutions

  1. Allow serialization/deseralization methods in defineCachedFunction and defineCachedEventHandler
  2. Detect Buffer/binary responses and store as base64, decode on cache hit
  3. Use a binary-safe serialization format for cache storage

Current workaround

Manually encode to base64 before caching and decode on retrieval:

export default defineCachedEventHandler(async (event) => {
  const cached = await useStorage('cache').getItem(`tile:${key}`)
  if (cached) {
    return Buffer.from(cached as string, 'base64')
  }
  
  const mvt = await getTileMvt(...)
  await useStorage('cache').setItem(`tile:${key}`, mvt.toString('base64'))
  return mvt
}, { maxAge: 0 }) // Disable built-in caching, use manual

Discussion

I understand this is by design, but I think having a serialization/deseralization methods could benefit. What do maintainers think?
Feel free to close this issue if it was already discussed!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions