Как стать автором
Обновить

Комментарии 79

Интересную конечно тему подняли. Теперь стоит думать, что и где применять
>>есть вероятность нарваться на юзер-агента, который чтит спецификацию и выдаст предупрежление.

Пока про такой юзер-агент не слышал. Как появится — будем решать проблему :)
Я тоже. Но есть вероятность, что они появятся, например, среди мобильных приложений. В любом случае, лучше быть в курсе=)
Да никто не будет делать такое. Везде нормально редиректится, а в новом продукте не будет? Кто после этого будет его использовать? :)
А так же (к автору поста):
> Использовать 303, тогда старые клиенты не поймут, что от них хотят.
это какие, например?
Например:
Opera младше 4.0,
Internet Explorer младше 4.0

Может для кого-то критична поддержка и этих браузеров=)
В таком случае, при всей моей романтической любви к PC-антиквариату, «следовать стандарту и использовать 303 или заботиться о совместимости со старыми клиентами и использовать 302?» кажется мне вопросом из компетенции капитана Очевидность.
Например, Zend_Http_Client из ZF с включенной опцией strict_redirects, которая, кстати говоря, по умолчанию выключена.
Мне кажется лишним выносить подобную логику в PHP (или любой другой серверный язык), выдачей «правильного» кода должен заниматься веб-сервер, когда увидит заголовок Location, если это действительно может на что-то повлиять (поскольку Apache отправляет 302, вероятно, это-таки ни на что не влияет :)). Так-то!
Ну прям уж) Не должен сервер это делать, вы что. Что значит «правильный код»? Это должно приложение решать — какой код возврата «правильный», это прикладное понятие, а не протокольное.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Не думаю что return будет корректным. В фреймворках обычно бросается некий Redirect_Exception, который обрабатывается контроллером (корректно завершается работа). А если контроллера, как такового, нет то die() или exit именно то что нужно.
НЛО прилетело и опубликовало эту надпись здесь
Ох, озадачили. Фреймворк это набор компонентов, с уже решенными типичными (и не очень) задачами а также облегчающие и ускоряющие разработку. Например ZF, Symfony

Или это шутка? )
это тролль
НЛО прилетело и опубликовало эту надпись здесь
табличку надо было по-больше
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
это для чувства глубокого удовлетворения ;)
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
В Опере можно отключить редиректы и я часто это делаю для отладки.
НЛО прилетело и опубликовало эту надпись здесь
Яваскрипт мерзкий убрали бы…
Тогда уж было бы правильным ввести условие для header($_SERVER['SERVER_PROTOCOL']." 303 See Other").
Чтобы при $_SERVER['SERVER_PROTOCOL']=='HTTP/1.0' возвращался 302-й код.
Неужели так сложно сделать защиту от повторного постинга без редиректа?
Всё же не для этого ИМХО редиректы придуманы.
да легко. например в форму внедряется скрытый ключ…
НЛО прилетело и опубликовало эту надпись здесь
Да, про 303 конечно соглашусь — ваша правда.

Хотя мне как-то ближе способ с дополнительным уникальным скрытым полем — он ко всему прочему от ботов защищает.
НЛО прилетело и опубликовало эту надпись здесь
ещё помогает задизэблить кнопку после нажатия
НЛО прилетело и опубликовало эту надпись здесь
а сейчас это такая большая редкость?
Если потом вернуться кнопкой «Back», то кнопка окажется заблокированной, и придется перезагружать страницу, чтобы ее разблокировать.
НЛО прилетело и опубликовало эту надпись здесь
Да, вы совершенно правы — это ещё один аргумент чтобы отказаться от редиректа в пользу скрытого поля :)
НЛО прилетело и опубликовало эту надпись здесь
Совершенно верно. Но в топике шла речь именно о повторной отправке данных.
НЛО прилетело и опубликовало эту надпись здесь
Ну, а откуда возьмется скрытое, сразу поле после того, как юзер сабмитил форму, если страница еще не успела загрузиться снова?
Скрытое поле генерится *до* сабмита формы и передаётся вместе с ней.
Если сервер видит что такое значение ему уже передавали — даёт отлуп.
Я имел ввиду вот этот момент:
>иногда пользователи успевают несколько раз отправить форму (кликая по кнопке в ожидании)
То есть если по вашему, то все равно нужно генерить яваскриптом либо новое значение для хайдена, либо дисэблить кнопку.
Однако, редирект — это более кошерно.
Значение генерится не на клиенте, а на сервере. Второй раз ничего генерить как раз не нужно — мы эту форму второй раз принимать не хотим.
Черт, даже стыдно, что для меня пришлось разжевывать, но буду убеждать себя, что это все из-за сложного дня, а не из-за того, что тупею.
В том-то и дело что не хотим, и обязательно скажем об этом пользователю выведя ошибку вместо красивой странички с успешной регистрацией :)
оно там было с самого начала, с произвольным значением — если запросы приходят с одинаковыми значениями — нужно игнорировать все, кроме первого.
Второй вариант — брать не произвольные, а известные значения для этого поля, чтобы сервер знал, какую форму он сгенерил, а какую — чужой дядя.
Отказываться от редиректа все-таки не надо.
С редиректом для пользователя сохраняется возможность свободно гулять по истории без предупреждений броузера «сейчас вы повторно отправите какие-то данные».

