From 65ac76bb2780bad121a40aa16de95f242256156a Mon Sep 17 00:00:00 2001 From: Roberto Bianchi Date: Thu, 19 Mar 2026 18:25:03 +0100 Subject: [PATCH 1/2] fix(qs): preserve fromParameters query params Signed-off-by: Roberto Bianchi --- index.js | 12 +++++++----- test/test.js | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 10375c9..fcc063d 100644 --- a/index.js +++ b/index.js @@ -605,29 +605,31 @@ async function fastifyHttpProxy (fastify, opts) { } dest = dest.replace(prefixPathWithVariables, rewritePrefixWithVariables) - if (queryParams) { - dest += `?${qs.stringify(queryParams)}` - } } else { dest = dest.replace(prefix, rewritePrefix) } + if (queryParams) { + dest += `?${qs.stringify(queryParams)}` + } + return { url: dest || '/', options: replyOpts } } function handler (request, reply) { const { url, options } = fromParameters(request.url, request.params, this.prefix) + const dest = url.split('?')[0] if (request.raw[kWs]) { reply.hijack() try { - wsProxy.handleUpgrade(request, url, noop) + wsProxy.handleUpgrade(request, dest, noop) } /* c8 ignore start */ catch (err) { request.log.warn({ err }, 'websocket proxy error') } /* c8 ignore stop */ return } - reply.from(url, options) + reply.from(dest, options) } fastify.decorateReply('fromParameters', fromParameters) diff --git a/test/test.js b/test/test.js index 30d2829..7996dad 100644 --- a/test/test.js +++ b/test/test.js @@ -38,6 +38,10 @@ async function run () { return 'this is /api2/a' }) + origin.get('/api2/echo-query', async (request) => { + return `query: ${JSON.stringify(request.query)}` + }) + origin.get('/variable-api/:id/endpoint', async (request) => { return `this is "variable-api" endpoint with id ${request.params.id}` }) @@ -900,6 +904,27 @@ async function run () { } }) + test('fromParameters should preserve query params with non-parameterized prefix', async t => { + let fromParametersUrl + const server = Fastify() + server.register(proxy, { + upstream: `http://localhost:${origin.server.address().port}`, + prefix: '/api', + rewritePrefix: '/api2', + preHandler (request, reply, done) { + const { url } = reply.fromParameters(request.url, request.params, '/api') + fromParametersUrl = url + done() + } + }) + + await server.listen({ port: 0 }) + t.after(() => server.close()) + + await fetch(`http://localhost:${server.server.address().port}/api/echo-query?foo=bar&baz=qux`) + t.assert.strictEqual(fromParametersUrl, '/api2/echo-query?foo=bar&baz=qux') + }) + test('preRewrite handler', async t => { const proxyServer = Fastify() From ad38e08388f3a6b490ef2d333901c79ae2e8b7ed Mon Sep 17 00:00:00 2001 From: Roberto Bianchi Date: Thu, 19 Mar 2026 20:08:44 +0100 Subject: [PATCH 2/2] Update index.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gürgün Dayıoğlu Signed-off-by: Roberto Bianchi --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index fcc063d..7be5933 100644 --- a/index.js +++ b/index.js @@ -618,7 +618,7 @@ async function fastifyHttpProxy (fastify, opts) { function handler (request, reply) { const { url, options } = fromParameters(request.url, request.params, this.prefix) - const dest = url.split('?')[0] + const dest = url.split('?', 1)[0] if (request.raw[kWs]) { reply.hijack()