| 1 | // Run after building apps/api. All rate-limit exhaustion is local, never production. |
| 2 | import assert from "node:assert/strict"; |
| 3 | import { readFileSync } from "node:fs"; |
| 4 | import { resolve } from "node:path"; |
| 5 | import { Miniflare, convertV4MiniflareOptions } from "miniflare"; |
| 6 | |
| 7 | const root = resolve("apps/api/build"); |
| 8 | const config = readFileSync("apps/api/wrangler.jsonc", "utf8"); |
| 9 | const services = [...config.matchAll(/"binding":\s*"([^"]+)"\s*,\s*"service"/g)].map((m) => m[1]); |
| 10 | let calls = 0; |
| 11 | const runtime = new Miniflare(convertV4MiniflareOptions({ |
| 12 | name: "api-agent-protocol", cf: false, modulesRoot: root, |
| 13 | modules: [{ type: "ESModule", path: resolve(root, "index.js") }, { type: "CompiledWasm", path: resolve(root, "index_bg.wasm") }], |
| 14 | compatibilityDate: "2026-09-26", |
| 15 | serviceBindings: Object.fromEntries(services.map((name) => [name, async () => { calls++; return Response.json(null); }])), |
| 16 | ratelimits: { |
| 17 | API_ANONYMOUS_LIMIT: { namespace_id: "4401", simple: { limit: 60, period: 60 } }, |
| 18 | API_TOKEN_LIMIT: { namespace_id: "4402", simple: { limit: 1000, period: 60 } }, |
| 19 | }, |
| 20 | })); |
| 21 | try { |
| 22 | const origin = await runtime.ready; |
| 23 | const request = (path, init) => fetch(new URL(path, origin), { ...init, signal: AbortSignal.timeout(15_000) }); |
| 24 | const openapi = await request("/openapi.json"); |
| 25 | assert.equal(openapi.status, 200); |
| 26 | assert.equal(openapi.headers.get("x-g1t-api-version"), "1"); |
| 27 | assert.equal(openapi.headers.get("ratelimit-policy"), '"anonymous";q=60;w=60'); |
| 28 | assert.equal(openapi.headers.get("ratelimit"), null, "no fabricated remaining count"); |
| 29 | const spec = await openapi.json(); |
| 30 | assert.ok(spec.components.securitySchemes.oauth.flows.authorizationCode.scopes["repo:read"]); |
| 31 | assert.equal((await request("/", { headers: { "X-G1t-Api-Version": "1" } })).status, 200); |
| 32 | assert.equal((await request("/v1/")).status, 200); |
| 33 | const before = calls; |
| 34 | assert.equal((await request("/repos/example/test/issues", { method: "POST", headers: { "X-G1t-Api-Version": "unsupported", "content-type": "application/json" }, body: "{}" })).status, 422); |
| 35 | assert.equal(calls, before, "unsupported versions cannot execute a mutation"); |
| 36 | const cors = await request("/repos", { method: "OPTIONS" }); |
| 37 | assert.equal(cors.status, 204); |
| 38 | assert.match(cors.headers.get("access-control-allow-headers"), /x-g1t-api-version/); |
| 39 | assert.match(cors.headers.get("access-control-expose-headers"), /ratelimit-policy/); |
| 40 | let exhausted; |
| 41 | for (let i = 0; i < 65; i++) { |
| 42 | const answer = await request("/"); |
| 43 | await answer.text(); |
| 44 | if (answer.status === 429) { exhausted = answer; break; } |
| 45 | } |
| 46 | assert.ok(exhausted, "local quota must be exhausted"); |
| 47 | assert.equal(exhausted.headers.get("retry-after"), "60"); |
| 48 | assert.equal(exhausted.headers.get("ratelimit"), '"anonymous";r=0;t=60'); |
| 49 | assert.equal(exhausted.headers.get("ratelimit-policy"), '"anonymous";q=60;w=60'); |
| 50 | console.log("API Worker: OpenAPI, version selection, mutation rejection, CORS, policy and actual 429 headers verified."); |
| 51 | } finally { await runtime.dispose(); } |