flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/deployments/src/redirect.ts

43 lines1,630 bytesCodeBlame
1/**
2 * What an app's old address answers once its workspace is renamed: every
3 * request is sent, path and query kept, to the same app at its new name.
4 * The old script stays in the dispatch namespace as this tiny Worker for as
5 * long as the workspace holds its old slug (`SLUG_HOLD_DAYS`), then the
6 * sweep removes it.
7 *
8 * Kept free of imports so its tests run on Node as they are.
9 */
10
11/** A hostname under g1t.page: labels of letters, digits and hyphens. */
12const HOST = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
13
14/** Where a request to the old address goes: the same path and query on `targetHost`. */
15export function redirectLocation(requestUrl: string, targetHost: string): string {
16 const url = new URL(requestUrl);
17 return `https://${targetHost}${url.pathname}${url.search}`;
18}
19
20/**
21 * The module Worker that answers every request with a 301 to the same path
22 * and query on `targetHost` (such as `web-acme.g1t.page`). Its logic is
23 * `redirectLocation`'s, spelled out again so the script needs nothing.
24 */
25export function redirectScript(targetHost: string): string {
26 const host = targetHost.toLowerCase();
27 if (!HOST.test(host)) throw new Error(`Not a hostname to redirect to: ${targetHost}`);
28 return `const TARGET = ${JSON.stringify(host)};
29export default {
30 fetch(request) {
31 const url = new URL(request.url);
32 return new Response(null, {
33 status: 301,
34 headers: {
35 location: "https://" + TARGET + url.pathname + url.search,
36 "x-robots-tag": "noindex",
37 "cache-control": "public, max-age=3600",
38 },
39 });
40 },
41};
42`;
43}