303 See Other: o redirecionamento depois de um POST de formulário
O 303 See Other diz ao cliente que a requisição foi processada e o resultado está em outra URL, que deve ser buscada com GET. É a resposta correta para um envio de formulário que deve levar o visitante a uma página de resultado ou confirmação, em vez de deixá-lo no POST.
Para que serve o 303
Um 303 não é exatamente sobre mover um recurso. É sobre separar uma ação do seu resultado. O cliente envia um POST, o servidor executa a ação, e então, em vez de devolver o resultado na resposta do POST, ele responde com 303 e um cabeçalho Location. O cliente faz um GET novo para aquele local, e a barra de endereço do navegador termina em uma URL comum que pode ser favoritada e recarregada.
A regra definidora é o método: seja qual for o método da requisição original, a requisição seguinte para a URL do Location é um GET. Isso é o oposto do 307 e do 308, que exigem que o método e o corpo originais sejam preservados.
Post/Redirect/Get, e o problema que resolve
Sem um redirecionamento depois de um POST, a página de resultado pertence à requisição POST, o que causa problemas conhecidos:
- Apertar recarregar reenvia o formulário, então o pedido é feito ou o comentário é postado duas vezes. Os navegadores avisam sobre isso com uma caixa de diálogo de "confirmar reenvio de formulário", que já é uma experiência ruim em si.
- A página não pode ser favoritada ou compartilhada, porque a URL não descreve o conteúdo.
- O botão voltar leva a um prompt de reenvio em vez da página anterior.
O Post/Redirect/Get corrige todos eles. O POST executa a ação e responde 303; o navegador faz GET na URL de resultado; um recarregamento agora só busca de novo uma página inofensiva. É por isso que quase todo framework tem um helper de "redirecionar depois de salvar".
303 vs 302 vs 307
- 302 Found é um redirecionamento temporário cujo tratamento de método é historicamente ambíguo. A maioria dos clientes transforma um POST em GET ao segui-lo, o que geralmente é o que você queria, mas o padrão não exige isso. Muitos frameworks ainda emitem 302 para post-depois-redirecionar e funciona na prática.
- 303 See Other torna esse comportamento explícito e obrigatório. Se sua intenção é "não repita meu POST, vá e faça GET nisso em vez disso", o 303 declara isso sem ambiguidade.
- 307 Temporary Redirect é o que evitar aqui. Ele exige que o POST seja repetido contra a nova URL, o que para o envio de um formulário significa executar a ação duas vezes.
Uma ressalva prática: o 303 foi introduzido no HTTP/1.1, então um cliente falando HTTP/1.0 pode não entendê-lo. Alguns frameworks usam 302 como padrão por esse motivo. Na web moderna isso raramente é uma restrição real, mas explica a divisão nos padrões que você vai ver entre linguagens.
Onde mais o 303 aparece
- APIs que iniciam um trabalho de longa duração. Um POST dispara um job e responde 303 com a URL de status daquele job, ou 202 com uma URL de status no corpo. Os dois padrões estão em uso; o 303 tem a vantagem de um navegador segui-lo automaticamente.
- Fluxos de OAuth e login. Alguns servidores de autorização redirecionam de volta para a aplicação cliente com um 303, para que o callback seja buscado com GET independentemente de como a requisição chegou.
- Configurações de dados vinculados (linked data) e negociação de conteúdo que distinguem uma coisa do mundo real do documento que a descreve, e usam o 303 para enviar clientes do identificador para o documento.
Como usar e verificar
- Depois de um POST bem-sucedido, devolva 303 com um
Locationabsoluto apontando para a página de resultado. Não renderize o resultado embutido. - Torne o destino idempotente. Ele vai ser buscado de novo a cada recarregamento e a cada navegação para trás, então precisa ser seguro para receber GET repetidamente.
- Carregue qualquer mensagem única, como "suas mudanças foram salvas", no estado da sessão ou em um parâmetro de consulta, em vez de no corpo do redirecionamento. O corpo de uma resposta 303 normalmente não é exibido.
- Verifique o código e o alvo:
Você deve vercurl -si -X POST -d "name=test" https://example.com/submit | grep -Ei "^(HTTP|location)"HTTP/1.1 303 See Othere a URL de resultado. - Siga o link e confirme que a segunda requisição é um GET que devolve 200. Se você ver um POST repetido nos logs do seu servidor, a regra está como 307 e precisa mudar.
- Confira se o destino em si não é outro redirecionamento. Um 303 para um 301 para a página real são três idas e voltas para um único envio de formulário.
Monitorando os endpoints por trás de um formulário
Um fluxo quebrado de post-depois-redirecionar é invisível para uma verificação que só busca a página inicial. O site está no ar, o formulário renderiza, e só as pessoas que o enviam encontram a falha. Pegue isso cedo observando os endpoints por trás da ação, como a página de resultado, a URL de confirmação e a rota de status do job, e verificando o código de status e o conteúdo esperados em cada um. A HostTracker oferece 13 tipos de monitor e alerta por e-mail, SMS, chamada de voz, Slack, Telegram e mais. Verifique o que qualquer URL devolve com a ferramenta de verificação HTTP, e leia 301 vs 302 e o guia completo da família de redirecionamento 3xx para os códigos vizinhos.