fastify / fastify-http-proxy

Proxy your http requests to another server, with hooks.
MIT License
338 stars 91 forks source link

Unable to use http-proxy for all routes (/*) with @fastify/cors plugin #309

Open kovalenp opened 1 year ago

kovalenp commented 1 year ago

Prerequisites

Fastify version

4.5.3

Plugin version

9.2.1

Node.js version

16.15.1

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

13.4

Description

I need to allow CORS for my Fastify application. To achieve this I'm using @fastify/cors package with following settings:

    fastify.register(cors, {
      origin: '*',
      methods: ['GET', 'POST'],
      allowedHeaders: ['Content-Type', 'Authorization'],
      credentials: true,
    })

if I register the http-proxy route for something like this:

    .register(require('@fastify/http-proxy'), {
      upstream: 'https://some_url',
    })

I will get an error:

/node_modules/find-my-way/index.js:292
      throw new Error(`Method '${method}' already declared for route '${path}' with constraints '${JSON.stringify(constraints)}'`)
            ^
Error: Method 'OPTIONS' already declared for route '/*' with constraints '{}'
    at Router._on (/node_modules/find-my-way/index.js:292:13)
    at Router.on (/node_modules/find-my-way/index.js:136:10)
    at Object.addNewRoute (/node_modules/fastify/lib/route.js:262:16)
    at Object.route (/node_modules/fastify/lib/route.js:194:19)
    at Object._route [as route] (/node_modules/fastify/fastify.js:268:27)
    at fastifyHttpProxy (/node_modules/@fastify/http-proxy/index.js:291:11)
    at Plugin.exec (/node_modules/avvio/plugin.js:130:19)
    at Boot.loadPlugin (/node_modules/avvio/plugin.js:272:10)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

Probably because of this part of the lib:

  fastify.route({
    url: '/*',
    method: opts.httpMethods || httpMethods,
    preHandler,
    config: opts.config || {},
    constraints: opts.constraints || {},
    handler

Steps to Reproduce

Register fastify/cors with fastify/fastify-http-proxy for all routes

    fastify
    .register(cors, {
      origin: '*',
      methods: ['GET', 'POST'],
      allowedHeaders: ['Content-Type', 'Authorization'],
      credentials: true,
    })
    .register(require('@fastify/http-proxy'), {
      upstream: 'https://some_url',
    })

Expected Behavior

There is a way to enable cors on all routes for http-proxy plugin

PS:

I tried something like:

.register(require('@fastify/http-proxy'), {
      upstream: process.env.PUBLIC_API_URL,
      onResponse: (request: FastifyRequest, reply: FastifyReply) => {
        reply.header('Access-Control-Allow-Origin', '*')
        reply.header('Access-Control-Allow-Methods', '*')
        reply.header('Access-Control-Allow-Headers', '*')
      },
    })

but it didn't do the trick for me

mcollina commented 1 year ago

Thanks for reporting! Would you like to send a Pull Request to address this issue? Remember to add unit tests.

amitkTechno commented 9 months ago

hello @kovalenp How did you resolve this issue? Thanks in advance.

kovalenp commented 9 months ago

@amitkTechno I didn't. You can remove /* route (if logic of your app allows to do so) and it will work, alternatively you could set the cors headers yourself

psimk commented 6 months ago

I managed to fix this by adding the prefix option:

await server.register(proxyPlugin, {
  prefix: "/api",
  upstream: "http://localhost:3002",
});

However, this does mean that now your clients will have to access the proxied server over the /api path.