http

HTTP ferramentas

Uma referência prática para depurar HTTP: semântica de status e de redirecionamento, diretivas de Cache-Control e qual ferramenta usar quando cabeçalhos, URLs ou cartões de compartilhamento se comportam mal.

9 ferramentas

§01 GUIA DO TEMA

O que você está depurando de verdade

Uma troca HTTP são quatro coisas separáveis, e a maior parte do tempo perdido em depuração vem de misturá-las: a URL (o que você pediu), os cabeçalhos de requisição (quem você afirma ser e o que aceita), a linha de status (o veredito) e os cabeçalhos de resposta (o contrato de cache, segurança e tipo de conteúdo). O corpo é a parte menos interessante — quando ele está errado, os cabeçalhos já explicaram o motivo.

Segundo, quase nada do que um navegador lhe mostra é a saída bruta da origem. Entre o seu servidor e o painel Network estão uma CDN, talvez um proxy, o HTTP/2 ou /3 (que deixam os nomes de campo em minúsculas e descartam a frase de motivo), um service worker e o cache em disco. Uma linha 200 OK (from disk cache) é a lembrança de uma resposta, não uma resposta — então, quando um cabeçalho parece ausente, pergunte primeiro de quem é a cópia que você está lendo.

Terceiro, o HTTP é em grande parte autodeclarado: User-Agent, Referer, Accept-Language e todo cabeçalho X- personalizado são afirmações que um cliente escolheu enviar, falsificáveis em uma linha de código. Só o que a origem emite — o código de status e os cabeçalhos de resposta — está sob o seu controle.

As classes de status de relance

ClasseSignificadoO que o cliente deve fazerCacheável por heurística
1xxProvisório (100, 101, 103)Continuar esperandoNão
2xxSucessoUsar o corpo (204 não tem)200, 203, 204, 206
3xxRedirecionamento / revalidaçãoSeguir Location; reusar o cache em 304300, 301, 308
4xxErrado como enviadoCorrigir; não repetir às cegas404, 405, 410, 414
5xxServidor falhou em uma requisição válidaRecuar; honrar Retry-After501

Dois códigos são rotineiramente mal tratados: 429 deveria carregar Retry-After, e 304 Not Modified é um sucesso — registrá-lo como erro esconde um cache funcionando.

A matriz de redirecionamentos que as pessoas erram

CódigoPermanênciaMétodo e corpo preservadosUsar para
301PermanenteNão — pode virar GETURL renomeada, consolidação de host
302TemporárioNão — mesmo risco de reescritaPadrão legado; evite para POST
303TemporárioNão — força GETPOST e depois redirecionar para um resultado
307TemporárioSimMudança temporária de endpoint de API
308PermanenteSimMudança permanente de endpoint POST

Os navegadores também guardam 301 com força, às vezes por toda a vida do perfil, então um erro desses é caro de desfazer — verifique primeiro em staging.

Cache-Control, diretiva por diretiva

DiretivaGovernaObservação
max-age=NFrescor em segundos, em qualquer cache0 força revalidação
s-maxage=NFrescor só para caches compartilhadosSobrepõe max-age na CDN
no-cacheArmazenar sim; revalidar antes de reusarNão é no-store
no-storeProíbe armazenar a respostaHTML autenticado
privateO navegador pode armazenar, caches compartilhados nãoRespostas personalizadas
must-revalidateNada de servir conteúdo velho em caso de erroCombine com max-age
immutableNunca revalidar enquanto estiver frescoAtivos com hash no nome
stale-while-revalidate=NServir o velho e atualizar em segundo planoSuaviza falhas de cache na CDN

O Vary também pertence a este lugar: se uma resposta varia conforme Accept-Language ou um cabeçalho personalizado e você nunca declara isso, um cache compartilhado entrega a variante errada ao próximo visitante.

Qual ferramenta para qual pergunta

Quando você tem uma URL e quer a resposta da própria origem, use os Cabeçalhos HTTP: a requisição parte de api.sitekits.dev, então nenhuma extensão, cache ou service worker está no caminho, e você recebe o status final, a URL final, a contagem de saltos e todo cabeçalho de resposta. Ele lê apenas cabeçalhos, nunca o corpo, e sua proteção contra SSRF recusa localhost e faixas privadas.

Quando você precisa enviar algo específico — um PATCH com corpo JSON, um cabeçalho Authorization: Bearer, um OPTIONS seco para ler um preflight — use o Testador REST API. As requisições vão do seu navegador direto ao destino, então a política de CORS dele se aplica exatamente como se aplica ao código do seu próprio front-end — ideal quando o bug é CORS. Se o token é o suspeito, cole-o no Decodificador JWT para ler o exp e as claims; decodificar não é verificar.

