pr_01m47d15m3e54sn21z27rpy5n9/services/deployments/src/redirect.test.ts

40 lines1,874 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { redirectLocation, redirectScript } from "./redirect.ts";
5
6/** The generated Worker, loaded as the dispatch namespace would run it. */
7async function load(source: string): Promise<{ fetch(request: Request): Response | Promise<Response> }> {
8 const module = await import(`data:text/javascript,${encodeURIComponent(source)}`);
9 return module.default;
10}
11
12test("the location keeps the path and query, on the new host", () => {
13 assert.equal(redirectLocation("https://web-acme.g1t.page/", "web-zenith.g1t.page"), "https://web-zenith.g1t.page/");
14 assert.equal(
15 redirectLocation("https://web-git-fix-acme.g1t.page/docs/a%20b?x=1&y=2#top", "web-git-fix-zenith.g1t.page"),
16 "https://web-git-fix-zenith.g1t.page/docs/a%20b?x=1&y=2",
17 );
18});
19
20test("the script answers every request with a 301 to the same place", async () => {
21 const worker = await load(redirectScript("web-zenith.g1t.page"));
22 for (const [from, method] of [
23 ["https://web-acme.g1t.page/", "GET"],
24 ["https://web-acme.g1t.page/api/items?page=2", "POST"],
25 ["https://web-acme.g1t.page/a/b/", "HEAD"],
26 ] as const) {
27 const response = await worker.fetch(new Request(from, { method }));
28 assert.equal(response.status, 301);
29 assert.equal(response.headers.get("location"), redirectLocation(from, "web-zenith.g1t.page"));
30 assert.equal(response.headers.get("x-robots-tag"), "noindex");
31 assert.match(response.headers.get("cache-control") ?? "", /max-age=\d+/);
32 }
33});
34
35test("the target is lowercased and must be a hostname", () => {
36 assert.match(redirectScript("Web-Zenith.g1t.page"), /"web-zenith\.g1t\.page"/);
37 assert.throws(() => redirectScript("evil.example/\"; alert(1); \""));
38 assert.throws(() => redirectScript("no-dots"));
39 assert.throws(() => redirectScript("-bad.g1t.page"));
40});