Ответ 304 не устанавливает пользовательский заголовок для apache с mod_headers

<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 ответа

Решение

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

Согласно текущей спецификации 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, и это, кажется, работает. Это, очевидно, ужасный взлом, но если вы достаточно отчаянны, вы можете подумать, что это вариант.

Другие вопросы по тегам