fastify-http-proxy
fastify-http-proxy copied to clipboard
Unable to use http-proxy for all routes (/*) with @fastify/cors plugin
Prerequisites
- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the bug has not already been reported
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
Thanks for reporting! Would you like to send a Pull Request to address this issue? Remember to add unit tests.
hello @kovalenp How did you resolve this issue? Thanks in advance.
@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
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.
This is still an issue.
I just tried to create a Fastify web server in this fashion:
const app = Fastify({
logger: true
});
// API routes
app.get('/api/stats', recordStats);
// CORS for API routes
await app.register(cors, {
prefix: '/api',
origin: '*'
});
app.register(proxy, {
upstream: 'http://localhost:3000', // remix server
prefix: '/',
rewritePrefix: '/',
http2: false
});
// Run the server!
await app.listen({ port: 3001 });
And it fails with the same error:
/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/find-my-way/index.js:291
throw new Error(`Method '${method}' already declared for route '${pattern}' with constraints '${JSON.stringify(constraints)}'`)
^
Error: Method 'OPTIONS' already declared for route '/*' with constraints '{}'
at Router._on (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/find-my-way/index.js:291:13)
at Router.on (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/find-my-way/index.js:139:10)
at Object.addNewRoute (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/fastify/lib/route.js:335:16)
at Object.route (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/fastify/lib/route.js:244:19)
at Object._route [as route] (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/fastify/fastify.js:286:27)
at fastifyHttpProxy (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/@fastify/http-proxy/index.js:282:11)
at Plugin.exec (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/avvio/lib/plugin.js:125:28)
at Boot._loadPlugin (/Users/bhouston/Coding/Personal/web3dsurvey/node_modules/avvio/boot.js:432:10)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
This is pretty basic stuff and it concerns me it doesn't work with Fastify.
BTW I got around it by writing my own cors responder, rather than using @fastify/cors.
api
Do you mind sharing your solution?
I got around this by adding this to the proxy options:
// skips OPTIONS
httpMethods: ["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH"] as HTTPMethods[],