Skip to content

Commit

Permalink
keep query params on proxy (#325)
Browse files Browse the repository at this point in the history
* keep query params on proxy

* apply pr feedback

* updated to use fast-querystring

* apply performace feedback from review

* add in limit for string split
  • Loading branch information
dancastillo authored Oct 22, 2023
1 parent 151c449 commit 330c91e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
24 changes: 21 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { ServerResponse } = require('node:http')
const WebSocket = require('ws')
const { convertUrlToWebSocket } = require('./utils')
const fp = require('fastify-plugin')
const qs = require('fast-querystring')

const httpMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTIONS']
const urlPattern = /^https?:\/\//
Expand Down Expand Up @@ -305,6 +306,20 @@ async function fastifyHttpProxy (fastify, opts) {
wsProxy = setupWebSocketProxy(fastify, opts, rewritePrefix)
}

function extractUrlComponents (urlString) {
const [path, queryString] = urlString.split('?', 2)
const components = {
path,
queryParams: null
}

if (queryString) {
components.queryParams = qs.parse(queryString)
}

return components
}

function handler (request, reply) {
if (request.raw[kWs]) {
reply.hijack()
Expand All @@ -316,11 +331,11 @@ async function fastifyHttpProxy (fastify, opts) {
}
return
}
const queryParamIndex = request.raw.url.indexOf('?')
let dest = request.raw.url.slice(0, queryParamIndex !== -1 ? queryParamIndex : undefined)
const { path, queryParams } = extractUrlComponents(request.url)
let dest = path

if (this.prefix.includes(':')) {
const requestedPathElements = request.url.split('/')
const requestedPathElements = path.split('/')
const prefixPathWithVariables = this.prefix.split('/').map((_, index) => requestedPathElements[index]).join('/')

let rewritePrefixWithVariables = rewritePrefix
Expand All @@ -329,6 +344,9 @@ async function fastifyHttpProxy (fastify, opts) {
}

dest = dest.replace(prefixPathWithVariables, rewritePrefixWithVariables)
if (queryParams) {
dest += `?${qs.stringify(queryParams)}`
}
} else {
dest = dest.replace(this.prefix, rewritePrefix)
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
},
"dependencies": {
"@fastify/reply-from": "^9.0.0",
"fast-querystring": "^1.1.2",
"fastify-plugin": "^4.5.0",
"ws": "^8.4.2"
},
Expand Down
27 changes: 27 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const proxy = require('../')
const got = require('got')
const { Unauthorized } = require('http-errors')
const Transform = require('node:stream').Transform
const qs = require('fast-querystring')

async function run () {
const origin = Fastify()
Expand Down Expand Up @@ -42,6 +43,10 @@ async function run () {
return `this is "variable-api" endpoint with id ${request.params.id}`
})

origin.get('/variable-api/:id/endpoint-with-query', async (request, reply) => {
return `this is "variable-api" endpoint with id ${request.params.id} and query params ${JSON.stringify(request.query)}`
})

origin.get('/timeout', async (request, reply) => {
await new Promise((resolve) => setTimeout(resolve, 600))
return 'this is never received'
Expand Down Expand Up @@ -890,6 +895,28 @@ async function run () {
)
t.equal(resultFooRoute.body, 'Hello World (foo) - lang = en')
})

test('keep the query params on proxy', { only: true }, async t => {
const proxyServer = Fastify()

proxyServer.register(proxy, {
upstream: `http://localhost:${origin.server.address().port}`,
prefix: '/api/:id/endpoint',
rewritePrefix: '/variable-api/:id/endpoint-with-query'
})

await proxyServer.listen({ port: 0 })

t.teardown(() => {
proxyServer.close()
})

const firstProxyPrefix = await got(
`http://localhost:${proxyServer.server.address().port}/api/123/endpoint?foo=bar&foo=baz&abc=qux`
)
const queryParams = JSON.stringify(qs.parse('foo=bar&foo=baz&abc=qux'))
t.equal(firstProxyPrefix.body, `this is "variable-api" endpoint with id 123 and query params ${queryParams}`)
})
}

run()

0 comments on commit 330c91e

Please sign in to comment.