Т.е. использовать POST запросы только как setter'ы (что-то меняющие на стороне сервера, но ничего не отображающие), а GET — как getter'ы (только отображающие, но никогда не меняющие ничего на стороне сервера) — идеологически правильно.

Более того, если мы переходим по какому-то специальному урлу (линк с картинкой кнопки) и при этом что-то меняется в даных на стороне сервера, правильно и после этого сделать редирект.
Согласен. crud далеко не худший способ организации веб-приложения.
для бота не проблема запросить форму с уникальным скрытым полем перед отправкой. это скорее защита от CSRF.
Это если он не совсем тупой.
А большинство ботов (по крайней мере те, которые мне пытаются досаждать) — совсем тупые.
Отправлять форму ajax-запросом, если включен js.
Если автор поста проведет тестирование различных браузеров в такой ситуации, мы ему будем очень благодарны. Может быть все браузеры корректно себя ведут?
Не понял вопроса. Что значит «все браузеры корректно себя ведут»? Все браузеры, поддерживающие HTTP/1.1 понимают 303 статус. И все популярные браузеры интерпретируют 302 статус как 303.
Совершенно верно, все браузеры не являющиеся музейными экспонатами, ведут себя корректно. Я думаю, это вопрос скорее академического характера.
скорее все браузеры ведут себя некорректно)
если есть спецификация, которая всеми выполняется как-то по другому, то наверное в спеке ошибка, а не в реализациях.
Есть какая практическая польза?
Через 10 лет ваше приложение продолжит работать правильно, в то время как у других бразуер будет спрашивать пользователя при переходе.
заметил, что в последнем сафари все чаще приходится тыкать на кнопку «если вас не перебросило автоматически тыкните сюда»… это оно? уже началось?
НЛО прилетело и опубликовало эту надпись здесь
это факт. потому что запостить повторно форму можно и умышленно.
НЛО прилетело и опубликовало эту надпись здесь
Врядли кто-то сейчас использует настолько старый клиент, который не поддерживает HTTP/1.0
Большинство сайтов хостятся на виртуальных хостингах, где без HOST заголовка не попадешь на нужный сайт.
тьфу…
* который не поддерживает HTTP/1.1
>Врядли кто-то сейчас использует настолько старый клиент, который не поддерживает HTTP/1.0
Если твои запросы в мир идут через squid, скажем, то они будут именно http/1.0. А таких ой как немало.
например, так: header('Location: /new/location', true, 303);

Например, не так. URL в Location должен быть абсолютным:

The field value consists of a single absolute URI.

Location = «Location» ":" absoluteURI

RFC 2616, п.14.30.
И правда:) Несмотря на то, что все браузеры поддерживают относительные URL'ы, по стандарту он должен быть абсолютным.
302 тоже все браузеры поддерживают.

уж если педантствовать — то во всем! ;)

кстати, если предположить, что некий сферический браузер в вакууме реализован строго по букве стандарта, то 302 не так страшно как относительный адрес.
есть еще одна проблема, на сей раз уже практическая.

ныне совершенно типична конфигурация сервера, когда фронтендом стоит nginx, проксирующий динамику на апач. Так вот проксирование делается по http/1.0; ответ http/1.1 будет просто некорректен (и может иметь крайне негативные последствия в виде отдачи chunked transfer encoding nginx-у, сделавшему запрос по 1.0 и этого никак не ожидающему); a http/1.0 303 формально некорректен, что будет практически — надо проверять.
НЛО прилетело и опубликовало эту надпись здесь
И прекрасно понимает http/1.1, пока это не касается работы с бэкендом.

Кстати host в 1.0 никаким образом не запрещается, в 1.1 же он просто обязателен
Хороший пример рака мозга, причем, заразного.

Итак, в вебе миллионы серверов с миллионами приложений, которые написаны с использованием 302. Старые клиенты, которые не знали про 303 постепенно отмирают, но приложения на серверах остаются и по-прежнему используют 302 вместо 303. И будут, потому что это вошло в образование веб-программистов и впитано с исходниками примеров из книжек.

Разработчики стандарта поступили не очень мудро. Нужно было быть ближе к народу и наделить 302 именно тем смыслом, который в него вкладывают те, кто его использует. А «старый 302» переименовать в 303-й =)

И все дела =)
Не надо париться по этому поводу :) Направление уже задано, и переделывать кучу софта смысла нет
задумывался об этом, читая rfc. но пришел к выводу, что фактически это бесполезная хрень. все клиенты понимают 302 и автоматически редиректят, поэтому инсинуации в rfc про 303 ни кого не волнуют. :)

«проблему» стоило бы порешать лишь в одном случае — если бы браузеры действительно запрашивали потдветждение юзера при 302 редиректе. но этого нет и никогда не будет, потому, что так устроен современный интернет. :)
Неожиданно столкнулся с проблемой: IE9 делает 302 редирект после POST тоже с помощью POST, т.е., если я правильно понимаю, он отрабатывает 302 статус как 307, в то время, как Firefox и Chrome отрабатывают 302 статус, как 303.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории