Prerequisites
Issue
Use case
I'm building a proxy that strips certain authentication-related query params (e.g. token, workspaceId) before forwarding to the upstream. When those are the only params, the result is an empty query string, and the upstream receives a trailing ?.
app.get('/proxy/*', (request, reply) => {
return reply.from('http://upstream/path', {
queryString: (search, reqUrl) => {
const params = new URLSearchParams(search);
params.delete('token');
params.delete('workspaceId');
return params.toString();
},
});
});
Problem
The getQueryString function always prepends ? to the result of the queryString option, both for the function form and the object form, even when the result is an empty string:
function getQueryString (search, reqUrl, opts, request) {
if (typeof opts.queryString === 'function') {
return '?' + opts.queryString(search, reqUrl, request)
}
if (opts.queryString) {
return '?' + querystring.stringify(opts.queryString)
}
if (search.length > 0) {
return search
}
const queryIndex = reqUrl.indexOf('?')
if (queryIndex > 0) {
return reqUrl.slice(queryIndex)
}
return ''
}
This means there's no way to signal "no query string". Returning '' from the function (or passing an empty object {}) produces a trailing ? on the upstream request path (e.g., a request to /proxy/items?token=secret results in the upstream receiving /path? instead of /path).
By contrast, the default code path (no queryString option) correctly returns '' when there's no query string to forward.
Expected behavior
When the queryString result is an empty/falsy string, no ? should be appended, matching the behavior of the default code path.
Suggested fix
if (typeof opts.queryString === 'function') {
const qs = opts.queryString(search, reqUrl, request)
return qs ? '?' + qs : ''
}
if (opts.queryString) {
const qs = querystring.stringify(opts.queryString)
return qs ? '?' + qs : ''
}
Environment
@fastify/reply-from: 12.6.0
- Node.js: 24.x
Prerequisites
Issue
Use case
I'm building a proxy that strips certain authentication-related query params (e.g.
token,workspaceId) before forwarding to the upstream. When those are the only params, the result is an empty query string, and the upstream receives a trailing?.Problem
The
getQueryStringfunction always prepends?to the result of thequeryStringoption, both for the function form and the object form, even when the result is an empty string:This means there's no way to signal "no query string". Returning
''from the function (or passing an empty object{}) produces a trailing?on the upstream request path (e.g., a request to/proxy/items?token=secretresults in the upstream receiving/path?instead of/path).By contrast, the default code path (no
queryStringoption) correctly returns''when there's no query string to forward.Expected behavior
When the
queryStringresult is an empty/falsy string, no?should be appended, matching the behavior of the default code path.Suggested fix
Environment
@fastify/reply-from: 12.6.0