Боремся с сообщением о повторной отправке формы

26.06.2011
@LEXXX_NF

Итак, однажды я встраивал на сайт одну хитрую форму, состоящую из нескольких шагов. Если в этой форме заполнить не все обязательные поля, то будет выведено сообщение об ошибке и просьба нажать в браузере «назад» и заполнить-таки необходимые поля. Вот такое странное представление о юзабилити. Нехитрая команда «назад» прекрасно выполнялась на старом месте жительства формы, а вот на новом сайте (на битриксе), она вызывала подозрительное окошко вот такого вида:

  • в Firefox:

    To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.

  • в Chrom'е

    Для правильного отображения это страницы требуются введенные ранее данные. Вы можете отправить эти данные еще раз, однако при этом будет выполнен повтор всех выполненных ранее действий. Нажмите "Обновить", чтобы отправить данные повторно и отобразить страницу.

  • в IE это целый трактат

    Веб-страница просрочена

  • и только Opera искренне заботится о нервах пользователя и послушно грузит страницу из кэша, не задавая никаких лишних вопросов.

Что ж, давайте разбираться.

Из описания ошибки в FF и Chrome'е становится ясно, что возникает она при отправке формы. Если быть точнее, то ошибка возникает, если мы пытаемся вернуться на страницу, на которую изначально попали, используя post-запрос. Чтобы было понятнее, я нарисовал картинку:

Схема возникновения ошибки

А теперь самый интересный вопрос: почему ошибка возникает не всегда? Как я писал выше, на старом сайте можно было вернуться назад без всяких дурацких сообщений про повторную отправку. С подачи моего коллеги Антона, было установлено, что во всём виновато кэширование, а точнее, заголовки, регламентирующие кэширование в браузере. Оказывается, если заголовками запрещается кэширование страницы, и переход на неё изначально был сделан post-запросом, то просто так вернуться на неё уже не получится. Дальнейшие эксперименты показали, что во всём виноват один заголовок Cache-Control. Чтобы исправить ситуацию, достаточно просто убрать этот его.

Если вы, как и я, не властны над кодом, генерируемым CMS, то удалить этот заголовок нам поможет волшебный .htaccess. Файл со следующим содержимым надо положить в ту папку, где находится проблемная страница:

<ifModule mod_headers.c>
  Header unset Cache-Control
</ifModule>

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

Уф... я написал столько текста ради одной строчки в .htaccess, надо бы приучить себя к лаконичности.

#1
Denis227
10.10.2012 02:46
Я скопировал указанный Вами код в файл htaccess, и закинул его в папку с проблемным РНР-скриптом. Но проблема не решилась, подскажите что делать
#2
@LEXXX_NF
11.10.2012 01:13
Возможно, у вас нет модуля mod_headers в апаче. Проверьте через phpinfo. Если модуля действительно нет, то придётся решать проблему на стороне PHP: в версии 5.3 появилась функция header_remove - она может помочь. А если у вас нет модуля и PHP старый, то я от всей дущи желаю вам сменить хостера :)
#3
Denis227
14.10.2012 21:41
Сервер у меня локальный, денвер так сказать)
#4
@LEXXX_NF
14.10.2012 22:29
В денвере действительно нет модуля mod_headers.
Не лучше ли приблизить конфиг локального сервера к боевому, например, с помощью VMware? Вдруг там модуль есть и проблема не возникнет...
#5
Таня
02.01.2013 17:33
Спасибо, мне помогло)
#6
Евгений
21.08.2017 15:12
if(isset($_POST) && $_POST['sessid'] == $_SESSION['sessid'])

Писáть здесь

А еще у меня есть: