forked from BetaHuhn/cf-worker-redirect
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from balena-io/handle-path-redirects
Handle path redirects
- Loading branch information
Showing
1 changed file
with
46 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,72 @@ | ||
// eslint-disable-next-line no-undef | ||
declare const REDIRECT_KV: KVNamespace | ||
declare const REDIRECT_KV: KVNamespace; | ||
|
||
export async function handleRequest(request: Request): Promise<Response> { | ||
const url = new URL(request.url) | ||
const path = url.pathname | ||
const fullUrl = url.host + url.pathname | ||
const requestUrl = new URL(request.url); | ||
const requestPath = requestUrl.pathname; | ||
const requestRootPath = `${requestUrl.host}/`; | ||
|
||
// Get the matching target URL by first checking against the full url and then the path | ||
const target = await REDIRECT_KV.get(fullUrl) || await REDIRECT_KV.get(path) | ||
// Get the matching target URL by first checking against the full url then host and then the path | ||
const target = | ||
(await REDIRECT_KV.get(`${requestUrl.host}${requestUrl.pathname}`)) || | ||
(await REDIRECT_KV.get(requestRootPath)) || | ||
(await REDIRECT_KV.get(requestPath)); | ||
|
||
if (!target || target === '404') { | ||
if (!target || target === "404") { | ||
// Optionally redirect to custom page on 404 | ||
const errorRedirect = await REDIRECT_KV.get(`${ url.host }/404`) || await REDIRECT_KV.get('404') | ||
|
||
if (errorRedirect === 'pass') { | ||
const errorRedirect = | ||
(await REDIRECT_KV.get(`${requestUrl.host}/404`)) || | ||
(await REDIRECT_KV.get("404")); | ||
|
||
if (errorRedirect === "pass") { | ||
// Pass the original request along | ||
return fetch(request) | ||
|
||
return fetch(request); | ||
} else if (errorRedirect) { | ||
|
||
// Redirect to the specified error page | ||
return Response.redirect(errorRedirect, 301) | ||
|
||
return Response.redirect(errorRedirect, 301); | ||
} | ||
|
||
// Return normal 404 error | ||
return new Response('Sorry, page not found.', { | ||
return new Response("Sorry, page not found.", { | ||
status: 404, | ||
statusText: 'page not found' | ||
}) | ||
statusText: "page not found", | ||
}); | ||
} | ||
|
||
// Pass the original request along | ||
if (target === 'pass') { | ||
return fetch(request) | ||
if (target === "pass") { | ||
return fetch(request); | ||
} | ||
|
||
/* | ||
Combine source and target URL search parameters (target params overwrite source params) | ||
Note: CF worker does not support url.searchParams.forEach | ||
*/ | ||
const targetUrl = new URL(target) | ||
Array.from(url.searchParams).forEach(([ key, val ]) => { | ||
if (targetUrl.searchParams.has(key) === false) { | ||
targetUrl.searchParams.set(key, val) | ||
} | ||
}) | ||
|
||
const redirectTo = targetUrl.toString() | ||
// Construct URL class from target (value from KV) so we can easily manipulate it | ||
const targetUrl = new URL(target); | ||
// Default to using targetUrl path | ||
let redirectPath = targetUrl.pathname; | ||
// Check if the request has a path though | ||
if (!emptyPath(requestPath) && emptyPath(targetUrl.pathname)) { | ||
// Since request has a path but target does not, use requestPath | ||
redirectPath = requestPath; | ||
} | ||
|
||
// Construct a redirect url using target host and redirect path | ||
const redirectUrl = new URL( | ||
`${targetUrl.protocol}//${targetUrl.host}${redirectPath}` | ||
); | ||
Array.from(requestUrl.searchParams).forEach(([key, val]) => { | ||
if (redirectUrl.searchParams.has(key) === false) { | ||
redirectUrl.searchParams.set(key, val); | ||
} | ||
}); | ||
|
||
// Redirect to the target URL | ||
return Response.redirect(redirectTo, 301) | ||
} | ||
return Response.redirect(redirectUrl, 301); | ||
} | ||
|
||
function emptyPath(path: string): boolean { | ||
return path === "/"; | ||
} |