Ответ 304 не устанавливает пользовательский заголовок для apache с mod_headers - PullRequest
4 голосов
/ 08 мая 2011
<VirtualHost *:80>
    ServerAdmin webmaster@dev.dom.com
    DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
    ServerName dev.dom.com
    ServerAlias dev.dom.com
    ErrorLog "logs/dev.dom.com-error.log"
    CustomLog "logs/dev.dom.com-access.log" common
    PassEnv CLUSTER
    Header always set X-Cluster "%{CLUSTER}e"
</VirtualHost>

Вот моя конфигурация. У меня есть переменная окружения, которая сообщает мне, в каком кластере я нахожусь, и которая передается в качестве заголовка в X-Cluster. Это возвращает штраф для ответа 200 или 404, но ответ 304 Not Modified никогда не возвращает заголовок, даже если он возвращает другие соответствующие заголовки Apache.

Как мне установить заголовок во время ответа 304?

Ответы [ 2 ]

7 голосов
/ 24 июля 2013

Согласно текущей спецификации HTTP, ответ 304 Not Modified не должен возвращать заголовки объекта (за исключением нескольких конкретных исключений). Цитирование из раздела 10.3.5 RFC 2616 :

Если условный GET использовал надежный валидатор кэша, ответ НЕ ДОЛЖЕН включать другие заголовки объекта. В противном случае (то есть условный GET использовал слабый валидатор), ответ НЕ ДОЛЖЕН включать в себя другие заголовки объекта; это предотвращает несоответствия между кэшированными телами сущностей и обновленными заголовками.

И, к сожалению, все заголовки расширений классифицируются как заголовки сущностей .

Однако, заглядывая в будущее, в проекте спецификации HTTPbis, который призван заменить RFC 2616, правила гораздо более мягкие. Цитирование из раздела 4.1 спецификации условных запросов :

Поскольку целью ответа 304 является минимизация передачи информации если получатель уже имеет одно или несколько кэшированных представлений, отправителю НЕ СЛЕДУЕТ генерировать метаданные представления, отличные от перечисленные выше поля, если только метаданные не существуют для руководящие обновления кеша.

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

Тем не менее, независимо от того, что написано в этих спецификациях, вам все равно придется иметь дело с тем, что может поддерживать Apache. И из того, что я видел в исходном коде, пользовательские заголовки все еще не поддерживаются в ответе 304.

Место фильтрации заголовков находится в функции ap_http_header_filter в файле / modules / http / http_filters.c :

Более конкретно, этот код:

if (r->status == HTTP_NOT_MODIFIED) {
    apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
                 (void *) &h, r->headers_out,
                 "Connection",
                 "Keep-Alive",
                 "ETag",
                 "Content-Location",
                 "Expires",
                 "Cache-Control",
                 "Vary",
                 "Warning",
                 "WWW-Authenticate",
                 "Proxy-Authenticate",
                 "Set-Cookie",
                 "Set-Cookie2",
                 NULL);
}

При возврате ответа «Не изменено» (304) приведенный выше список заголовков является единственным пропущенным (кроме нескольких автоматически сгенерированных заголовков, таких как Дата и Сервер ). И из того, что я вижу, не представляется простым способ подключиться к этому коду, чтобы изменить поведение.

Суть в том, что в настоящее время это невозможно в Apache. По крайней мере, один отчет об ошибках запрашивает поддержку других заголовков, но это специально для заголовков CORS. Однако, если повезет, это может побудить их быть более открытыми для поддержки пользовательских заголовков в целом.

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

Просто найдите имена заголовков, которые вы хотите заменить, в каталоге bin Apache (в Windows вы должны найти их в libhttpd.dll ). Затем используйте двоичный редактор для замены строки с нулевым символом в конце новым именем заголовка (конечно, она должна быть такой же длины или короче, чем заголовок, который вы заменяете).

Я не знаю о других операционных системах, но я проверил это на Windows, и, похоже, оно работает. Это, очевидно, ужасный взлом, но если вы достаточно отчаялись, вы можете подумать, что это вариант.

1 голос
/ 18 ноября 2011

Apache явно запрещает изменять заголовки ответа в ответе 304 для соответствия спецификации http. Имя этого типа ответа "Не изменено". Вы можете изменить это поведение, используя архитектуру фильтров Apache, написав собственный модуль или, возможно, с помощью mod_perl, но, скорее всего, это неправильно.

...