Por que o HTTP não tem redirecionamento POST?

162

Os redirecionamentos HTTP são feitos pelos códigos HTTP 301 e 302 (talvez outros códigos também) e um campo de cabeçalho conhecido como "Local", que possui o endereço do novo local a ser percorrido. No entanto, os navegadores sempre enviam uma solicitação "GET" para esse URL.

No entanto, muitas vezes você precisa redirecionar seu usuário para outro domínio via POST (pagamentos bancários, por exemplo). Este é um cenário comum e realmente um requisito. Alguém sabe por que um requisito tão comum foi negligenciado na especificação HTTP? A solução alternativa é enviar um formulário (com parâmetros em campos ocultos) com ação definida para o local de destino (o valor do campo de cabeçalho Local ) e usar setTimeoutpara enviar o formulário para o local de destino.

Saeed Neamati
fonte
1
O código de status 307 é o que você está procurando? Veja minha resposta abaixo.
David Ruttka

Respostas:

180

No HTTP 1.1, existe realmente um código de status ( 307 ) que indica que a solicitação deve ser repetida usando o mesmo método e postar dados .

Como outros já disseram, existe um potencial de uso indevido aqui, e pode ser por isso que muitas estruturas aderem a 301 e 302 em suas abstrações. No entanto, com o entendimento adequado e o uso responsável, você deve conseguir o que está procurando.

Observe que, de acordo com a especificação do W3.org , quando METHODnão é HEADou GET, os agentes do usuário devem avisar o usuário antes de executar novamente a solicitação no novo local. Você também deve fornecer uma observação e um mecanismo de fallback para o usuário, caso os agentes antigos não tenham certeza do que fazer com um 307.

Usando este formulário:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

E com o Test307.aspx, basta retornar 307 com o Local: http://google.com , o Chrome 13 e o Fiddler confirmam que "test = the test" é realmente publicado no Google. É claro que a resposta é 405, já que o Google não permite o POST, mas mostra a mecânica.

Para obter mais informações, consulte Lista de códigos de status HTTP e a especificação W3.org .

Redirecionamento temporário (desde HTTP / 1.1) Nessa ocasião, a solicitação deve ser repetida com outro URI, mas solicitações futuras ainda podem usar o URI original. 2 Ao contrário de 303, o método de solicitação não deve ser alterado ao reemitir a solicitação original. Por exemplo, uma solicitação POST deve ser repetida usando outra solicitação POST.

David Ruttka
fonte
2
@ DavidRuttka, Qual é o suporte do navegador em estado selvagem ?
Pacerier
5
@ DavidRuttka, você pode querer atualizar sua resposta para levar em consideração o rfc7231 (obsoletos rfc2616). A solicitação do usuário é baseada em um requisito no rfc2616. Esse requisito é eliminado no rfc7231 e o rfc7231 também introduz o requisito de que os redirecionamentos 307 não devem alterar o método de solicitação (que você mencionou na sua cotação no final da sua resposta).
Nibarius 22/10
Observe que, de acordo com tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "Os códigos de redirecionamento HTTP 301-306 NÃO DEVEM ser usados, a menos que o provedor de serviços esteja ciente de que o cliente é de fato um usuário - agent "Parece que os serviços ReSTful devem usar 308 em vez de 301. No entanto, este é apenas um rascunho.
Bruce Adams
49

Encontrei uma boa explicação nesta página aqui .

As situações mais simples da WWW são transações "idempotentes", ou seja, aquelas que podem ser repetidas sem causar nenhum dano. Normalmente, essas transações são "GET", porque são recuperadas referências de URL simples (por exemplo, href = ou src = atributos em HTML) ou porque são envios de formulários usando o método GET. O redirecionamento de uma transação desse tipo é direto e não há perguntas: o cliente recebe a resposta de redirecionamento, incluindo um cabeçalho Location: que especifica o novo URL, e o cliente reage a ele reemitindo a transação para o novo URL. Há uma diferença entre os diferentes códigos de status 30x associados a esses redirecionamentos em sua capacidade de cache implícita, mas, caso contrário, eles são basicamente semelhantes (301 e 302) em resposta às solicitações GET.

As transações POST são diferentes, pois são definidas como não-idempotentes (como pedir uma pizza, votar ou o que for) e não devem ser arbitrariamente repetidas.

As especificações do protocolo HTTP foram projetadas para levar em consideração essa distinção: o método GET é definido como inerentemente idempotente, enquanto o método POST é definido como, pelo menos potencialmente, não idempotente; as especificações exigem uma série de precauções a serem tomadas pelos agentes clientes (como navegadores) para proteger os usuários contra (re) enviar inadvertidamente uma transação POST que eles não pretendiam ou enviar um POST em um contexto que eles não desejariam .