Quando a unidade que falha é um carregamento de página inteiro em vez de uma requisição, exporte um HAR e abra no Visualizador HAR; o guia de campo do HAR cobre os tempos. Mistérios de query string caem para o Parseador de URL, que lista os parâmetros decodificados de percent-encoding usando o parser WHATWG do navegador, mais o URL Encode quando um valor foi escapado uma vez a mais. O Parseador UserAgent reduz uma string de UA a navegador, sistema operacional, classe de dispositivo e uma heurística de bot; códigos desconhecidos vão para os Códigos HTTP; um arquivo que baixa em vez de renderizar geralmente é uma questão de Content-Type para o Verificador MIME. Quando a resposta está saudável mas o cartão de compartilhamento está errado, cole o HTML da página na Pré-visualização OG — a análise é local, então funciona em builds de staging e atrás de login.

Pegadinhas

Strict-Transport-Security em uma resposta HTTP não faz nada

Os navegadores ignoram HSTS entregue por HTTP puro, e cookies Secure também são descartados ali. Sirva o redirecionamento de upgrade na porta 80 e os cabeçalhos de segurança na resposta HTTPS — e verifique os dois saltos, não só o último.

Cabeçalhos de segurança são por resposta, não por site

Um Content-Security-Policy endurecido no seu HTML não diz nada sobre o JSON da sua API, sobre as páginas de erro da sua CDN ou sobre um bucket de uploads em outro lugar. O Gerador CSP escreve o cabeçalho; a sua configuração de deploy decide quais respostas o carregam.

Cadeias de redirecionamento custam ida e volta

http://example.comhttps://example.comhttps://www.example.com//home/ custa três idas e voltas extras antes de qualquer HTML, e cada salto pode descartar um método, um cookie ou uma query string. Reduza tudo a um salto na borda.

200 com um erro no corpo derrota o monitoramento por status

Responder 200 enquanto o payload diz {"error": ...} esconde falhas dos alertas baseados em classe de status e infla a disponibilidade medida. Se o SLO é seu, faça a asserção sobre o payload também — veja as ferramentas reunidas para trabalho de SRE.

+ e %20 não são intercambiáveis

Em uma query string codificada como application/x-www-form-urlencoded, + decodifica para espaço; em um segmento de caminho ele é um sinal de mais literal. A codificação dupla é o bug irmão: %20 se torna %2520 e a quebra parece problema de roteamento, não de escapamento.

FAQ
Por que meu POST virou um GET depois de um redirecionamento?
Porque 301 e 302 permitem que clientes reescrevam o método para GET e descartem o corpo, e os navegadores fazem exatamente isso. Use 307 para uma mudança temporária e 308 para uma permanente quando o método e o corpo precisam sobreviver ao salto. Um formulário ou webhook que perde o payload silenciosamente geralmente está batendo em um redirecionamento de http para https ou de barra final configurado como 301.
Por que os cabeçalhos de resposta no DevTools são diferentes do que diz a configuração do meu servidor?
O que o DevTools mostra é a resposta depois de todos os saltos. Uma CDN, um proxy reverso ou um service worker podem adicionar, reescrever ou remover cabeçalhos, o HTTP/2 e o /3 deixam todo nome de campo em minúsculas e descartam a frase de motivo, e uma linha marcada como 200 (from disk cache) não é uma resposta nova de forma alguma. Buscar a URL pelo lado do servidor elimina essas variáveis e mostra o que a origem emitiu para a URL final da cadeia.
O Cache-Control no-cache impede que os navegadores armazenem minha página?
Não. no-cache permite o armazenamento, mas exige revalidação com a origem, normalmente via ETag e If-None-Match, antes de uma cópia guardada ser reutilizada. no-store é a diretiva que proíbe gravar a resposta em disco. HTML autenticado normalmente quer private, no-store, enquanto ativos estáticos com hash no nome querem um max-age longo mais immutable.
Por que minha API funciona no curl e falha no navegador com um erro de CORS?
O CORS é imposto pelo navegador, não pelo servidor, e o curl o ignora por completo. Para qualquer coisa além de uma requisição simples, o navegador primeiro envia um preflight OPTIONS e se recusa a expor a resposta a menos que a origem devolva um Access-Control-Allow-Origin compatível, mais Access-Control-Allow-Credentials quando há cookies envolvidos. O servidor muitas vezes responde 200 perfeitamente bem; você simplesmente não pode ler. Inspecione primeiro a resposta do OPTIONS.
Por que meu cabeçalho Strict-Transport-Security está sendo ignorado?
Porque os navegadores só honram o HSTS quando ele chega por HTTPS. Uma política servida em uma resposta HTTP puro é descartada de imediato — assim como qualquer cookie Secure definido ali — então a resposta na porta 80 deve carregar o redirecionamento de upgrade e nada mais, com os cabeçalhos de segurança anexados à resposta HTTPS. Verifique cada salto em vez do 200 final: um cabeçalho presente no fim de uma cadeia de redirecionamentos não diz nada sobre o que o primeiro salto enviou. Lembre-se de que includeSubDomains e preload comprometem todo subdomínio com HTTPS pelo max-age que você publicou, e sair da lista de preload leva meses.