forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClientSideRedirectExceptions.tsx
68 lines (61 loc) · 2.54 KB
/
ClientSideRedirectExceptions.tsx
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
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// We recently moved several rest api operations around
// in the docs. That means that we are out of sync with
// the urls defined in the OpenAPI. We will eventually
// update those urls but for now we want to ensure that
// we have client-side redirects in place for any urls
// in the product that link to the rest docs (e.g., error
// code urls from the apis).
// The client-side redirects can consist of operation urls
// being redirected to the new operation url or headings
// on a page that need to be redirected to the new page (e.g.,
// /rest/reference/repos#statuses to
// /rest/reference/commits#commit-statuses)
export default function ClientSideRedirectExceptions() {
const router = useRouter()
useEffect(() => {
// Because we have an async call to fetch, it's possible that this
// component unmounts before we perform the redirect, however, React
// will still try to perform the redirect even after the component
// is unmounted. To prevent this, we can use the AbortController signal
// to abort the Web request when the component unmounts.
const controller = new AbortController()
const signal = controller.signal
const { hash, pathname } = window.location
// path without a version or language
const barePath = pathname
.replace(`/${router.locale}`, '')
.replace(`/${router.query.versionId || ''}`, '')
async function getRedirect() {
try {
const sp = new URLSearchParams()
sp.set('path', barePath)
sp.set('hash', hash.replace(/^#/, ''))
// call the anchor-redirect endpoint to get the redirect url
const response = await fetch(`/anchor-redirect?${sp.toString()}`, {
signal,
})
// the response status will always be 200 unless there
// was a problem with the fetch request. When the
// redirect doesn't exist the json response will be empty
if (response.ok) {
const { to } = await response.json()
if (to) {
// we want to redirect with the language and version in tact
// so we'll replace the full url's path and hash
const fromUrl = pathname + hash
const bareUrl = barePath + hash
const toUrl = fromUrl.replace(bareUrl, to)
router.replace(toUrl)
}
}
} catch (error) {
console.warn('Unable to fetch client-side redirect:', error)
}
}
getRedirect()
return () => controller.abort()
}, [])
return null
}