Pull to refresh

Четыре зловещие шестнадцатеричные цифры на страницах ошибок — и как преодолеть их

Reading time2 min
Views3K
С этим загадочным глюком вы столкнётесь только при сочетании сразу нескольких условий.

Ваш сайт обслуживается Apache Server. (Это условие выполнить нетрудно: сейчас Apache — один из наиболее популярных вебосерверов.)

Ваш сайт также снабжён кэширующим сервером nginx. (Закупая shared-хостинг для небольшого сайта, вы можете до последней минуты ничего и не знать о том, что хостинговый провайдер, заботясь об экономии ресурсов, навесил nginx. Если, конечно, не полезете читать заголовки HTTP-отклика.)

Вы ставите какой-нибудь движок, работающий на PHP. (Например, CMS Drupal. Или, например, вики MediaWiki.)

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

И тогда приходят они. Четыре шестнадцатеричные цифры. Они появляются в коде страницы с описанием ошибки 404 (а также и 403), они стоят в этом коде перед «<!DOCTYPE», и поэтому многие браузеры (например, Firefox) стремятся отобразить их выше всего остального текста страницы — а значит, заметно разламывают дизайн, задуманный создателями CMS или вики:

3340
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
    <head>
          <title> … … …

В чём же дело?

Drupal, оказывается, вызывает функцию «drupal_set_header('HTTP/1.1 404 Not Found')» в случае ошибки 404. Да и в MediaWiki (даже в самой недавней версии 1.18 — я проверял) есть аналогичная ошибка. Вместо того, чтобы бережно проверять состояние суперглобальной переменной $_SERVER['SERVER_PROTOCOL'], движки наивно предполагают, что использование протокола HTTP версии 1.1 безопасно.

Между тем это далеко не так: nginx полагается на протокол HTTP версии 1.0 при общении с бэкэндом. В свою очередь, Apache Server, завидя протокол HTTP 1.1 в отклике PHP (да притом с отсутствующим заголовком Content-Length), переходит на HTTP 1.1 да передаёт ответ ломтями (chunks) и снабжает заголовком «Transfer-Encoding: chunked», но nginx это никак ужé не поможет.

Как решить проблему?

Очень просто. Достаточно в конфигурацию Apache Server (например, в файл .htaccess внутри каталога с движком вики или CMS) поместить две директивы, принуждающие Apache к безальтернативному использованию HTTP версии 1.0:

SetEnv force-response-1.0 1
SetEnv downgrade-1.0 1

Это позволяет тотчас же достигнуть желаемого.

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

Исправляю положение дел, выложив на Хабрахабре собственное изложение проблемы и пересказ действенного рецепта её решения.
Tags:
Hubs:
+72
Comments39

Articles

Change theme settings