{
  "id": "build-a-cloudflare-worker-api-proxy",
  "type": "prompts",
  "category": "prompts",
  "locale": "pt",
  "url": "/pt/prompts/build-a-cloudflare-worker-api-proxy",
  "title": "Prompt para Construir um Proxy de API do Cloudflare Worker",
  "description": "Prompt copiável de IA para construir um Cloudflare Worker que faz proxy e limita taxa de chamadas de API externas, adiciona cabeçalhos de autenticação e armazena respostas em cache.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Cloudflare",
    "TypeScript"
  ],
  "tags": [
    "cloudflare",
    "typescript",
    "security",
    "deploy"
  ],
  "difficulty": "medium",
  "updated": "2026-06-08",
  "markdown": "Use este prompt para criar um Cloudflare Worker que atua como intermediário para uma API externa, injeta cabeçalhos de autenticação, limita taxa por IP usando Workers KV e armazena respostas em cache — para que os clientes nunca vejam sua chave de API upstream.\n\n## Prompt Principal\n\n```txt title=\"Main Prompt\"\nYou are building a Cloudflare Worker using TypeScript and the Workers runtime (not Node.js).\nThe Worker will proxy requests to an upstream API (e.g., OpenAI at https://api.openai.com).\n\nTask: create a production-ready API proxy Worker.\n\nRequirements:\n- Use `wrangler` v3 for local dev. Scaffold with `bun create cloudflare@latest` and choose\n  \"Hello World\" Worker with TypeScript.\n- Upstream URL: read from a Wrangler secret `UPSTREAM_URL` (string).\n- Auth: inject `Authorization: Bearer ${env.UPSTREAM_API_KEY}` on every proxied request,\n  where `UPSTREAM_API_KEY` is a Wrangler secret. Never expose this header to the client.\n- CORS: allow only origins in `env.ALLOWED_ORIGINS` (comma-separated string secret).\n  Return a `403` for disallowed origins. Handle preflight OPTIONS requests.\n- Rate limiting: use Workers KV binding `RATE_LIMIT_KV`.\n  - Key: `rl:${ip}` where ip is `request.headers.get('CF-Connecting-IP')`.\n  - Value: request count for the current UTC minute (TTL = 60 s).\n  - Limit: 60 requests/minute per IP. Return `429` with `Retry-After: 60` if exceeded.\n- Caching: for GET requests, check `caches.default` before proxying upstream. Cache\n  successful responses with `Cache-Control: public, max-age=300`.\n- Strip the following headers from the upstream response before returning to the client:\n  `x-powered-by`, `server`, `cf-ray`.\n- Wrangler config: declare the KV namespace binding and all secrets in `wrangler.toml`.\n- Do NOT use Node.js APIs (`fs`, `path`, `Buffer`) — Workers runtime only.\n\nStop and list all planned files before writing code.\n```\n\n## Notas de Implementação\n\n- Cloudflare Workers recebem um `Request` e retornam um `Response` — evite padrões no estilo `express`.\n- `caches.default` é o cache de borda do Cloudflare; funciona apenas em produção. Use `MINIFLARE_CACHE` para testes de desenvolvimento local ou simule o cache.\n- `CF-Connecting-IP` é injetado pelo Cloudflare — não é falsificável da internet pública, mas teste localmente com um IP fallback fixo.\n- Segredos do Wrangler são definidos com `wrangler secret put UPSTREAM_API_KEY` — nunca os armazene em `wrangler.toml` ou arquivos `.env` commitados.\n\n## Alterações de Arquivo Esperadas\n\n```txt\nwrangler.toml                  (new)\nsrc/index.ts                   (new — Worker entrypoint)\nsrc/cors.ts                    (new — CORS helper)\nsrc/rate-limit.ts              (new — KV rate limiter)\npackage.json                   (new)\ntsconfig.json                  (new)\n.dev.vars                      (new — local dev secrets, gitignored)\n.gitignore                     (edited — add .dev.vars)\n```\n\n## Critérios de Aceitação\n\n- `wrangler dev` inicia sem erros e faz proxy de um `GET /` para a URL upstream.\n- Um IP que envia 61 requisições em um minuto recebe um `429` na 61ª requisição.\n- Uma requisição de uma origem não permitida recebe um `403`.\n- O cabeçalho `Authorization` não aparece na resposta ou em qualquer cabeçalho visível ao cliente.\n- `wrangler deploy` é bem-sucedido e o Worker está ativo em `workers.dev`.\n\n## Comandos de Teste\n\n```bash\nwrangler dev &\n# test normal proxy\ncurl http://localhost:8787/ -H \"Origin: https://myapp.com\"\n# test CORS rejection\ncurl http://localhost:8787/ -H \"Origin: https://evil.com\"\n# test rate limit (requires 61 rapid requests)\nfor i in $(seq 1 62); do curl -s -o /dev/null -w \"%{http_code}\\n\" http://localhost:8787/; done\n```\n\n## Erros Comuns de IA\n\n- Usar `process.env` em vez do parâmetro `env` passado para o manipulador `fetch` do Worker.\n- Esquecer de lidar com requisições preflight `OPTIONS`, quebrando o CORS para chamadas POST/PUT.\n- Armazenar `UPSTREAM_API_KEY` em `wrangler.toml` como uma variável simples em vez de um segredo.\n- Usar `node:buffer` ou outros built-ins do Node.js, que não estão disponíveis no runtime do Workers.\n\n## Prompt de Correção\n\n```txt title=\"Fix Prompt\"\nThe Worker fails with a runtime error or leaks the API key. Fix in order:\n1. Replace `process.env.X` with `env.X` everywhere — Workers use the `env` handler parameter.\n2. Add an OPTIONS handler before the proxy logic that returns the CORS headers with a 204 status.\n3. Move `UPSTREAM_API_KEY` from `wrangler.toml` [vars] to a secret: `wrangler secret put UPSTREAM_API_KEY`.\nShow only the corrected diff.\n```"
}