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