| 1 | /** |
| 2 | * The methods only g1t's own services call (`chatInternalClient` in |
| 3 | * @g1t/contracts), at `POST /internal/<method>`: they act as @g1t and take |
| 4 | * no viewer. The site never reaches them: it calls `/rpc/<method>` by name, |
| 5 | * on a person's behalf, and nothing it sends goes to `/internal/`. And |
| 6 | * anything that came in from the internet is refused, should a route ever |
| 7 | * be pointed at this Worker by mistake. |
| 8 | */ |
| 9 | |
| 10 | /** What the service does for these methods (src/index.ts). */ |
| 11 | export type InternalChat = { |
| 12 | internalG1tPost(a: { workspace: string; channel_id: string; body: string }): Promise<unknown>; |
| 13 | internalG1tEdit(a: { workspace: string; channel_id: string; id: string; body: string }): Promise<unknown>; |
| 14 | }; |
| 15 | |
| 16 | /** |
| 17 | * Whether a request came from the internet. Cloudflare names the client of |
| 18 | * every request that reached it from outside; a service binding's request |
| 19 | * carries none of these unless a caller copied them over, which g1t's |
| 20 | * services never do. |
| 21 | */ |
| 22 | export function fromInternet(request: Request): boolean { |
| 23 | return request.headers.has("cf-connecting-ip") || request.headers.has("x-real-ip") || request.headers.has("x-forwarded-for"); |
| 24 | } |
| 25 | |
| 26 | export async function internalAnswer(service: InternalChat, request: Request, method: string): Promise<Response> { |
| 27 | if (fromInternet(request)) return new Response("Forbidden\n", { status: 403 }); |
| 28 | const args = (await request.json().catch(() => ({}))) as any; |
| 29 | switch (method) { |
| 30 | case "g1t_post": |
| 31 | return Response.json(await service.internalG1tPost(args)); |
| 32 | case "g1t_edit": |
| 33 | return Response.json(await service.internalG1tEdit(args)); |
| 34 | default: |
| 35 | return new Response("Unknown method\n", { status: 404 }); |
| 36 | } |
| 37 | } |