Embora eu não seja fã de restringir os usuários tecnicamente para impedir que causem problemas indesejados ou causem danos indesejados aos seus aplicativos, posso entender o ponto e faz sentido.

Falcão
fonte
grande parte do raciocínio vai para os dias em que os intertubos eram lentos e pouco confiáveis ​​(que ainda existem em muitos locais do mundo). Lembro-me claramente de quando eu usava a discagem e seria desconectada aleatoriamente sempre que alguém pegava o telefone. Era melhor recarregar a página e ver em que estado estava o servidor do que reenviar as coisas e correr o risco de executar a mesma ação duas vezes.
precisa saber é o seguinte
@ Falcon, Aumentar o "contador de visitantes" seria considerado não idempotente? Se assim for, quase Não há sites estes dias fazer idempotent GETs ...
Pacerier
@ Pacerier: Normalmente, o idempotente é interpretado como "idempotente de uma maneira significativa", por exemplo, comprando o mesmo item duas vezes, não marcando duas visitas. Caso contrário, você estaria certo. Mas, na verdade, a especificação deveria exigir que os servidores fossem significativamente idempotentes quando necessário, como incorporar um ID na página para evitar duplicações - não exigindo que o navegador fizesse ao usuário uma pergunta que ele não tem como responder com precisão. Independentemente disso, impedir o redirecionamento de um POST não afeta a idempotência; é simplesmente uma mensagem dizendo que o destino da solicitação está realmente lá.
Lawrence Dol
Não vejo como isso faz sentido para esse raciocínio. Digamos que eu esteja no site do banco Chase e envie um formulário. Eu já concordei / confiei neles. Portanto, se eles precisam redirecionar esses dados para outra página, por que eu teria que concordar novamente. Ou outro exemplo, diga que sou uma pessoa que desativa o JavaScript por padrão. Um dia, preencho um aplicativo de hipoteca on-line e, quando envio o formulário, ele apresenta erros. Seria ótimo se o aplicativo pudesse redirecionar (com POST) para a página que acabei de preencher para preencher previamente os dados.
b01
@Flacon, preciso de prova de que restringir um redirecionamento com POST pode impedir o caos em qualquer aspecto. Como primeiro preciso confiar no aplicativo com meus dados, eles podem fazer o que quiserem com ele depois que tiverem os dados. E não acho que os redirecionamentos sejam mais vulneráveis ​​do que os solicitados no POST.
2201:
3

GET (e alguns outros métodos) são definidos como 'SEGURO' na especificação http ( RFC 2616 ):

9.1.1 Métodos seguros

Os implementadores devem estar cientes de que o software representa o usuário em suas interações pela Internet e devem ter cuidado para permitir que o usuário esteja ciente de quaisquer ações que possa executar que possam ter um significado inesperado para si ou para outros.

Em particular, foi estabelecida a convenção de que os métodos GET e HEAD NÃO DEVEM ter o significado de tomar uma ação diferente da recuperação. Esses métodos devem ser considerados "seguros". Isso permite que os agentes do usuário representem outros métodos, como POST, PUT e DELETE, de uma maneira especial, para que o usuário fique ciente do fato de que uma ação possivelmente insegura está sendo solicitada.

Naturalmente, não é possível garantir que o servidor não gere efeitos colaterais como resultado da execução de uma solicitação GET; de fato, alguns recursos dinâmicos consideram isso um recurso. A distinção importante aqui é que o usuário não solicitou os efeitos colaterais, portanto, não pode ser responsabilizado por eles.

Isso significa que uma solicitação GET nunca deve ter conseqüências sérias para o usuário, além de ver algo que ele pode não querer ver, mas uma solicitação POST pode alterar um recurso importante para eles ou para outras pessoas.

Embora isso tenha mudado com o JavaScript, tradicionalmente havia interfaces de usuário diferentes - os usuários podiam acionar solicitações GET clicando nos links, mas precisavam preencher um formulário para acionar uma solicitação POST. Eu acho que os designers de HTTP estavam interessados ​​em manter a distinção entre métodos seguros e não seguros.

Também não acho que seja necessário redirecionar para um POST. Presumivelmente, qualquer ação que precise ser executada chamando uma função no código do servidor ou, se for necessário, em um servidor diferente, em vez de enviar um redirecionamento contendo uma URL para o POST do navegador, o servidor poderia fazer uma solicitação para o próprio servidor, agindo como um proxy para o usuário.

bdsl
fonte