Skip to content

Commit 499a26c

Browse files
authored
fix: preserve query string when stripping path prefix (#249)
1 parent 00f73c1 commit 499a26c

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

lib/engine.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ function middie (complete, options = {}) {
6565
holder.res = res
6666
holder.normalizedUrl = normalizePathForMatching(sanitizeUrl(req.url), normalizationOptions)
6767
holder.normalizedReqUrl = normalizePathForMatching(req.url, normalizationOptions)
68+
const sanitized = sanitizeUrl(req.url)
69+
holder.urlSuffix = req.url.slice(sanitized.length)
6870
holder.context = ctx
6971
holder.done()
7072
}
@@ -75,6 +77,7 @@ function middie (complete, options = {}) {
7577
this.res = null
7678
this.normalizedUrl = null
7779
this.normalizedReqUrl = null
80+
this.urlSuffix = null
7881
this.context = null
7982
this.i = 0
8083

@@ -84,6 +87,7 @@ function middie (complete, options = {}) {
8487
const res = that.res
8588
const normalizedUrl = that.normalizedUrl
8689
const normalizedReqUrl = that.normalizedReqUrl
90+
const urlSuffix = that.urlSuffix
8791
const context = that.context
8892
const i = that.i++
8993

@@ -94,6 +98,7 @@ function middie (complete, options = {}) {
9498
that.res = null
9599
that.normalizedUrl = null
96100
that.normalizedReqUrl = null
101+
that.urlSuffix = null
97102
that.context = null
98103
that.i = 0
99104
pool.release(that)
@@ -106,6 +111,7 @@ function middie (complete, options = {}) {
106111
that.res = null
107112
that.normalizedUrl = null
108113
that.normalizedReqUrl = null
114+
that.urlSuffix = null
109115
that.context = null
110116
that.i = 0
111117
pool.release(that)
@@ -120,6 +126,7 @@ function middie (complete, options = {}) {
120126
if (req.url[0] !== '/') {
121127
req.url = '/' + req.url
122128
}
129+
req.url = req.url + urlSuffix
123130
fn(req, res, that.done)
124131
} else {
125132
that.done()

test/req-url-stripping.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,60 @@ test('req.url stripping with all normalization options combined', async (t) => {
143143
await app.inject({ method: 'GET', url: '//secret//data//' })
144144
t.assert.strictEqual(capturedUrl, '/data', '//secret//data// should strip to /data')
145145
})
146+
147+
test('req.url stripping preserves query string', async (t) => {
148+
const app = Fastify()
149+
t.after(() => app.close())
150+
151+
await app.register(middiePlugin)
152+
153+
let capturedUrl = null
154+
155+
app.use('/api', (req, _res, next) => {
156+
capturedUrl = req.url
157+
next()
158+
})
159+
160+
app.get('/api/resource', async () => ({ ok: true }))
161+
162+
capturedUrl = null
163+
await app.inject({ method: 'GET', url: '/api/resource?foo=bar' })
164+
t.assert.strictEqual(capturedUrl, '/resource?foo=bar', 'single query param preserved')
165+
166+
capturedUrl = null
167+
await app.inject({ method: 'GET', url: '/api/resource?foo=bar&baz=qux' })
168+
t.assert.strictEqual(capturedUrl, '/resource?foo=bar&baz=qux', 'multiple query params preserved')
169+
170+
capturedUrl = null
171+
await app.inject({ method: 'GET', url: '/api/resource?a=1&b=2&c=3' })
172+
t.assert.strictEqual(capturedUrl, '/resource?a=1&b=2&c=3', 'many query params preserved')
173+
})
174+
175+
test('req.url stripping preserves query string with normalization options', async (t) => {
176+
const app = Fastify({
177+
routerOptions: {
178+
ignoreDuplicateSlashes: true,
179+
ignoreTrailingSlash: true
180+
}
181+
})
182+
t.after(() => app.close())
183+
184+
await app.register(middiePlugin)
185+
186+
let capturedUrl = null
187+
188+
app.use('/secret', (req, _res, next) => {
189+
capturedUrl = req.url
190+
next()
191+
})
192+
193+
app.get('/secret/data', async () => ({ ok: true }))
194+
195+
capturedUrl = null
196+
await app.inject({ method: 'GET', url: '//secret/data?key=value' })
197+
t.assert.strictEqual(capturedUrl, '/data?key=value', '//secret/data?key=value preserves query string')
198+
199+
capturedUrl = null
200+
await app.inject({ method: 'GET', url: '/secret//data/?key=value' })
201+
t.assert.strictEqual(capturedUrl, '/data?key=value', '/secret//data/?key=value preserves query string')
202+
})

0 commit comments

Comments
 (0)