nitro icon indicating copy to clipboard operation
nitro copied to clipboard

swr + proxy requests

Open AndersCV opened this issue 1 year ago • 3 comments

Environment


  • Operating System: Linux
  • Node Version: v18.18.0
  • Nuxt Version: 3.9.3
  • CLI Version: 3.10.0
  • Nitro Version: 2.8.1
  • Package Manager: [email protected]
  • Builder: -
  • User Config: devtools, runtimeConfig, routeRules
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/nuxt-starter-51fgbr

Describe the bug

When proxying api requests through Nitro that have caching enabled from routeRules the response object is malformed. In the reproduction i linked I'm using a catch-all endpoint to proxy requests from Nitro to an external backend. With caching enabled the response returned from this endpoint is malformed.

Happens when using the h3 proxyRequest method. Switching to $fetch resolves the issue.

Additional context

No response

Logs

No response

AndersCV avatar Jan 23 '24 09:01 AndersCV

As a workaround: Using $fetch to get the data, then transform + return should still work fine with SWR/caching rules

TheAlexLichter avatar Jan 23 '24 22:01 TheAlexLichter

@manniL Could you provide some additional information on your workaround? We'd also like to implement caching for proxy calls.

We're currently using Nuxt with a custom server route that functions as a proxy for an useFetch requests. Within the custom server route, we return a cachedEventHandler that calls the API.

We'd like to change that to use routeRules with a proxy handler and caching options.

dennisadriaans avatar Apr 29 '24 10:04 dennisadriaans

@dennisadriaans

I came up with this catch-all route to proxy all my requests to external backend:

// server/api/[...].ts

import { joinURL } from 'ufo'

export default defineEventHandler(async (event) => {
  const proxyUrl = useRuntimeConfig().proxyUrl
  const secretKey = useRuntimeConfig().apiToken
  const authHeaderName = useRuntimeConfig().public.AUTH_HEADER_NAME

  const path = event.path.replace(/^\/api\//, '')
  const target = joinURL(proxyUrl, path)
  const method = event.method
  const authHeader = getHeader(event, authHeaderName)

  // readBody inside a GET request returns 405 so we have to check request method
  const body = method !== 'GET' ? await readBody(event) : null

  try {
    return await $fetch(target, {
      method: method,
      body: body,
      headers: {
        'X-TBOOK-TOKEN': secretKey,
        ...(authHeader && { [authHeaderName]: authHeader }),
      },
    })
  } catch (error) {
    throw createError(error as Error)
  }
})

AndersCV avatar Apr 30 '24 07:04 AndersCV