Re: proxy cache key и fastcgi cache key

Gena Makhomed gmm at csdoc.com
Fri Jan 10 23:06:00 UTC 2014


On 11.01.2014 0:17, Валентин Бартенев wrote:

>>>>>>>> Кому интересно почитать, подробней вот ссылка.
>>>>>>>> http://habrahabr.ru/post/166855/
>> ...
>>>> $host
>>>> in this order of precedence: host name from the request line, or host
>>>> name from the “Host” request header field, or the server name matching a
>>>> request
>> ...
>>> Единственный правильный способ: пойти в IETF с предложением исправить
>>> соответствующие RFC, которые в том числе оговаривают, что следует делать
>>> при получении нескольких заголовков Host, ну а потом уже сюда.
>>
>> с RFC то как раз все в порядке: "network location of the URI
>> (authority) MUST be transmitted in a Host header field",
>> только вот nginx не соответствует этим требованиям...
>>
>> http://tools.ietf.org/search/rfc2616#section-5.1.2
...
> Если почитать внимательнее, то приведенные требования относятся к клиенту.
> Понятно, что сервер в принципе не может влиять на то, что transmitted в
> запросе.

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

В тот момент, когда nginx делает http запрос к удаленному
серверу он выступает в роли клиента. поэтому я и цитировал 5.1.2

а дальше, получив ответ от удаленного сервера он с этим ответом
делает разные интересные вещи, например, сканирует его на предмет
ssi-директив, или пропускает через свои sub/addition/и т.п. модули.
и то, что получится в результате - складывает в файл кеша на диске,
и после дополнительной цепочки преобразований - отправляет то,
что получилось в результате как ответ на запрос своего клиента.

например, если исходный запрос от клиента к nginx был

GET http://good-site.com/pub/WWW/TheProject.html HTTP/1.1
Host: bad-site.com

содержимое заголовка Host: согласно 5.2.1 должно игнорироваться,
адрес хоста в этом случае: good-site.com

а согласно требований 5.1.2 - network location of the URI (authority) 
MUST be transmitted in a Host header field, то есть исходящий запрос
должен быть

GET /pub/WWW/TheProject.html HTTP/1.1
Host: good-site.com

nginx же в настройке по-умолчанию не соответсвует RFC,
и вместо требуемого значения пишет в заголовок Host:
значение переменной $proxy_host

Теперь рассмотрим вариант связи с backend`ом по протоколу FastCGI,
но поскольку у нас большой и сложный сайт сделаем два фронтенда:

1) основной nginx frontend
2) nginx frontend на хосте backend`а
3) backend, работающий по протоколу FastCGI.

запрос от клиента проходит цепочку (1)->(2)->(3).
поскольку между (1) и (2) используется протокол http,
то согласно требований 5.1.2 и 5.2.1 на (2) запрос приходит
в виде

GET /pub/WWW/TheProject.html HTTP/1.1
Host: good-site.com

не смотря на то, что в исходном запросе
от клиента был игнорируемый заголовок Host: bad-site.com

а дальше - все просто. В соответствии с требованиями
спецификации протокола FastCGI - nginx записывает в переменную
HTTP_HOST значение good-site.com.

точнее, он ДОЛЖЕН так делать, согласно требований HTTP протокола
прямо из коробки, без какой-либо дополнительной настройки.

Эта схема работает одинаково вне зависимости от количества
промежуточных серверов между nginx frontend и backend.

точнее, ДОЛЖНА работать одинаково,
вне зависимости от количества промежуточных серверов.

если в случае отсутствия промежуточных серверов nginx ведет себя
не так, - то это BUG, ибо в случае, когда на nginx frontend
приходит запрос в виде absoluteURI, - тогда "Any Host header
field value in the request MUST be ignored".
nginx этого по каким-то причинам не делает.

хотя согласно требований RFC - обе эти формы записи:

GET http://good-site.com/pub/WWW/TheProject.html HTTP/1.1

и

GET /pub/WWW/TheProject.html HTTP/1.1
Host: good-site.com

полностью эквивалентны между собой. и nginx имеет
полное право и даже обязанность трансформировать
запрос с absoluteURI в запрос с relativeURI
и network location of the URI (authority)
MUST be transmitted in a Host header field.

=============================================================

> Что касается сервера, написано буквально секцией ниже:
> http://tools.ietf.org/search/rfc2616#section-5.2
>
> 5.2 The Resource Identified by a Request
>
>     The exact resource identified by an Internet request is determined by
>     examining both the Request-URI and the Host header field.
>
>     An origin server that does not allow resources to differ by the
>     requested host MAY ignore the Host header field value when
>     determining the resource identified by an HTTP/1.1 request. (But see
>     section 19.6.1.1 for other requirements on Host support in HTTP/1.1.)
>
>     An origin server that does differentiate resources based on the host
>     requested (sometimes referred to as virtual hosts or vanity host
>     names) MUST use the following rules for determining the requested
>     resource on an HTTP/1.1 request:
>
>     1. If Request-URI is an absoluteURI, the host is part of the
>       Request-URI. Any Host header field value in the request MUST be
>       ignored.
>
>     2. If the Request-URI is not an absoluteURI, and the request includes
>       a Host header field, the host is determined by the Host header
>       field value.
>
>     3. If the host as determined by rule 1 or 2 is not a valid host on
>       the server, the response MUST be a 400 (Bad Request) error message.
>
>     Recipients of an HTTP/1.0 request that lacks a Host header field MAY
>     attempt to use heuristics (e.g., examination of the URI path for
>     something unique to a particular host) in order to determine what
>     exact resource is being requested.
>
> Ровным счетом так nginx и поступает, если передан absoluteURI, то виртуальный
> сервер определяется по нему, а заголовок Host игнорируется.

Та часть nginx, которая работает в режиме сервера определяет Host
правильно. И правильно сохранет его в свою переменную $host.

Но дальше в нарушение RFC вместо $host зачем-то используется $http_host
не смотря на прямой запрет: Any Host header field value in the request 
MUST be ignored.

А несоответствие требованиям RFC 2616 - это ведь BUG, верно?

-- 
Best regards,
  Gena



Подробная информация о списке рассылки nginx-ru