reply.fromParameters() drops query params after a second "?"
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript, node.js
- Domain
- backend-api-design
Research direction
The issue identifies extractUrlComponents() and the faulty urlString.split('?', 2) call; locate that function and read the surrounding URL handling. Reproduce with the provided request containing a second ?, then check that the upstream receives both query parameters. Done when the query string is preserved and the relevant tests cover this case.
Written by the indexing model from the issue text.
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Fastify version
5.x
Plugin version
11.6.6
Node.js version
22.x
Description
reply.fromParameters() truncates the query string at the second ?. Everything after it, including later &key=value pairs, is lost.
A literal ? is valid inside a query string (RFC 3986, section 3.4), and it is common in redirect parameters such as ?next=/a?b=1.
The cause is urlString.split('?', 2) in extractUrlComponents(). String.prototype.split with a limit discards the rest of the string instead of keeping it in the last element.
The default handler is not affected, because it removes the query string from the destination and @fastify/reply-from forwards the original one. The problem appears when you use reply.fromParameters() as documented in the README and pass its url to reply.from().
Steps to reproduce
const Fastify = require('fastify')
const proxy = require('@fastify/http-proxy')
const origin = Fastify()
origin.get('/api2/echo', async (request) => request.query)
const server = Fastify()
server.register(proxy, {
upstream: 'http://localhost:3001',
prefix: '/api',
rewritePrefix: '/api2',
preHandler (request, reply, done) {
const { url, options } = reply.fromParameters(request.url, request.params, '/api')
reply.from(url, options)
}
})
await origin.listen({ port: 3001 })
await server.listen({ port: 3000 })
curl 'http://localhost:3000/api/echo?next=/a?b=1&c=2'
Expected behavior
The upstream receives {"next":"/a?b=1","c":"2"}.
The actual response is {"next":"/a"}.
- Dominant language
- JavaScript
- Stars
- 394
- Forks
- 105
- Avg merge
- 9h 34m
- Merged PRs (30d)
- 2
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from fastify/fastify-http-proxy
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
fastify/fastify-http-proxy#493 ·
All issues in fastify/fastify-http-proxy
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
arfct/timezone.fyi#19 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
tensorflow/tfjs#8754 ·
-
bug main ui
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
openhab/openhab-webui#4671 ·
Maintainers usually reply within 1 day
-
scratch-paint's npm test does not run lint, so CI never lints paint; one lint error is currently in developPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
scratchfoundation/scratch-editor#754 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 96/100
google/site-kit-wp#14102 ·
Maintainers usually reply within 2 days