Золотое правило веб-разработчика

Правило

Золотое правило веб-разработчика звучит так:

Не отвечай на POST-запрос страницей.

На пост-запрос следует отвечать редиректом на страницу, где есть какой-то результат выполнения этого запроса, скажем, список комментариев, где новый комментарий уже запостился.

Когда на странице, полученной по посту, жмёшь F5, «Эксплорер» спрашивает, переотправить ли данные формы. Естественно, нормальный пользователь не понимает, почему у него это спрашивают, и почему нельзя просто перезагрузить страницу — вдруг там появились ещё комментарии? А нельзя потому, что у браузера просто нет никакого механизма получения страницы заново, кроме как повторением того же пост-запроса.

Неопытный пользователь жмёт «Отмену», но быстро обнаруживает, что это приводит только к печальному «Внимание: страница устарела». Так он постепенно научается всегда требовать переотправки формы, становясь, таким образом, опытным пользователем. Опера совершенно справедливо переотправляет форму, не задавая пользователю бессмысленных вопросов.

Естественно, что при переотправке формы комментарий запосчивается дважды, трижды или восемнадцать раз. Не стоит переживать по этому поводу; пусть переживает создатель такого кривого сайта.

Исключение

Отвечать на пост-запрос страницей можно только в экстремальной ситуации.

Например, пользователь запостил новый комментарий, а веб-сервер из-за какого-нибудь сбоя не смог связаться с сервером БД, чтобы этот комментарий добавить в базу. Сообщение об ошибке должно содержать текстарию с полным текстом комментария (чтобы не получилось, что всё написанное пропало) и объяснять человеку, что если его сообщение представляет для него ценность, он должен его скопировать и сохранить себе на память (или попробовать запостить позже).

Иными словами, нарушать это правило можно только тогда, когда иначе предотвратить потерю данных невозможно физически.

Дальше
11 комментариев
Артём Курапов 2008

Не соглашусь. Есть ещё исключения, например фильтрация табличных данных (без ajax’а). Или вы предлагаете сохранять в сессию и всё-равно делать редирект?

Илья Бирман 2008

Я не просто предлагаю, а я считаю это единственным допустимым вариантом :-)

Моё право нажать F5 священно.

Сохранять в сессию, кстати, ничего не нужно. Нужно просто делать редирект на lalala.php?filter=x¶m=y&order=z, где параметры — это то, что пришло из формы по посту.

Олег Французов 2008

!!комментарий запосчивается дважды, трижды или восемьнадцать раз!!

Опечатка?

Илья Бирман 2008

Да вот похоже, что нет. Спасибо, исправил.

Роман Парпалак 2008

Видимо, Илья зашел на очередной сайт, на котором после обработки POST-данных не было редиректа, разозлился на разработчиков и написал эту заметку :)

Денис Радченко 2008

Золотые слова. Всегда стараюсь не отдавать страницу по POST запросу, делаю self redirect

Андрей Руденко 2008

«Нужно просто делать редирект на lalala.php?filter=x¶m=y&order=z»

Для этого просто нужно указать метод GET в форме :)

«Иными словами, нарушать это правило можно только тогда, когда иначе предотвратить потерю данных невозможно физически.»

Т. е. при любой ошибке типа «не заполнено то-то обязательное поле», я правильно вас понял?

Илья Бирман 2008

Ошибки в форме — не повод нарушать правило. Нам ничто не мешает положить уже заполненные поля в сессию/куку и показать их оттуда, сделав нормальный редирект.

Я же написал, отвечаем страницей, только если физически невозможно иначе сохранить данные. А здесь-то не просто возможно, а проще простого это сделать.

Ilya RooT 2008

!!Моё право нажать F5 священно.!!

В последней бете Оперы вроде как ушли проблемы со сложными AJAX сайтами, например gmail.com или pusk.ru И зачем вам тогда F5? Или же вы по какой-нибудь причине недолюбливаете AJAX?

Илья Бирман 2008

Я не уловил связи вообще никакой.

Андрей Руденко 2008

