forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
handle-redirects.js
72 lines (59 loc) · 2.43 KB
/
handle-redirects.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import patterns from '../../lib/patterns.js'
import { URL } from 'url'
import languages from '../../lib/languages.js'
export default function handleRedirects(req, res, next) {
// never redirect assets
if (patterns.assetPaths.test(req.path)) return next()
// blanket redirects for languageless homepage
if (req.path === '/') {
let language = 'en'
// if set, redirect to user's preferred language translation or else English
if (
req.context.userLanguage &&
languages[req.context.userLanguage] &&
!languages[req.context.userLanguage].wip
) {
language = req.context.userLanguage
}
res.set('cache-control', 'private, no-store')
return res.redirect(302, `/${language}`)
}
// begin redirect handling
let redirect = req.path
let queryParams = req._parsedUrl.query
// have to do this now because searchPath replacement changes the path as well as the query params
if (queryParams) {
// update old-style query params (#9467)
if ('q' in req.query) {
queryParams = queryParams.replace('q=', 'query=')
}
queryParams = '?' + queryParams
redirect = (redirect + queryParams).replace(patterns.searchPath, '$1')
}
// remove query params temporarily so we can find the path in the redirects object
let redirectWithoutQueryParams = removeQueryParams(redirect)
// look for a redirect in the global object
// for example, given an incoming path /v3/activity/event_types
// find /en/developers/webhooks-and-events/github-event-types
redirectWithoutQueryParams =
req.context.redirects[redirectWithoutQueryParams] || redirectWithoutQueryParams
// add query params back in
redirect = queryParams ? redirectWithoutQueryParams + queryParams : redirectWithoutQueryParams
// do not redirect a path to itself
// req._parsedUrl.path includes query params whereas req.path does not
if (redirect === req._parsedUrl.path) return next()
// do not redirect if the redirected page can't be found
if (!req.context.pages[removeQueryParams(redirect)]) {
// display error on the page in development, but not in production
// include final full redirect path in the message
if (process.env.NODE_ENV !== 'production' && req.context) {
req.context.redirectNotFound = redirect
}
return next()
}
// do the redirect!
return res.redirect(301, redirect)
}
function removeQueryParams(redirect) {
return new URL(redirect, 'https://docs.github.com').pathname
}