Чому HTTP не має переадресації POST?


162

Перенаправлення HTTP здійснюються за допомогою кодів HTTP 301 та 302 (можливо, також і інших кодів) та поля заголовка, відомого як "Місцезнаходження", яке має адресу нового місця. Однак браузери завжди надсилають запит "GET" на цю URL-адресу.

Однак багато разів потрібно перенаправляти користувача на інший домен через POST (наприклад, банківські платежі). Це загальний сценарій і справді вимога. Хтось знає, чому така специфічна вимога була знехтувана в специфікації HTTP? Вирішення завдання полягає в тому, щоб надіслати форму (з параметрами в прихованих полях) з дією, встановленою в цільове місце (значення поля заголовка Location ), і використовувати setTimeoutдля подання форми в цільове місце.


1
Чи є код коду 307, який ви шукаєте? Дивіться мою відповідь нижче.
Девід Руттка

Відповіді:


180

У HTTP 1.1 фактично існує код статусу ( 307 ), який вказує на те, що запит слід повторити, використовуючи той самий метод та розміщувати дані .

Як зазначають інші, тут існує потенція для нецільового використання, через що багато рамок у своїх абстракціях дотримуються 301 та 302. Однак при належному розумінні та відповідальному використанні ви повинні мати можливість досягти того, що шукаєте.

Зауважте, що згідно зі специфікацією W3.org , коли METHODнемає HEADабо GET, агенти користувача повинні сповістити користувача перед повторним виконанням запиту в новому місці. Ви також повинні надати примітку та механізм резервного копіювання для користувача, якщо старі агенти користувача не знають, що робити з 307.

Використовуючи цю форму:

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

А маючи Test307.aspx, просто поверніть 307 з адресою Location: http://google.com , Chrome 13 та Fiddler підтверджують, що "test = test" дійсно розміщено в Google. Звичайно, подальша відповідь - це 405, оскільки Google не дозволяє POST, але це показує механіку.

Для отримання додаткової інформації див. Список кодів HTTP-статусу та специфікацію W3.org .

307 Тимчасовий переадресацію (оскільки HTTP / 1.1) У цьому випадку запит слід повторити з іншим URI, але майбутні запити все ще можуть використовувати оригінальний URI. 2 На відміну від 303, метод запиту не слід змінювати при повторному виданні початкового запиту. Наприклад, запит POST повинен бути повторений, використовуючи інший запит POST.


2
@DavidRuttka, яка підтримка браузера в дикій природі ?
Pacerier

5
@DavidRuttka ви можете оновити свою відповідь, щоб врахувати rfc7231 (застаріло rfc2616). Запрошення користувача базується на вимозі в rfc2616. Ця вимога відмінена у rfc7231, а rfc7231 також вводить вимогу, щоб 307 переадресацій не повинні змінювати метод запиту (про що ви згадуєте в цитаті в кінці своєї відповіді).
nibarius

Зауважте, що відповідно до tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "Коди перенаправлення HTTP 301-306 НЕ БУДЬ застосовуватися, якщо постачальник послуг не знає, що клієнт насправді є користувачем- агент "Тож здається, що послуги ReSTful повинні використовувати 308 замість 301. Однак це лише чернетка.
Брюс Адамс

49

Я знайшов гарне пояснення на цій сторінці тут .

Найпростіші ситуації на WWW - це "ідентичні" транзакції, тобто ті, які можна повторити, не завдаючи шкоди. Зазвичай це транзакції "GET", або тому, що вони отримують прямі посилання URL-адрес (наприклад, href = або src = атрибути в HTML), або тому, що вони представляють форми, використовуючи метод GET. Перенаправлення такої транзакції є простим, і жодних питань не виникає: клієнт отримує відповідь про переадресацію, включаючи заголовок Location: Location, який вказує нову URL-адресу, а клієнт реагує на неї, повторно видаючи транзакцію на нову URL-адресу. Існує різниця між різними кодами статусу 30x, пов'язаними з цими перенаправленнями, у їх прихованій кешованості, але в іншому випадку вони в основному схожі (301 і 302) у відповідь на GET-запити.

Угоди POST різні, оскільки вони, в принципі, є неідентичними (наприклад, замовлення піци, голосування чи інше) і їх не можна повторювати довільно.

Специфікації протоколу HTTP розроблені для врахування цього розрізнення: метод GET визначений як такий, що за своєю суттю є ідентичним, тоді як метод POST визначений як мінімум потенційно неідентичний; специфікації вимагають дотримання ряду запобіжних заходів, які повинні вжити клієнтські агенти (наприклад, браузери) для захисту користувачів від ненавмисного (повторного) подання транзакції POST, яку вони не мали наміру, або подання POST у контекст, який вони не хотіли б. .

Хоча я не прихильник технічно обмежувати користувачів, щоб не допустити їх небажаного посягання чи заподіяння небажаної шкоди їх програмам, я можу зрозуміти, що це має сенс.


значна частина міркувань йде в ті часи, коли міжтрубки були повільними та ненадійними (які вони все ще є у багатьох місцях світу). Я чітко пам’ятаю, коли я користувався набором номерів і випадково відключався, коли хтось інший піднімав телефон. Краще було перезавантажити сторінку та побачити, у якому стані знаходиться сервер, ніж повторно подавати речі та ризикувати виконати одну й ту ж дію двічі.
zzzzBov

@Falcon, Чи вважатиметься збільшення "лічильника відвідувачів" не ідентичним? Якщо так, то майже жоден веб-сайт в цей час не робить
безсильних GETs

@Pacerier: Зазвичай idempotent інтерпретується як "ідентичний потенціал змістовно", наприклад, купуючи один і той же товар два рази, не припиняючи двох відвідувань. Інакше ви будете цілком праві. Але дійсно, специфікація повинна вимагати від серверів бути значущим ідентичним, де це необхідно, наприклад, вставляти ідентифікатор на сторінку, щоб запобігти дублюванню - не вимагаючи від браузера запитувати у користувача питання, на який вони не мають змоги відповісти з якоюсь точністю. Незалежно від того, запобігання перенаправлення POST не впливає на ідентифікацію; це просто повідомлення про те, що ціль запиту насправді там.
Лоуренс Дол

Я не бачу, як це має сенс для цих міркувань. Скажіть, я перебуваю на веб-сайті банку Chase, і я надсилаю форму. Я вже погодився / довірився їм. Тож якщо їм доведеться перенаправляти ці дані на іншу сторінку, чому б мені довелося погодитись ще раз. Або інший приклад: Скажіть, що я людина, яка вимикає JavaScript за замовчуванням. Одного разу я заходжу заповнювати іпотечну програму в Інтернеті, і коли я надсилаю форму, у неї є помилки. Було б чудово, якщо додаток може переспрямувати (з POST) на сторінку, яку я щойно заповнив, щоб попередньо заповнити дані.
b01

@Flacon, мені потрібні докази того, що обмеження переадресації з POST може запобігти хаосу в будь-якому відношенні. Оскільки я вперше повинен довіряти програмі мої дані, вони можуть робити все, що завгодно, коли вони отримають ці дані. І я не думаю, що переадресація є більш вразливою, ніж запит з POST.
b01

3

GET (та кілька інших методів) визначені як "БЕЗКОШТОВНИЙ" у специфікації http ( RFC 2616 ):

9.1.1 Безпечні методи

Виконавці повинні усвідомлювати, що програмне забезпечення представляє користувача у взаємодії через Інтернет, і повинні бути обережними, щоб користувач усвідомлював будь-які дії, які вони можуть вчинити, які можуть мати несподіване значення для себе та інших.

Зокрема, було встановлено, що методи GET і HEAD НЕ повинні мати значення для вжиття інших дій, ніж пошук. Ці методи слід вважати "безпечними". Це дозволяє користувачам-агентам представляти інші методи, такі як POST, PUT та DELETE, спеціальним чином, щоб користувач ознайомився з тим, що вимагається можлива небезпечна дія.

Природно, неможливо забезпечити, щоб сервер не генерував побічні ефекти в результаті виконання запиту GET; насправді деякі динамічні ресурси вважають цю особливість. Тут важливим є те, що користувач не вимагає побічних ефектів, тому не може бути відповідальним за них.

Це означає, що запит GET ніколи не повинен мати серйозних наслідків для користувача, крім того, щоб побачити те, що вони можуть не хотіти бачити, але POST-запит може змінити важливий для них ресурс або для інших людей.

Хоча це змінилося в JavaScript, традиційно існували різні інтерфейси користувача - користувачі могли запускати GET-запити, натискаючи посилання, але доведеться заповнити форму, щоб викликати POST-запит. Я думаю, що дизайнери HTTP прагнули зберегти відмінність між безпечними та небезпечними методами.

Я також не думаю, що коли-небудь слід перенаправлятись на пошту. Будь-яку дію, яку потрібно здійснити, можливо, можна здійснити за допомогою виклику функції в коді на стороні сервера, або якщо це потрібно зробити на іншому сервері, а не надсилати перенаправлення, що містить URL-адресу браузера на POST, на сервер може сам подати запит на цей сервер, діючи як проксі для користувача.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.