Comments 79
Интересную конечно тему подняли. Теперь стоит думать, что и где применять
>>есть вероятность нарваться на юзер-агента, который чтит спецификацию и выдаст предупрежление.
Пока про такой юзер-агент не слышал. Как появится — будем решать проблему :)
Пока про такой юзер-агент не слышал. Как появится — будем решать проблему :)
Я тоже. Но есть вероятность, что они появятся, например, среди мобильных приложений. В любом случае, лучше быть в курсе=)
А так же (к автору поста):
> Использовать 303, тогда старые клиенты не поймут, что от них хотят.
это какие, например?
> Использовать 303, тогда старые клиенты не поймут, что от них хотят.
это какие, например?
Например:
Opera младше 4.0,
Internet Explorer младше 4.0
Может для кого-то критична поддержка и этих браузеров=)
Opera младше 4.0,
Internet Explorer младше 4.0
Может для кого-то критична поддержка и этих браузеров=)
Например,
Zend_Http_Client
из ZF с включенной опцией strict_redirects
, которая, кстати говоря, по умолчанию выключена.Мне кажется лишним выносить подобную логику в PHP (или любой другой серверный язык), выдачей «правильного» кода должен заниматься веб-сервер, когда увидит заголовок Location, если это действительно может на что-то повлиять (поскольку Apache отправляет 302, вероятно, это-таки ни на что не влияет :)). Так-то!
Не думаю что
return
будет корректным. В фреймворках обычно бросается некий Redirect_Exception
, который обрабатывается контроллером (корректно завершается работа). А если контроллера, как такового, нет то die()
или exit
именно то что нужно.Яваскрипт мерзкий убрали бы…
Тогда уж было бы правильным ввести условие для header($_SERVER['SERVER_PROTOCOL']." 303 See Other").
Чтобы при $_SERVER['SERVER_PROTOCOL']=='HTTP/1.0' возвращался 302-й код.
Чтобы при $_SERVER['SERVER_PROTOCOL']=='HTTP/1.0' возвращался 302-й код.
Неужели так сложно сделать защиту от повторного постинга без редиректа?
Всё же не для этого ИМХО редиректы придуманы.
Всё же не для этого ИМХО редиректы придуманы.
да легко. например в форму внедряется скрытый ключ…
Да, про 303 конечно соглашусь — ваша правда.
Хотя мне как-то ближе способ с дополнительным уникальным скрытым полем — он ко всему прочему от ботов защищает.
Хотя мне как-то ближе способ с дополнительным уникальным скрытым полем — он ко всему прочему от ботов защищает.
ещё помогает задизэблить кнопку после нажатия
Да, вы совершенно правы — это ещё один аргумент чтобы отказаться от редиректа в пользу скрытого поля :)
Ну, а откуда возьмется скрытое, сразу поле после того, как юзер сабмитил форму, если страница еще не успела загрузиться снова?
Скрытое поле генерится *до* сабмита формы и передаётся вместе с ней.
Если сервер видит что такое значение ему уже передавали — даёт отлуп.
Если сервер видит что такое значение ему уже передавали — даёт отлуп.
Я имел ввиду вот этот момент:
>иногда пользователи успевают несколько раз отправить форму (кликая по кнопке в ожидании)
То есть если по вашему, то все равно нужно генерить яваскриптом либо новое значение для хайдена, либо дисэблить кнопку.
Однако, редирект — это более кошерно.
>иногда пользователи успевают несколько раз отправить форму (кликая по кнопке в ожидании)
То есть если по вашему, то все равно нужно генерить яваскриптом либо новое значение для хайдена, либо дисэблить кнопку.
Однако, редирект — это более кошерно.
оно там было с самого начала, с произвольным значением — если запросы приходят с одинаковыми значениями — нужно игнорировать все, кроме первого.
Отказываться от редиректа все-таки не надо.
С редиректом для пользователя сохраняется возможность свободно гулять по истории без предупреждений броузера «сейчас вы повторно отправите какие-то данные».
Т.е. использовать POST запросы только как setter'ы (что-то меняющие на стороне сервера, но ничего не отображающие), а GET — как getter'ы (только отображающие, но никогда не меняющие ничего на стороне сервера) — идеологически правильно.
Более того, если мы переходим по какому-то специальному урлу (линк с картинкой кнопки) и при этом что-то меняется в даных на стороне сервера, правильно и после этого сделать редирект.
С редиректом для пользователя сохраняется возможность свободно гулять по истории без предупреждений броузера «сейчас вы повторно отправите какие-то данные».
Т.е. использовать POST запросы только как setter'ы (что-то меняющие на стороне сервера, но ничего не отображающие), а GET — как getter'ы (только отображающие, но никогда не меняющие ничего на стороне сервера) — идеологически правильно.
Более того, если мы переходим по какому-то специальному урлу (линк с картинкой кнопки) и при этом что-то меняется в даных на стороне сервера, правильно и после этого сделать редирект.
для бота не проблема запросить форму с уникальным скрытым полем перед отправкой. это скорее защита от CSRF.
Отправлять форму ajax-запросом, если включен js.
Если автор поста проведет тестирование различных браузеров в такой ситуации, мы ему будем очень благодарны. Может быть все браузеры корректно себя ведут?
Не понял вопроса. Что значит «все браузеры корректно себя ведут»? Все браузеры, поддерживающие HTTP/1.1 понимают 303 статус. И все популярные браузеры интерпретируют 302 статус как 303.
Совершенно верно, все браузеры не являющиеся музейными экспонатами, ведут себя корректно. Я думаю, это вопрос скорее академического характера.
Есть какая практическая польза?
Врядли кто-то сейчас использует настолько старый клиент, который не поддерживает HTTP/1.0
Большинство сайтов хостятся на виртуальных хостингах, где без HOST заголовка не попадешь на нужный сайт.
Большинство сайтов хостятся на виртуальных хостингах, где без HOST заголовка не попадешь на нужный сайт.
например, так: header('Location: /new/location', true, 303);
Например, не так. URL в Location должен быть абсолютным:
RFC 2616, п.14.30.
Например, не так. URL в Location должен быть абсолютным:
The field value consists of a single absolute URI.
Location = «Location» ":" absoluteURI
RFC 2616, п.14.30.
И правда:) Несмотря на то, что все браузеры поддерживают относительные URL'ы, по стандарту он должен быть абсолютным.
302 тоже все браузеры поддерживают.
уж если педантствовать — то во всем! ;)
кстати, если предположить, что некий сферический браузер в вакууме реализован строго по букве стандарта, то 302 не так страшно как относительный адрес.
уж если педантствовать — то во всем! ;)
кстати, если предположить, что некий сферический браузер в вакууме реализован строго по букве стандарта, то 302 не так страшно как относительный адрес.
есть еще одна проблема, на сей раз уже практическая.
ныне совершенно типична конфигурация сервера, когда фронтендом стоит nginx, проксирующий динамику на апач. Так вот проксирование делается по http/1.0; ответ http/1.1 будет просто некорректен (и может иметь крайне негативные последствия в виде отдачи chunked transfer encoding nginx-у, сделавшему запрос по 1.0 и этого никак не ожидающему); a http/1.0 303 формально некорректен, что будет практически — надо проверять.
ныне совершенно типична конфигурация сервера, когда фронтендом стоит nginx, проксирующий динамику на апач. Так вот проксирование делается по http/1.0; ответ http/1.1 будет просто некорректен (и может иметь крайне негативные последствия в виде отдачи chunked transfer encoding nginx-у, сделавшему запрос по 1.0 и этого никак не ожидающему); a http/1.0 303 формально некорректен, что будет практически — надо проверять.
Хороший пример рака мозга, причем, заразного.
Итак, в вебе миллионы серверов с миллионами приложений, которые написаны с использованием 302. Старые клиенты, которые не знали про 303 постепенно отмирают, но приложения на серверах остаются и по-прежнему используют 302 вместо 303. И будут, потому что это вошло в образование веб-программистов и впитано с исходниками примеров из книжек.
Разработчики стандарта поступили не очень мудро. Нужно было быть ближе к народу и наделить 302 именно тем смыслом, который в него вкладывают те, кто его использует. А «старый 302» переименовать в 303-й =)
И все дела =)
Итак, в вебе миллионы серверов с миллионами приложений, которые написаны с использованием 302. Старые клиенты, которые не знали про 303 постепенно отмирают, но приложения на серверах остаются и по-прежнему используют 302 вместо 303. И будут, потому что это вошло в образование веб-программистов и впитано с исходниками примеров из книжек.
Разработчики стандарта поступили не очень мудро. Нужно было быть ближе к народу и наделить 302 именно тем смыслом, который в него вкладывают те, кто его использует. А «старый 302» переименовать в 303-й =)
И все дела =)
Не надо париться по этому поводу :) Направление уже задано, и переделывать кучу софта смысла нет
задумывался об этом, читая rfc. но пришел к выводу, что фактически это бесполезная хрень. все клиенты понимают 302 и автоматически редиректят, поэтому инсинуации в rfc про 303 ни кого не волнуют. :)
«проблему» стоило бы порешать лишь в одном случае — если бы браузеры действительно запрашивали потдветждение юзера при 302 редиректе. но этого нет и никогда не будет, потому, что так устроен современный интернет. :)
«проблему» стоило бы порешать лишь в одном случае — если бы браузеры действительно запрашивали потдветждение юзера при 302 редиректе. но этого нет и никогда не будет, потому, что так устроен современный интернет. :)
Неожиданно столкнулся с проблемой: IE9 делает 302 редирект после POST тоже с помощью POST, т.е., если я правильно понимаю, он отрабатывает 302 статус как 307, в то время, как Firefox и Chrome отрабатывают 302 статус, как 303.
Sign up to leave a comment.
Редирект после POST запроса