Skip to content

Commit e3d87ed

Browse files
authored
Added support for parametric rewrite prefix (#294)
1 parent 5723af1 commit e3d87ed

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ server.register(proxy, {
5555
http2: false // optional
5656
})
5757

58+
// /rest-api/123/endpoint will be proxied to http://my-rest-api.example.com/123/endpoint
59+
server.register(proxy, {
60+
upstream: 'http://my-rest-api.example.com',
61+
prefix: '/rest-api/:id/endpoint', // optional
62+
rewritePrefix: '/:id/endpoint', // optional
63+
http2: false // optional
64+
})
65+
5866
// /auth/user will be proxied to http://single-signon.example.com/signon/user
5967
server.register(proxy, {
6068
upstream: 'http://single-signon.example.com',
@@ -118,6 +126,8 @@ An URL (including protocol) that represents the target server to use for proxyin
118126

119127
The prefix to mount this plugin on. All the requests to the current server starting with the given prefix will be proxied to the provided upstream.
120128

129+
Parametric path is supported. To register a parametric path, use the colon before the parameter name.
130+
121131
The prefix will be removed from the URL when forwarding the HTTP
122132
request.
123133

index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,13 @@ async function fastifyHttpProxy (fastify, opts) {
302302
if (this.prefix.includes(':')) {
303303
const requestedPathElements = request.url.split('/')
304304
const prefixPathWithVariables = this.prefix.split('/').map((_, index) => requestedPathElements[index]).join('/')
305-
dest = dest.replace(prefixPathWithVariables, rewritePrefix)
305+
306+
let rewritePrefixWithVariables = rewritePrefix
307+
for (const [name, value] of Object.entries(request.params)) {
308+
rewritePrefixWithVariables = rewritePrefixWithVariables.replace(`:${name}`, value)
309+
}
310+
311+
dest = dest.replace(prefixPathWithVariables, rewritePrefixWithVariables)
306312
} else {
307313
dest = dest.replace(this.prefix, rewritePrefix)
308314
}

test/test.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ async function run () {
3333
return 'this is /api2/a'
3434
})
3535

36+
origin.get('/variable-api/:id/endpoint', async (request, reply) => {
37+
return `this is "variable-api" endpoint with id ${request.params.id}`
38+
})
39+
3640
origin.get('/timeout', async (request, reply) => {
3741
await new Promise((resolve) => setTimeout(resolve, 600))
3842
return 'this is never received'
@@ -453,7 +457,7 @@ async function run () {
453457
t.equal(firstProxyPrefix.body, 'this is /api2/a')
454458
})
455459

456-
test('rewritePrefix with variables', async t => {
460+
test('prefix with variables', async t => {
457461
const proxyServer = Fastify()
458462

459463
proxyServer.register(proxy, {
@@ -474,6 +478,69 @@ async function run () {
474478
t.equal(firstProxyPrefix.body, 'this is /api2/a')
475479
})
476480

481+
test('prefix and rewritePrefix with variables', async t => {
482+
const proxyServer = Fastify()
483+
484+
proxyServer.register(proxy, {
485+
upstream: `http://localhost:${origin.server.address().port}`,
486+
prefix: '/api/:id',
487+
rewritePrefix: '/variable-api/:id'
488+
})
489+
490+
await proxyServer.listen({ port: 0 })
491+
492+
t.teardown(() => {
493+
proxyServer.close()
494+
})
495+
496+
const firstProxyPrefix = await got(
497+
`http://localhost:${proxyServer.server.address().port}/api/123/endpoint`
498+
)
499+
t.equal(firstProxyPrefix.body, 'this is "variable-api" endpoint with id 123')
500+
})
501+
502+
test('prefix (complete path) and rewritePrefix with variables and similar path', async t => {
503+
const proxyServer = Fastify()
504+
505+
proxyServer.register(proxy, {
506+
upstream: `http://localhost:${origin.server.address().port}`,
507+
prefix: '/api/:id/static',
508+
rewritePrefix: '/variable-api/:id/endpoint'
509+
})
510+
511+
await proxyServer.listen({ port: 0 })
512+
513+
t.teardown(() => {
514+
proxyServer.close()
515+
})
516+
517+
const firstProxyPrefix = await got(
518+
`http://localhost:${proxyServer.server.address().port}/api/123/static`
519+
)
520+
t.equal(firstProxyPrefix.body, 'this is "variable-api" endpoint with id 123')
521+
})
522+
523+
test('prefix and rewritePrefix with variables with different paths', async t => {
524+
const proxyServer = Fastify()
525+
526+
proxyServer.register(proxy, {
527+
upstream: `http://localhost:${origin.server.address().port}`,
528+
prefix: '/:id',
529+
rewritePrefix: '/variable-api/:id/endpoint'
530+
})
531+
532+
await proxyServer.listen({ port: 0 })
533+
534+
t.teardown(() => {
535+
proxyServer.close()
536+
})
537+
538+
const firstProxyPrefix = await got(
539+
`http://localhost:${proxyServer.server.address().port}/123`
540+
)
541+
t.equal(firstProxyPrefix.body, 'this is "variable-api" endpoint with id 123')
542+
})
543+
477544
test('rewrite location headers', async t => {
478545
const proxyServer = Fastify()
479546

0 commit comments

Comments
 (0)