Depurar webhooks sem a canalização

Toda a integração de webhooks começa com o mesmo problema pouco glamoroso: o servidor do fornecedor precisa de chamar o seu código, o seu código corre no seu portátil, e nada consegue chegar ao seu portátil. Por isso, antes de depurar o trabalho real — a verificação da assinatura, a forma da carga, a lógica do processador — primeiro constrói a canalização: um túnel, uma implantação de staging, um URL público que reencaminha para a sua máquina. Este artigo trata de saltar esse passo com um recetor temporário como o Testador de Webhooks deste site: crie um endereço, aponte o fornecedor para ele, acione o evento e leia exatamente o que chegou. Depois escreva o seu processador contra a verdade, e não contra a documentação.

O ciclo de depuração, e onde ele se quebra

O ciclo saudável de um webhook é curto: um evento acontece no fornecedor, o fornecedor faz POST de uma carga assinada para o seu endpoint, o seu endpoint verifica a assinatura, analisa o corpo, faz o trabalho e responde 200. O ciclo doentio — aquele que toda a gente reconhece — acrescenta nevoeiro a cada passo. O painel do fornecedor diz que a entrega falhou com um 500, ou um 404, ou nada de todo. Era o seu código a responder, um proxy pelo meio, ou um URL de endpoint com um erro de escrita? A nova tentativa chega com o mesmo id de evento — ou é um evento novo para o mesmo pagamento? A documentação mostra um exemplo JSON arrumado, mas as cargas de produção trazem campos extra, objetos aninhados que o exemplo achatou e, ocasionalmente, um tipo de conteúdo que o exemplo nunca mencionou. A documentação de webhooks do Stripe e do GitHub (ligada abaixo) insiste nas mesmas disciplinas — verificar assinaturas, responder depressa, tratar duplicados — e nenhuma delas pode ser praticada até conseguir ver uma entrega real.

A quebra quase nunca está na lógica interessante. Está na distância entre o que acredita que foi enviado e o que foi enviado: um cabeçalho de assinatura calculado sobre um corpo que a sua framework já tinha analisado e resserializado, um segredo copiado do painel errado, um tipo de evento que a sua instrução switch escreve ligeiramente diferente, um processador que funciona para o evento de teste do painel e não para o evento real de produção. Tudo isso é invisível de dentro dos seus próprios registos, porque os seus registos começam depois de o seu código já ter feito a sua primeira suposição errada. Uma entrega capturada, registada por algo que não é o seu código, é a verdade fundamental que encurta o ciclo.

O que um recetor temporário lhe compra

Um recetor temporário é um URL público cujo único trabalho é aceitar tudo e mostrar-lhe: o Testador de Webhooks deste site cria um com um clique, mantém-no durante 30 minutos, regista até 50 entregas com o seu método, caminho e consulta, cabeçalhos e corpo (até 256 KB cada), e depois elimina tudo automaticamente. O que isso lhe compra é sequenciação. Em vez de implementar um processador meio escrito numa máquina pública só para observar o tráfego — e depois depurar a implementação e o processador ao mesmo tempo —, separa a observação da implementação. Primeiro, observe vários eventos reais a chegar e aprenda a sua forma verdadeira. Depois escreva o processador localmente, contra cargas capturadas que pode repetir manualmente nos seus próprios testes. Por fim, aponte o fornecedor para o seu endpoint real e acione o evento mais uma vez, sabendo já exatamente como é uma entrega correta e o que o seu processador deve fazer com ela.

Também lhe compra provas quando a conversa atravessa a fronteira de uma equipa. «O teu webhook envia o montante como cadeia» é uma discussão; uma entrega capturada que mostra "amount": "2000" é um facto. A mesma captura responde às perguntas dos tickets de suporte dos fornecedores — que id de evento, que carimbo temporal, que cabeçalho de assinatura estava presente — sem uma ronda de arqueologia de registos, e esclarece se uma entrega em falta nunca foi enviada ou foi enviada para o endereço de teste antigo que alguém se esqueceu de atualizar. Ferramenta vizinha, mesma filosofia: o traçador de cadeias de estado HTTP mostra o que um URL faz do ponto de vista de um servidor quando a questão é de redirecionamentos e não de cargas.

O fluxo de trabalho, com esta ferramenta

Um: abra o Testador de Webhooks e crie um hook. Copie o URL de receção — e a partir deste momento trate esse URL como uma credencial, pelas razões que a secção seguinte explica. Dois: cole-o nas definições de webhook do fornecedor como endpoint de teste — o Stripe, o GitHub e a maioria dos fornecedores permitem vários endpoints, pelo que o seu endpoint de produção fica intocado — ou na configuração do seu próprio serviço, se estiver a depurar um remetente que controla. Três: acione o evento da maneira honesta. Use o fluxo real do fornecedor (um pagamento em modo de teste, um push real para um ramo descartável) em vez de apenas o botão «enviar evento de teste» do painel, porque os eventos de teste por vezes diferem dos reais precisamente nos campos que lhe interessam. Quatro: leia a captura. Verifique primeiro o método e o tipo de conteúdo, depois a assinatura e os cabeçalhos do evento, e depois o corpo como texto bruto, antes de confiar em qualquer vista bonita dele.

