O teste que falta antes de publicar um link curto: HEAD, GET e redirecionamentos
Você vai colocar um link curto num QR Code impresso, num e-mail ou numa documentação. Antes de publicar, roda curl -I, vê um Location correto e considera o teste encerrado. Parece razoável. Só que esse comando não reproduz a requisição que acontece quando alguém abre o link no navegador.
-I faz uma requisição HEAD. Ao abrir a URL, o navegador normalmente faz GET. Pela semântica do HTTP, HEAD deve se comportar como GET sem enviar o corpo da resposta. Na prática, uma configuração equivocada pode tratar os dois métodos de formas diferentes. O teste com HEAD continua útil; o problema é usá-lo como prova única.
Montei um laboratório local pequeno para mostrar a diferença, sem depender de nenhum encurtador real.
Primeiro, suba o laboratório
Salve o código abaixo como redirect-lab.mjs e execute node redirect-lab.mjs. Ele usa apenas o módulo HTTP do Node.js. O comportamento inconsistente é proposital: serve para demonstrar por que vale comparar os métodos, não para sugerir que HEAD e GET devam levar a destinos diferentes.
import http from 'node:http';
http.createServer((req, res) => {
if (req.url === '/curto') {
res.writeHead(302, {
Location: req.method === 'HEAD' ? '/pagina-antiga' : '/pagina-nova',
'Cache-Control': 'no-store',
});
res.end();
return;
}
if (req.url === '/pagina-antiga') {
res.writeHead(404);
res.end('Página antiga não encontrada\n');
return;
}
if (req.url === '/pagina-nova') {
res.writeHead(200);
res.end('Página nova\n');
return;
}
res.writeHead(404);
res.end();
}).listen(8765, '127.0.0.1');
Primeiro salto não é a viagem inteira
Vamos partir de uma URL de teste:
http://127.0.0.1:8765/curto
Para ver a resposta ao HEAD:
curl -sS -I http://127.0.0.1:8765/curto
Para ver os cabeçalhos de uma requisição GET, sem mostrar o corpo na tela:
curl -sS -D - -o /dev/null http://127.0.0.1:8765/curto
Aqui, -D - imprime os cabeçalhos recebidos e -o /dev/null descarta o corpo da resposta. Diferente de -I, isso ainda é um GET. Sem -L, o curl para na primeira resposta de redirecionamento. O manual do curl documenta essas opções.
Se você quer acompanhar os redirecionamentos HTTP até a resposta final, acrescente -L e um limite de saltos:
curl -sS -L --max-redirs 5 -D - -o /dev/null \
-w 'final=%{url_effective} saltos=%{num_redirects} codigo=%{http_code}\n' \
http://127.0.0.1:8765/curto
Assim aparecem os cabeçalhos de cada etapa, seguidos pela URL efetiva, pela quantidade de redirecionamentos seguidos e pelo código da última resposta. O limite impede que um loop faça o teste seguir dezenas de URLs.
O terminal com o laboratório deve continuar aberto. Rode os três comandos em outro terminal. No primeiro, a parte importante da saída é:
HTTP/1.1 302 Found
Location: /pagina-antiga
No GET sem -L, a resposta já muda:
HTTP/1.1 302 Found
Location: /pagina-nova
No GET com -L, o curl segue esse segundo caminho:
HTTP/1.1 302 Found
Location: /pagina-nova
HTTP/1.1 200 OK
final=http://127.0.0.1:8765/pagina-nova saltos=1 codigo=200
Os trechos acima foram executados no laboratório local; omiti data e cabeçalhos não essenciais. Se você tivesse conferido apenas curl -I, teria registrado /pagina-antiga como destino, embora o GET chegue a /pagina-nova.
Como interpretar um teste de verdade
Há três perguntas diferentes, e cada comando responde só a parte delas:
- Qual é o primeiro salto? Leia o código
3xxe o cabeçalhoLocationda primeira resposta. O valor pode ser relativo, como/pagina-nova; nesse caso, ele é resolvido a partir da URL atual. - HEAD e GET concordam? Compare as respostas iniciais. Se não concordarem, investigue a aplicação, o proxy ou a CDN antes de publicar o link. O laboratório acima é um exemplo deliberadamente quebrado.
- Onde termina a cadeia HTTP? Use GET com
-Le confira cada resposta, a URL efetiva e o código final. Um200no fim significa que houve uma resposta bem-sucedida naquele ponto da cadeia HTTP; não prova que a página mostrada ao usuário seja o destino esperado.
O último detalhe importa. Uma página intermediária pode responder 200 e depois navegar por JavaScript ou por meta refresh. O curl não executa JavaScript como um navegador, e -L acompanha redirecionamentos HTTP, não todos os mecanismos de navegação de uma página. A documentação da MDN separa esses tipos de redirecionamento.
Se o resultado do terminal e o do navegador diferirem, abra as ferramentas de desenvolvimento, ative Preserve log na aba Network e observe a sequência real de requisições. Isso ajuda a separar um redirecionamento HTTP de uma navegação iniciada pelo HTML ou pelo JavaScript.
O limite que eu não ignoraria
Esse procedimento não certifica a segurança de uma URL. Ao requisitar um link, você já entra em contato com o servidor, que pode registrar a visita ou contá-la como clique. O destino também pode variar por horário, região, dispositivo ou outros sinais. Para uma URL suspeita, não faça um processo automatizado seguir destinos arbitrários a partir de uma rede interna só porque o primeiro Location parece confiável.
Para links sob seu controle, a regra prática é simples: compare HEAD e GET, siga a cadeia HTTP com um limite e faça uma última verificação no navegador. São testes complementares, não três maneiras de obter a mesma resposta.
Transparência: colaboro com o encurtar.link. O laboratório deste texto é genérico, roda localmente e não descreve a implementação do serviço.