Engenharia reversa de um projeto Cloudflare: por onde começar
Assumi um projeto que já rodava no Cloudflare e precisei mapear a arquitetura. Comecei errado — lendo código — e aprendi que o wrangler.toml é a planta baixa.
O problema
Assumi um projeto que já rodava no Cloudflare: um simulador de notas de concursos com frontend (a interface visual que o usuário vê) e backend (o motor que processa os dados por trás dos panos). Não fui eu quem construí. A primeira pergunta que qualquer pessoa desenvolvedora se faz numa situação dessas é: por onde eu começo a entender como isso foi desenhado?
No desenvolvimento em Node.js tradicional (uma ferramenta muito usada para criar servidores), você procura o arquivo principal como o app.js, olha as rotas do Express (que direcionam o tráfego da aplicação) e segue o caminho das peças. No Cloudflare esse caminho existe, mas é o caminho errado para começar. Eu perdi umas duas horas lendo o arquivo index.js achando que iria entender tudo — e terminei mais confuso do que comecei. Isso aconteceu porque o Worker (um pequeno programa que roda na nuvem da Cloudflare) funciona apenas como um dispatcher (um direcionador ou recepcionista); a lógica real está espalhada entre handlers (funções que tratam cada tarefa), bindings (as conexões com outros serviços) e recursos que o código não mostra sozinho.
O que de fato me deu o mapa do projeto foi perceber que, no ecossistema Cloudflare, a engenharia reversa (o ato de desmontar para entender como foi feito) começa por dois lugares específicos, e nenhum deles é o código-fonte principal.
O wrangler.toml é a planta baixa
O arquivo wrangler.toml (ou wrangler.jsonc) é o arquivo de configuração do deploy (o processo de colocar a aplicação para rodar no ar). Ele te diz, antes de você ler qualquer linha de código, com o que o projeto se conecta. É a mesma diferença entre olhar a planta de um prédio ou tentar decifrar a estrutura dele andando no escuro pelos corredores.
O que procurar no arquivo, exatamente nesta ordem:
nameecompatibility_date— qual é o nome do Worker e quais recursos do motor V8 (a tecnologia que executa o JavaScript) estão ativos. A data de compatibilidade dita as regras do jogo; um Worker configurado com a data de 2023 pode assumir comportamentos que mudaram com o tempo.[[d1_databases]]— existe um bloco D1? Se sim, significa que o projeto guarda dados em um banco de dados relacional (usando SQLite rodando no edge, ou seja, em servidores espalhados pelo mundo bem perto do usuário). Anote obinding— é por esse nome de conexão (env.DB) que o código conversa com o banco.[[kv_namespaces]]ou[[r2_buckets]]— o projeto armazena blobs (arquivos grandes como fotos e documentos, no R2) ou chave-valor (KV, que funciona como um dicionário super rápido de dados)? Cada um é uma categoria diferente de estado (dados salvos).[vars]— variáveis de ambiente não-secretas (configurações abertas da aplicação). E as senhas ou chaves secretas? Segredos não aparecem neste arquivo; eles são configurados pelo terminal via comandowrangler secret pute só existem quando o projeto está rodando na nuvem.[assets]— tem um diretório de assets (arquivos estáticos)? Então o Worker também entrega páginas HTML e imagens do frontend, e não funciona apenas como uma API (que fornece só dados brutos).
Só com isso, antes de tocar no código, você já sabe: o projeto tem banco de dados, tem memória cache, tem telas visuais e qual nome de conexão (binding) liga cada peça.
Dissecando o ponto de entrada
O ponto de entrada (onde tudo começa) de um Worker é um arquivo que exporta um objeto com o método fetch (uma função que “atende” as requisições de rede que chegam). Em projetos organizados, não é um arquivo index.js gigante de mil linhas — é um roteador leve (que pode usar bibliotecas como itty-router, Hono, ou uma estrutura de controle simples tipo switch case) que despacha as chamadas para os seus devidos lugares.
// padrão típico
export default {
async fetch(req, env) {
const url = new URL(req.url);
if (url.pathname.startsWith('/api/')) return apiRouter(req, env);
return env.ASSETS.fetch(req); // serve HTML estático
},
};
Esse padrão de duas vias — tudo que começa com /api/* vai para a lógica de código, e o resto vai para os assets (o site estático) — é o que diferencia um Worker “full-stack” (que entrega o site completo, frontend e backend) de um Worker “só API”. Se o arquivo wrangler.toml possui o bloco [assets], quase sempre a estrutura é essa.
A partir daí, você segue a rota. O frontend chamou GET /api/candidato/123? Você vai no roteador e vê que essa chamada bate no arquivo pessoaHandler.js. Lá dentro está a consulta SQL (a instrução para buscar dados) que extrai informações do banco D1. O fluxo completo — requisição (request) → conexão (binding) → consulta (query) → resposta (response) — fica claro e visível navegando por apenas 4 arquivos.
A pasta .wrangler/state: não apague achando que é cache
Esse foi o erro que cometi e que me custou a perda de um banco de dados de testes. A pasta .wrangler/state contém os dados locais simulados (mockados) do D1 — ou seja, o seu banco de dados de desenvolvimento que roda no seu próprio computador. Visualmente, ela se parece com uma pasta de cache de compilação (aqueles arquivos temporários dispensáveis, igual à pasta node_modules ou .cache). Mas ela não é.
Se você apagar essa pasta achando que é lixo eletrônico, apaga junto o banco de dados local onde você estava testando a aplicação. O Worker continua funcionando, mas as consultas que dependiam daqueles dados voltam completamente vazias. A confusão fica enorme porque o sistema não mostra nenhum erro claro — apenas entrega um “resultado inesperado”.
A regra que guardei depois disso: tudo que começa com ponto em um projeto Cloudflare é estado (dados salvos), não cache descartável. Não apago nada sem antes saber exatamente o que está armazenado ali dentro.
O procedimento que fixei
Depois de errar a ordem na primeira vez, criei um passo a passo definitivo para mapear qualquer projeto Cloudflare que eu assumir:
- Abrir o
wrangler.tomlprimeiro. Anotar todas as conexões (bindings): D1, KV, R2, ASSETS e secrets. Sem essa lista, o código não faz sentido. - Achar o ponto de entrada do
fetch. É a porta de entrada onde a distribuição das chamadas acontece. - Seguir uma rota de ponta a ponta. Pegar um endereço público qualquer do sistema e rastrear o caminho: requisição (request) → manipulador (handler) → conexão (binding) → consulta (query) → resposta (response).
- Listar os segredos com
wrangler secret list. O arquivowrangler.tomlnão mostra os valores das senhas, mas esse comando lista quais chaves existem. Isso te diz exatamente quais APIs e serviços externos o projeto consome.
Quatro passos e meia hora de trabalho. Em qualquer projeto Cloudflare, essa rotina te entrega o mapa completo. O resto é apenas ler o código com o mapa em mãos.
O que aprendi
A lição que fica para além deste caso: a ordem de leitura importa tanto quanto o conteúdo do que você lê. Eu comecei lendo direto o código-fonte porque é o que faria em um projeto Node.js tradicional. No ecossistema Cloudflare, isso é o equivalente a tentar explorar os quartos de uma casa antes de ver a planta baixa — você entende os detalhes sem compreender a estrutura que os sustenta. O arquivo wrangler.toml é a planta. Agora, eu sempre leio ele primeiro.
E o segundo aprendizado: em plataformas serverless (onde não gerenciamos servidores físicos diretamente), a configuração faz parte do próprio código. O que no Node.js tradicional chamamos de “infraestrutura que roda ao redor do código”, no Cloudflare vira “bindings que o código acessa diretamente através do objeto env”. Ignorar a configuração é o mesmo que ignorar metade de toda a aplicação.
Comentários
Carregando comentários…