Cinco: escreva ou corrija o seu processador contra essa captura. Verifique a assinatura sobre o corpo bruto exatamente como foi recebido — é por isso que a captura mostra os bytes por analisar — e torne o seu processador idempotente sobre o id de evento que agora consegue ver que é estável entre novas tentativas. Seis: elimine o hook (ou deixe passar os seus 30 minutos), remova o endpoint de teste do fornecedor e volte a apontar a entrega para o seu processador real. Sete: acione o evento mais uma vez e veja o seu próprio endpoint responder-lhe. Se agora falhar, a diferença entre a entrega boa capturada e o comportamento do seu processador é todo o erro, e é uma diferença que pode inspecionar em vez de adivinhar.

Segurança: o URL é a credencial

Um recetor que qualquer pessoa pode ler não precisa de início de sessão, e essa conveniência tem um preço ao qual deve prestar atenção: o id do hook no URL é a única credencial, e autoriza tanto enviar como ver. Qualquer pessoa que obtenha o URL — de uma captura de ecrã, de um registo de chat, de um ecrã partilhado — pode ler cada carga que o hook capturar enquanto ele viver. Por isso as regras são as das palavras-passe: nunca publique o URL, nunca o use para um feed de produção ao vivo, e elimine o hook quando a sessão terminar, em vez de deixar as capturas esgotarem a sua meia hora. As cargas merecem o mesmo respeito do outro lado: uma carga real de pagamento ou de push pode conter endereços de correio de clientes, detalhes de encomendas e metadados que não colaria num gist público, e uma entrega capturada é exatamente essa classe de documento. O modo de teste, os repositórios descartáveis e os eventos sintéticos existem precisamente para que os artefactos de depuração não contenham nada que valha a pena roubar.

Os próprios limites do testador fazem parte da história de segurança e estão declarados claramente na página da ferramenta: as capturas são guardadas no servidor de verificação apenas até o hook expirar ou o eliminar — 30 minutos no máximo —, os corpos estão limitados a 256 KB e os hooks a 50 pedidos, e o recetor nunca vai buscar, seguir ou repetir nada, pelo que uma carga capturada não pode transformar-se em tráfego de saída do servidor. Mesmo assim, os juízos ficam consigo. Se uma carga seria um problema nas mãos de um estranho, não pertence de todo a um visualizador partilhado: use a sua própria infraestrutura para essa sessão de depuração, como faria com os segredos de produção. As ferramentas convenientes ganham o seu lugar no trabalho de baixa sensibilidade que preenche a maioria dos dias de depuração.

Limites: apenas receber e inspecionar

O que esta ferramenta deliberadamente não faz é tudo o que vem depois da inspeção. Não reencaminha entregas para o seu portátil (esse é o trabalho de um túnel, e os túneis são a ferramenta certa quando o processador já existe e está a iterar sobre ele ao vivo), não repete um pedido capturado para o seu endpoint real, não transforma nem assina nada, e não mantém um histórico além de 30 minutos. Essas ausências são o desenho: um recetor que reencaminha é um proxy com o seu tráfego a fluir por ele, um recetor que repete é um remetente, e ambos são confianças maiores do que uma caixa de entrada de 30 minutos. Use o testador para a fase a que ele se adequa — ver a verdade antes e enquanto constrói o processador — e deixe o seu próprio endpoint, atrás da sua própria autenticação e dos seus próprios registos, assumir no momento em que a integração entrar em produção.

Fontes e leituras adicionais

Perguntas frequentes

Posso usar um recetor temporário com o Stripe ou o GitHub?

Sim — ambos permitem registar endpoints de webhook adicionais, pelo que o recetor pode coexistir com o seu endpoint de produção sem o tocar. Crie o hook, adicione o seu URL nas definições de webhook do fornecedor e use o modo de teste (Stripe) ou um repositório descartável (GitHub) para acionar eventos reais. A documentação de ambos os fornecedores, ligada nas fontes, cobre o registo de endpoints e os seus esquemas de assinatura; verifique as assinaturas no seu processador sobre o corpo bruto, exatamente como a captura o mostra.

É seguro apontar webhooks reais de produção para um recetor partilhado?

Não. Qualquer pessoa com o URL do hook pode ler tudo o que ele capturar, e as cargas reais transportam rotineiramente dados de clientes. Use o modo de teste, contas sandbox e eventos sintéticos com um recetor partilhado; mantenha o tráfego de produção na sua própria infraestrutura. O hook também expira após 30 minutos, pelo que um feed de produção apontado a um começaria a falhar silenciosamente meia hora depois — outra razão para ser uma ferramenta de depuração, e não um endpoint.

Porque é que o testador não reencaminha pedidos para o meu computador?

Porque receber e inspecionar é uma confiança deliberadamente pequena: o servidor guarda uma entrega durante 30 minutos no máximo e nunca inicia tráfego por sua conta. Reencaminhar torná-lo-ia um proxy de tráfego arbitrário para a sua máquina, e repetir torná-lo-ia um remetente — ambos são serviços diferentes e maiores, com riscos diferentes. Quando o seu processador existir e estiver a iterar ao vivo, um túnel é a ferramenta certa para essa fase.