Dlaczego HTTP nie ma przekierowania POST?

162

Przekierowania HTTP są wykonywane za pomocą kodów HTTP 301 i 302 (być może także innych kodów) oraz pola nagłówka znanego jako „Lokalizacja”, które ma adres nowego miejsca, do którego należy przejść. Jednak przeglądarki zawsze wysyłają żądanie „GET” na ten adres URL.

Jednak wiele razy musisz przekierować użytkownika do innej domeny za pomocą POST (na przykład płatności bankowe). Jest to powszechny scenariusz i naprawdę wymaganie. Czy ktoś wie, dlaczego tak powszechny wymóg został pominięty w specyfikacji HTTP? Obejściem tego problemu jest wysłanie formularza (z parametrami w ukrytych polach) z działaniem ustawionym na lokalizację docelową (wartość pola nagłówka Lokalizacja ) i użycie setTimeoutdo przesłania formularza do lokalizacji docelowej.

Saeed Neamati
źródło
1
Czy szukasz kodu stanu 307? Zobacz moją odpowiedź poniżej.
David Ruttka,

Odpowiedzi:

180

W HTTP 1.1 faktycznie znajduje się kod statusu ( 307 ), który wskazuje, że żądanie powinno zostać powtórzone przy użyciu tej samej metody i danych pocztowych .

Jak powiedzieli inni, istnieje tutaj możliwość niewłaściwego użycia , co może być powodem, dla którego wiele ram trzyma się 301 i 302 w swoich abstrakcjach. Jednak przy odpowiednim zrozumieniu i odpowiedzialnym użytkowaniu powinieneś być w stanie osiągnąć to, czego szukasz.

Należy zauważyć, że zgodnie z w3.org ciemno , gdy METHODnie jest HEADlub GET, aplikacje klienckie powinny skłonić użytkownika przed ponownym wykonaniem wniosku w nowej lokalizacji. Powinieneś także podać notatkę i mechanizm awaryjny dla użytkownika, na wypadek gdyby stare programy klienckie nie były pewne, co zrobić z 307.

Za pomocą tego formularza:

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

A Test307.aspx po prostu zwraca 307 z lokalizacją: http://google.com , Chrome 13 i Fiddler potwierdzają, że „test = test” jest rzeczywiście opublikowany w Google. Oczywiście dalszą odpowiedzią jest 405, ponieważ Google nie pozwala na POST, ale pokazuje mechanikę.

Aby uzyskać więcej informacji, zobacz Lista kodów stanu HTTP i specyfikacja W3.org .

307 Tymczasowe przekierowanie (od HTTP / 1.1) W tej sytuacji żądanie należy powtórzyć z innym identyfikatorem URI, ale przyszłe żądania mogą nadal używać oryginalnego identyfikatora URI. 2 W przeciwieństwie do 303, metoda żądania nie powinna zostać zmieniona przy ponownym uruchomieniu pierwotnego żądania. Na przykład żądanie POST musi zostać powtórzone przy użyciu innego żądania POST.

David Ruttka
źródło
2
@DavidRuttka, Jaka jest obsługa przeglądarki w środowisku naturalnym ?
Pacerier
5
@DavidRuttka możesz zaktualizować swoją odpowiedź, aby wziąć pod uwagę rfc7231 (przestarzałe rfc2616). Monitowanie użytkownika jest oparte na wymaganiach zawartych w rfc2616. To wymaganie jest porzucone w rfc7231, a rfc7231 wprowadza również wymóg, że przekierowania 307 nie mogą zmieniać metody żądania (o której wspomniałeś w cytacie na końcu swojej odpowiedzi).
nibarius
Należy pamiętać, że zgodnie z tools.ietf.org/id/draft-hunt-http-rest-redirect-00.htmlKODY przekierowań HTTP 301-306 NIE POWINNY być używane, chyba że usługodawca wie, że klient jest w rzeczywistości użytkownikiem agent "Wygląda na to, że usługi ReSTful powinny korzystać z 308 zamiast 301. Jest to jednak tylko wersja robocza.
Bruce Adams,
49

Znalazłem dobre wyjaśnienie w tej stronie tutaj .

Najprostsze sytuacje w sieci WWW to transakcje „idempotentne”, tzn. Takie, które można powtarzać bez powodowania szkody. Zazwyczaj są to transakcje „GET”, ponieważ albo pobierają bezpośrednie odwołania do adresów URL (np. Href = lub src = atrybuty w HTML), albo dlatego, że są przesyłane za pomocą metody GET. Przekierowanie transakcji tego rodzaju jest proste i nie zadaje żadnych pytań: klient otrzymuje odpowiedź przekierowania, w tym nagłówek Location:, który określa nowy adres URL, a klient reaguje na to, wysyłając ponownie transakcję na nowy adres URL. Istnieje różnica między różnymi 30-krotnymi kodami stanu związanymi z tymi przekierowaniami w ich domyślnej pamięci podręcznej, ale poza tym są one zasadniczo podobne (301 i 302) w odpowiedzi na żądania GET.

Transakcje POST są różne, ponieważ są zdefiniowane jako zasadniczo nie idempotentne (takie jak zamówienie pizzy, oddanie głosu lub cokolwiek innego) i nie mogą być arbitralnie powtarzane.

Specyfikacje protokołu HTTP mają na celu uwzględnienie tego rozróżnienia: metoda GET jest z natury idempotentna, podczas gdy metoda POST jest zdefiniowana jako, co najmniej potencjalnie, niebędąca idempotentna; specyfikacje wymagają, aby agenci klienta (tacy jak przeglądarki) podjęli szereg środków ostrożności w celu ochrony użytkowników przed nieumyślnym (ponownym) przesłaniem transakcji POST, której nie zamierzali, lub przedłożeniem POST w kontekście, którego nie chcieliby .

