Skip to content

Commit a589952

Browse files
committed
add ability for redirects to preserve the querystring and hash
when the requested URL is redirected, as the result of: config.redirects preserve the querystring and hash, conditional to: config.redirects[index].preserveQuery config.redirects[index].preserveHash when the requested URL is redirected, as the result of either: config.cleanUrls config.trailingSlash preserve the querystring and hash, without condition based on: * upstream PR 154 vercel/serve-handler#154 * upstream PR 144 vercel/serve-handler#144
1 parent e54b28e commit a589952

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

lib/serve-handler/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ In the example above, `/old-docs/12` would be forwarded to `/new-docs/12` with s
168168

169169
**NOTE:** The paths can contain globs (matched using [minimatch](https://github.com/isaacs/minimatch)) or regular expressions (match using [path-to-regexp](https://github.com/pillarjs/path-to-regexp)).
170170

171+
By default, the querystring and hash are not preserved by the redirect. The following boolean attributes enable this behavior:
172+
173+
```json
174+
{
175+
"redirects": [
176+
{ "source": "/from?foo=bar#baz", "destination": "/to", "preserveQuery": true, "preserveHash": true }
177+
]
178+
}
179+
```
180+
171181
### headers (Array)
172182

173183
Allows you to set custom headers (and overwrite the default ones) for certain paths:

lib/serve-handler/src/index.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ const shouldRedirect = (decodedPath, {redirects = [], trailingSlash}, cleanUrl)
139139
}
140140
return {
141141
target: ensureSlashStart(decodedPath),
142-
statusCode: defaultType
142+
statusCode: defaultType,
143+
preserveQuery: true,
144+
preserveHash: true
143145
}
144146
}
145147

@@ -164,21 +166,25 @@ const shouldRedirect = (decodedPath, {redirects = [], trailingSlash}, cleanUrl)
164166
if (target) {
165167
return {
166168
target: ensureSlashStart(target),
167-
statusCode: defaultType
169+
statusCode: defaultType,
170+
preserveQuery: true,
171+
preserveHash: true
168172
}
169173
}
170174
}
171175

172176
// This is currently the fastest way to
173177
// iterate over an array
174178
for (let index = 0; index < redirects.length; index++) {
175-
const {source, destination, type} = redirects[index]
179+
const {source, destination, type, preserveQuery, preserveHash} = redirects[index]
176180
const target = toTarget(source, destination, decodedPath)
177181

178182
if (target) {
179183
return {
180184
target,
181-
statusCode: type || defaultType
185+
statusCode: type || defaultType,
186+
preserveQuery: !!preserveQuery,
187+
preserveHash: !!preserveHash
182188
}
183189
}
184190
}
@@ -763,8 +769,18 @@ module.exports = async (request, response, config = {}, methods = {}) => {
763769
}
764770

765771
if (paths.redirect) {
772+
// conditionally preserve search and hash
773+
let req_url, req_search, req_hash
774+
775+
if (paths.redirect.preserveQuery || paths.redirect.preserveHash) {
776+
req_url = url.parse(request.url)
777+
}
778+
779+
req_search = (paths.redirect.preserveQuery && req_url.search) ? req_url.search : ''
780+
req_hash = (paths.redirect.preserveHash && req_url.hash) ? req_url.hash : ''
781+
766782
response.writeHead(paths.redirect.statusCode, {
767-
Location: encodeURI(paths.redirect.target)
783+
Location: encodeURI(paths.redirect.target + req_search + req_hash)
768784
})
769785

770786
response.end()

0 commit comments

Comments
 (0)