Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: proxy cache key и fastcgi cache key
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 mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru
|