Chociaż nie jestem fanem ograniczania użytkowników pod względem technicznym, aby zapobiec powodowaniu niechcianego chaosu lub wyrządzaniu niepożądanej szkody ich aplikacjom, rozumiem ten punkt i ma to sens.

Sokół
źródło
wiele argumentów pochodzi z czasów, gdy tuby były powolne i zawodne (które wciąż znajdują się w wielu miejscach na świecie). Wyraźnie pamiętam, kiedy korzystałem z połączenia telefonicznego i losowo byłem rozłączany za każdym razem, gdy ktoś inny odbierał telefon. Lepiej było ponownie załadować stronę i zobaczyć, w jakim stanie był serwer, niż ponownie przesłać rzeczy i zaryzykować dwukrotne wykonanie tej samej akcji.
zzzzBov,
@ Falcon, czy zwiększenie „licznika odwiedzin” byłoby uważane za niestosowne? Jeśli tak, to prawie żadna strona internetowa obecnie nie robi idempotentnych GET ...
Pacerier
@Pacerier: Zazwyczaj idempotent jest interpretowany jako „idempotentny w sensowny sposób”, na przykład kupowanie tego samego produktu dwa razy, a nie dwie wizyty. W przeciwnym razie miałbyś rację. Ale tak naprawdę specyfikacja powinna wymagać, aby serwery były znacząco idempotentne tam, gdzie to konieczne, takie jak osadzanie identyfikatora na stronie, aby zapobiec duplikowaniu - nie wymagając od przeglądarki zadawania użytkownikowi pytania, na które nie ma odpowiedzi z jakąkolwiek dokładnością. Niezależnie od tego, zapobieganie przekierowaniu testu POST nie wpływa na idempotencję; to po prostu komunikat informujący, że cel żądania rzeczywiście tam jest.
Lawrence Dol
Nie rozumiem, jak to ma sens w tym rozumowaniu. Powiedz, że jestem na stronie banku Chase i przesyłam formularz. Już je zgodziłem / zaufałem. Więc jeśli muszą przekierować te dane na inną stronę, dlaczego miałbym się ponownie zgadzać. Lub inny przykład: powiedz, że jestem osobą, która domyślnie wyłącza JavaScript. Pewnego dnia zaczynam wypełniać aplikację hipoteczną online, a kiedy przesyłam formularz, zawiera błędy. Byłoby wspaniale, gdyby aplikacja mogła przekierowywać (za pomocą POST) na stronę, którą właśnie wypełniłem, aby wstępnie wypełnić dane.
b01
@ Flacon, potrzebuję dowodu, że ograniczenie przekierowania za pomocą POST może zapobiec chaosowi pod każdym względem. Ponieważ najpierw muszę ufać aplikacji przy użyciu moich danych, mogą oni robić z nią, co tylko chcą, kiedy będą mieli dane. I nie sądzę, że przekierowania są bardziej wrażliwe niż żądanie z POST.
b01
3

GET (i kilka innych metod) są zdefiniowane jako „SAFE” w specyfikacji http ( RFC 2616 ):

9.1.1 Bezpieczne metody

Wdrażający powinni być świadomi, że oprogramowanie reprezentuje użytkownika w jego interakcjach przez Internet, i powinni być ostrożni, aby pozwolić użytkownikowi być świadomym wszelkich działań, które mogą podjąć, które mogą mieć nieoczekiwane znaczenie dla nich samych lub innych osób.

W szczególności ustanowiono konwencję, że metody GET i HEAD NIE POWINNY mieć znaczenia innego niż odzyskanie. Metody te należy uznać za „bezpieczne”. Pozwala to agentom użytkownika na reprezentowanie innych metod, takich jak POST, PUT i DELETE, w specjalny sposób, dzięki czemu użytkownik jest informowany o tym, że żądane jest potencjalnie niebezpieczne działanie.

Oczywiście nie można zapewnić, że serwer nie generuje skutków ubocznych w wyniku wykonania żądania GET; w rzeczywistości niektóre zasoby dynamiczne uważają tę funkcję. Ważnym rozróżnieniem jest tutaj to, że użytkownik nie zażądał skutków ubocznych, dlatego nie może być pociągnięty do odpowiedzialności za nie.

Oznacza to, że żądanie GET nigdy nie powinno mieć poważnych konsekwencji dla użytkownika, poza tym, że zobaczy coś, czego może nie chcieć zobaczyć, ale żądanie POST może zmienić zasób, który jest dla niego ważny lub dla innych osób.

Chociaż zmieniło się to w JavaScript, tradycyjnie istniały różne interfejsy użytkownika - użytkownicy mogli wywoływać żądania GET, klikając linki, ale musieli wypełnić formularz, aby wywołać żądanie POST. Myślę, że projektanci HTTP chcieli zachować rozróżnienie między metodami bezpiecznymi i niezabezpieczonymi.

Nie sądzę też, aby kiedykolwiek konieczne było przekierowanie do POST. Wszelkie działania, które należy wykonać, można przypuszczalnie wykonać przez wywołanie funkcji w kodzie serwera lub, jeśli trzeba to zrobić na innym serwerze, zamiast wysyłać przekierowanie zawierające adres URL przeglądarki do POST na serwer może wysłać zapytanie do tego samego serwera, działając jak proxy dla użytkownika.

bdsl
źródło