Илья Бирман, во-первых, объясните что такое «физически невозможно иначе сохранить данные». Если вы их выводите, значит получили. А значит что мешает засунуть их в ту же сессию?

«Ошибки в форме — не повод нарушать правило»
Чье правило? Ваше? Почему бы и нет? При ошибках в форме куда логичнее никуда редирект не делать, так как текущий запрос не смог быть выполненным, соответсвенно следующее действие пользователя, это повторение этого запроса с новыми данными. Собственно никаких проблем с F5 это не вызовет, но приложение будет более понятным и структурированным.

Собственно то, что вы описали — есть часть понятия REST (RESTful-приложение соответственно). Только помимо этого там еще много очень клевых концептов. В общем то весь цивилизованный мир его и юзает.

Илья Бирман 2008

Моё правило. Вы заголовок заметки-то прочитайте. Я формулирую правило и указываю на исключение, которое мне приходит в голову. Безусловно, из того факта, что я его формулирую, не следует, что вы должны его соблюдать.

Сессия — недостаточно надёжно. В ней можно хранить введённый год рождения и домашний адрес. Если что-нибудь не сработает — ну придётся ввести заново. Это ж механическая работа. А вот хранить в сессии текст неотправившегося комментария — это опасно. Комментатор мог два часа его выдумывать, его жалко будет потерять просто из-за того, что у человека, например, выключены куки.

Проблему с F5 я описал в заметке, перечитайте её, пожалуйста.

clops 2008

Артём Курапов: любая фильтрация должна работать на основе GET запроса, дабы результат можно было зафигачить в закладки или «послать ссылку другу»

Андрей Руденко 2008

«Моё правило»

Я про то, что вы начинаете воспринимать его как аксиому, что не верно, хотя бы потому что само правило не верно. Что, конечно же, не означает, что вы им не можете пользоваться.

«Сессия — недостаточно надёжно»

Сохранять в сессию и редиректить предложили вы. Я как раз говорю, что никакой сессии (при ошибках в форме в частности и в любом другом случае в контексте этой темы) не нужно и никакого редиректа тоже.

«Проблему с F5 я описал в заметке»

Проблема сводится к «Естественно, что при переотправке формы комментарий запосчивается дважды, трижды или восемнадцать раз». Из чего вы выводите правило, что после каждого ПОСТ-запроса нужно делать редирект. Это не так. Редирект нужно делать только после запроса, изменившего/добавившего/удалившего какие-либо данные. Т. е. после PUT и DELETE запросов тоже (и пофиг, что в нынешних условиях они виртуальны). Если изменений не произошло, то пусть хоть 50 раз обновит, ничего не изменится. И да, данные не потеряются.

«перечитайте её, пожалуйста»

Я то ее прочитал. А вот вы про REST, кажется, нет. Почитайте. Конечно на PHP это не так уж и просто использовать удобно, но возможно что-то уже и поменялось в мире PHP-фрейморков в лучшую сторону.

Илья Бирман 2008

Я про REST, естественно, не читал, но я вам про него и не пишу ничего. Почему вы думаете, что я должен был про него прочитать-то?

Все те вещи, про которые вы пишете, цитируя меня не к месту, мы уже обсудили ранее, и я не понимаю, зачем к этому возвращаться. Я не хочу видеть вопроса о переотправке формы при нажатии F5, даже когда я в IE, независимо от того, потеряются данные или нет. Просто потому, что это мудацкий вопрос.

Андрей Руденко 2008

Винда вся полна мудацких вопросов, ее пользователи к этому привыкли :)

А про REST хорошо почитать, потому что все эти «золотые правила разработчика» уже сформулированы, описаны и при том в куда более полном и интересном виде. А что не менее важно, средства для их простого воплощения также уже есть. К тому же это обще-вебовский концепт, т. е. интересен даже без привязки к программированию.

Вячеслав Мацнев 2008

«Золотое правило веб-разработчика» — самое ценное, что я узнал за сегодняшнее утро.
Я не являюсь веб-разработчиком, поэтому «правило» не было для меня очевидным ранее.

Мои книги