Skip to content

Commit 1ea720b

Browse files
authored
Serve executor.sh's forwarded paths from an unplaced front Worker (#2225)
* Serve executor.sh's forwarded paths from an unplaced front Worker * Test the executor.sh front Worker
1 parent 61b61a1 commit 1ea720b

5 files changed

Lines changed: 313 additions & 0 deletions

File tree

‎.github/workflows/deploy.yml‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ jobs:
106106
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
107107
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
108108

109+
# The unplaced front Worker on the `executor.sh/*` route (src/edge/front.ts).
110+
# After executor-cloud, so each deploy changes the edge's settings in
111+
# executor-cloud before the Worker in front of it.
112+
- name: Deploy executor.sh front Worker
113+
run: bun run wrangler deploy -c wrangler.edge.jsonc
114+
working-directory: apps/cloud
115+
env:
116+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
117+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
118+
109119
# Deploy marker: one event per deploy into the same Axiom dataset the
110120
# worker traces land in, so a latency step-change lines up with its
111121
# deploy in one query. Skipped (not failed) when the secret is absent,

‎apps/cloud/src/edge/front.test.ts‎

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { describe, expect, it } from "@effect/vitest";
2+
3+
import { frontResponse, type FrontEnv } from "./front";
4+
5+
/** A Worker stand-in that records what it receives and answers with `respond`. */
6+
const recordingWorker = (respond: () => Response) => {
7+
const received: Request[] = [];
8+
return {
9+
received,
10+
worker: {
11+
fetch: (request: Request) => {
12+
received.push(request);
13+
return Promise.resolve(respond());
14+
},
15+
},
16+
};
17+
};
18+
19+
const settings = (v2: FrontEnv["V2"], marketing?: FrontEnv["MARKETING"]): FrontEnv => ({
20+
V2: v2,
21+
MARKETING: marketing,
22+
V2_SIGN_UP_URL: "https://app.executor.sh/login?mode=signup",
23+
V2_OAUTH_STATE_PREFIX: "x2.",
24+
V2_ANALYTICS_PROXY_PATH: "/api/0123456789abcdef",
25+
V2_ERROR_TUNNEL_PATH: "/api/fedcba9876543210/submit",
26+
});
27+
28+
const IMMUTABLE = "public, max-age=31536000, immutable";
29+
30+
describe("frontResponse", () => {
31+
it("returns v2's asset with its caching, status and body unchanged, adding only the referrer policy", async () => {
32+
const v2 = recordingWorker(
33+
() =>
34+
new Response("console.log(1)", {
35+
status: 200,
36+
headers: {
37+
"cache-control": IMMUTABLE,
38+
"content-type": "text/javascript",
39+
etag: '"abc"',
40+
},
41+
}),
42+
);
43+
44+
const response = await frontResponse(
45+
new Request("https://executor.sh/_astro/page.abc123.js"),
46+
settings(v2.worker),
47+
);
48+
49+
expect(v2.received.map((request) => request.url)).toEqual([
50+
"https://executor.sh/_astro/page.abc123.js",
51+
]);
52+
expect(response?.status).toBe(200);
53+
expect(response?.headers.get("cache-control")).toBe(IMMUTABLE);
54+
expect(response?.headers.get("content-type")).toBe("text/javascript");
55+
expect(response?.headers.get("etag")).toBe('"abc"');
56+
expect(response?.headers.get("referrer-policy")).toBe("no-referrer");
57+
expect(await response?.text()).toBe("console.log(1)");
58+
});
59+
60+
it("answers v2's redirects itself, as executor-cloud does", async () => {
61+
const v2 = recordingWorker(() => new Response("v2"));
62+
63+
const response = await frontResponse(
64+
new Request("https://executor.sh/sign-up"),
65+
settings(v2.worker),
66+
);
67+
68+
expect(v2.received).toHaveLength(0);
69+
expect(response?.status).toBe(302);
70+
expect(response?.headers.get("location")).toBe("https://app.executor.sh/login?mode=signup");
71+
expect(response?.headers.get("referrer-policy")).toBe("no-referrer");
72+
});
73+
74+
it("sends v1's legal pages to v1's marketing worker", async () => {
75+
const v2 = recordingWorker(() => new Response("v2"));
76+
const marketing = recordingWorker(() => new Response("terms"));
77+
78+
const response = await frontResponse(
79+
new Request("https://executor.sh/terms"),
80+
settings(v2.worker, marketing.worker),
81+
);
82+
83+
expect(v2.received).toHaveLength(0);
84+
expect(marketing.received.map((request) => request.url)).toEqual(["https://executor.sh/terms"]);
85+
expect(await response?.text()).toBe("terms");
86+
expect(response?.headers.get("referrer-policy")).toBe("no-referrer");
87+
});
88+
89+
it("passes on every request executor-cloud serves itself", () => {
90+
const v2 = recordingWorker(() => new Response("v2"));
91+
const marketing = recordingWorker(() => new Response("terms"));
92+
const env = settings(v2.worker, marketing.worker);
93+
94+
for (const request of [
95+
new Request("https://executor.sh/", { headers: { cookie: "wos-session=sealed" } }),
96+
new Request("https://executor.sh/login"),
97+
new Request("https://executor.sh/mcp", { method: "POST" }),
98+
new Request("https://executor.sh/api/auth/callback?code=c&state=s"),
99+
new Request("https://executor.sh/api/oauth/callback?code=c&state=abc"),
100+
new Request("https://executor.sh/acme"),
101+
new Request("https://executor.sh/favicon.ico"),
102+
]) {
103+
expect(frontResponse(request, env), request.url).toBeNull();
104+
}
105+
expect(v2.received).toHaveLength(0);
106+
expect(marketing.received).toHaveLength(0);
107+
});
108+
109+
it("passes everything on when v2's settings are absent", () => {
110+
expect(frontResponse(new Request("https://executor.sh/_astro/page.abc123.js"), {})).toBeNull();
111+
});
112+
});

‎apps/cloud/src/edge/front.ts‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// ---------------------------------------------------------------------------
2+
// The `executor.sh` front Worker (`wrangler.edge.jsonc`, Worker
3+
// `executor-cloud-edge`).
4+
//
5+
// `executor-cloud` is placed near v1's database (`placement.region` in
6+
// wrangler.jsonc), so every request it runs crosses to Virginia first. The
7+
// requests its edge hands to v2 or to v1's marketing worker never use that
8+
// database, yet each paid the trip: a 2 KB `/_astro/*` file took up to 2.6 s.
9+
// This Worker has no placement and runs the same edge decision
10+
// (./marketing.ts) where the request lands, on a zone route
11+
// `executor.sh/*`. A zone route runs before the Worker on the hostname's
12+
// Custom Domain, which Cloudflare treats as the origin, so a request v1 owns
13+
// goes on with `fetch(request)` to `executor-cloud` unchanged: same URL,
14+
// method, headers, cookies, body stream and redirect handling as before.
15+
//
16+
// `executor-cloud` keeps its own copy of the edge, which answers nothing this
17+
// Worker passes on. Deleting this Worker (or its route) returns `executor.sh`
18+
// to exactly that, which is the rollback.
19+
// ---------------------------------------------------------------------------
20+
21+
import { marketingProxyRequest, v2EdgeResponse, type V2EdgeEnv } from "./marketing";
22+
import { withPrivateReferrerPolicy } from "./referrer-policy";
23+
24+
/** The front Worker's bindings and settings (`wrangler.edge.jsonc`). */
25+
export interface FrontEnv extends V2EdgeEnv {
26+
/** v1's marketing worker, which serves v1's legal pages. */
27+
readonly MARKETING?: { readonly fetch: (request: Request) => Promise<Response> };
28+
}
29+
30+
/**
31+
* Answer an `executor.sh` request that v2 or v1's marketing worker owns,
32+
* exactly as `executor-cloud`'s entry does, including its `no-referrer`
33+
* policy. Returns `null` for every request `executor-cloud` serves itself.
34+
*/
35+
export const frontResponse = (request: Request, env: FrontEnv): Promise<Response> | null => {
36+
const v2 = v2EdgeResponse(request, env);
37+
if (v2) return v2.then(withPrivateReferrerPolicy);
38+
const marketingRequest = marketingProxyRequest(request);
39+
if (marketingRequest && env.MARKETING) {
40+
return env.MARKETING.fetch(marketingRequest).then(withPrivateReferrerPolicy);
41+
}
42+
return null;
43+
};
44+
45+
export default {
46+
fetch: (request, env) => frontResponse(request, env) ?? fetch(request),
47+
} satisfies ExportedHandler<FrontEnv>;

‎apps/cloud/src/edge/production-config.test.ts‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { describe, expect, it } from "@effect/vitest";
55
import { Schema } from "effect";
66
import { unstable_readConfig } from "wrangler";
77

8+
import { frontResponse } from "./front";
89
import { parseV2Edge, v2EdgeResponse, type V2EdgeEnv, type V2Service } from "./marketing";
910

1011
// The deployed edge reads its v2 settings from wrangler.jsonc. These tests read
@@ -18,6 +19,23 @@ const config = Schema.decodeUnknownSync(WranglerConfig)(
1819
unstable_readConfig({ config: fileURLToPath(new URL("../../wrangler.jsonc", import.meta.url)) }),
1920
);
2021

22+
// The front Worker (wrangler.edge.jsonc) runs the same edge on executor.sh
23+
// before `executor-cloud`, with its own copy of the settings.
24+
const EdgeWranglerConfig = Schema.Struct({
25+
main: Schema.String,
26+
vars: Schema.Record(Schema.String, Schema.Unknown),
27+
services: Schema.Array(Schema.Struct({ binding: Schema.String, service: Schema.String })),
28+
routes: Schema.Array(
29+
Schema.Struct({ pattern: Schema.String, zone_name: Schema.optional(Schema.String) }),
30+
),
31+
placement: Schema.optional(Schema.Unknown),
32+
});
33+
const edgeConfig = Schema.decodeUnknownSync(EdgeWranglerConfig)(
34+
unstable_readConfig({
35+
config: fileURLToPath(new URL("../../wrangler.edge.jsonc", import.meta.url)),
36+
}),
37+
);
38+
2139
const stringVar = (name: string): string | undefined => {
2240
const value = config.vars[name];
2341
return typeof value === "string" ? value : undefined;
@@ -34,6 +52,20 @@ const shipped: V2EdgeEnv = {
3452
V2_ERROR_TUNNEL_PATH: stringVar("V2_ERROR_TUNNEL_PATH"),
3553
};
3654

55+
const edgeStringVar = (name: string): string | undefined => {
56+
const value = edgeConfig.vars[name];
57+
return typeof value === "string" ? value : undefined;
58+
};
59+
60+
/** The front Worker's shipped settings, with the same stand-in. */
61+
const frontShipped: V2EdgeEnv = {
62+
V2: standIn,
63+
V2_SIGN_UP_URL: edgeStringVar("V2_SIGN_UP_URL"),
64+
V2_OAUTH_STATE_PREFIX: edgeStringVar("V2_OAUTH_STATE_PREFIX"),
65+
V2_ANALYTICS_PROXY_PATH: edgeStringVar("V2_ANALYTICS_PROXY_PATH"),
66+
V2_ERROR_TUNNEL_PATH: edgeStringVar("V2_ERROR_TUNNEL_PATH"),
67+
};
68+
3769
describe("production v2 edge settings", () => {
3870
it("binds V2 to the unplaced marketing gateway", () => {
3971
const bindings = config.services.filter((service) => service.binding === "V2");
@@ -66,6 +98,40 @@ describe("production v2 edge settings", () => {
6698
});
6799
});
68100

101+
describe("the executor.sh front Worker's settings", () => {
102+
it("runs the front entry on a zone route for every executor.sh path", () => {
103+
expect(edgeConfig.main).toMatch(/src\/edge\/front\.ts$/);
104+
expect(edgeConfig.routes).toEqual([{ pattern: "executor.sh/*", zone_name: "executor.sh" }]);
105+
});
106+
107+
// Placement would send every request it answers to the placed region,
108+
// which is the trip this Worker exists to avoid.
109+
it("is not placed", () => {
110+
expect(edgeConfig.placement).toBeUndefined();
111+
});
112+
113+
it("ships the same v2 settings as executor-cloud", () => {
114+
const v2Vars = (vars: Readonly<Record<string, unknown>>) =>
115+
Object.fromEntries(Object.entries(vars).filter(([name]) => name.startsWith("V2_")));
116+
expect(Object.keys(v2Vars(edgeConfig.vars)).toSorted()).toEqual([
117+
"V2_ANALYTICS_PROXY_PATH",
118+
"V2_ERROR_TUNNEL_PATH",
119+
"V2_OAUTH_STATE_PREFIX",
120+
"V2_SIGN_UP_URL",
121+
]);
122+
expect(v2Vars(edgeConfig.vars)).toEqual(v2Vars(config.vars));
123+
});
124+
125+
it("binds the same v2 and marketing Workers as executor-cloud", () => {
126+
const bound = (services: typeof config.services) =>
127+
services
128+
.filter((service) => service.binding === "V2" || service.binding === "MARKETING")
129+
.toSorted((a, b) => a.binding.localeCompare(b.binding));
130+
expect(bound(edgeConfig.services)).toEqual(bound(config.services));
131+
expect(bound(edgeConfig.services)).toHaveLength(2);
132+
});
133+
});
134+
69135
// v2 publishes the exact set of executor.sh requests v1's edge forwards to it.
70136
// `v2-edge-contract.json` is a verbatim copy of v2's edge contract; update it
71137
// only together with v2's contract, never by hand here. Every case runs
@@ -133,6 +199,38 @@ describe("v2's edge contract", () => {
133199
});
134200
}
135201

202+
// The front Worker answers the same requests the same way: everything the
203+
// contract forwards reaches v2 once, and nothing else reaches it.
204+
const runFrontCase = async (method: string, target: string) => {
205+
const calls: Request[] = [];
206+
const v2: V2Service = {
207+
fetch: (request) => {
208+
calls.push(request);
209+
return Promise.resolve(new Response("v2"));
210+
},
211+
};
212+
const request = new Request(`${contract.origin}${target}`, { method });
213+
const response = await frontResponse(request, { ...frontShipped, V2: v2 });
214+
return { request, calls, response };
215+
};
216+
217+
for (const { method, target } of forwarded) {
218+
it(`front Worker forwards ${method} ${target} to v2`, async () => {
219+
const { request, calls, response } = await runFrontCase(method, target);
220+
expect(calls).toHaveLength(1);
221+
expect(calls[0]?.url).toBe(request.url);
222+
expect(calls[0]?.method).toBe(method);
223+
expect(await response?.text()).toBe("v2");
224+
});
225+
}
226+
227+
for (const { method, target } of contract.cases.filter((c) => !c.forwards)) {
228+
it(`front Worker does not forward ${method} ${target} to v2`, async () => {
229+
const { calls } = await runFrontCase(method, target);
230+
expect(calls).toHaveLength(0);
231+
});
232+
}
233+
136234
// Sign-up is not forwarded: the edge redirects it to v2's sign-up page.
137235
it("lists both sign-up paths as not forwarded", () => {
138236
expect(signUps.map((c) => c.target).toSorted()).toEqual(["/sign-up", "/signup"]);

‎apps/cloud/wrangler.edge.jsonc‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"$schema": "node_modules/wrangler/config-schema.json",
3+
// The `executor.sh` front Worker (src/edge/front.ts). It answers the
4+
// requests v1's edge hands to v2 or to v1's marketing worker where they
5+
// land, and passes every other request on to `executor-cloud`, the Worker
6+
// on the `executor.sh` Custom Domain. Deployed after `executor-cloud` by
7+
// .github/workflows/deploy.yml.
8+
"name": "executor-cloud-edge",
9+
"compatibility_date": "2025-04-01",
10+
"main": "src/edge/front.ts",
11+
"workers_dev": false,
12+
"preview_urls": false,
13+
// A zone route runs before the Custom Domain's Worker; see front.ts.
14+
"routes": [
15+
{
16+
"pattern": "executor.sh/*",
17+
"zone_name": "executor.sh",
18+
},
19+
],
20+
// No `placement`, on purpose: this Worker exists to run where the request
21+
// lands. `executor-cloud` stays placed for v1's own requests.
22+
"observability": {
23+
"enabled": true,
24+
"redact_query_string": true,
25+
},
26+
"logpush": true,
27+
// The same Workers and v2 settings as `executor-cloud`'s wrangler.jsonc,
28+
// which keeps its own copy of the edge. src/edge/production-config.test.ts
29+
// fails when the two differ.
30+
"services": [
31+
{
32+
"binding": "MARKETING",
33+
"service": "executor-marketing",
34+
},
35+
{
36+
"binding": "V2",
37+
"service": "executor-next-marketing-v2",
38+
},
39+
],
40+
"vars": {
41+
"V2_SIGN_UP_URL": "https://app.executor.sh/login?mode=signup",
42+
"V2_OAUTH_STATE_PREFIX": "x2.",
43+
"V2_ANALYTICS_PROXY_PATH": "/api/00e2e1f082a6ef17",
44+
"V2_ERROR_TUNNEL_PATH": "/api/fd6fab1fbb4883e1/submit",
45+
},
46+
}

0 commit comments

Comments
 (0)