Re: Документация к директиве fastcgi_cache_key

2018-12-03 Пенетрантность Константин Ткаченко
пт, 30 нояб. 2018 г. в 13:36, Илья Шипицин :

> протоколы действительно разные.
> но выглядит так, что предложение Гены поможет написать документацию, более
> устойчивую к тупому копипасту (есть такой патерн, что глядя на пример
> документации на авторитетном сайте, его копируют)
>
> пт, 30 нояб. 2018 г. в 14:30, Gena Makhomed :
>
>> On 29.11.2018 21:02, Maxim Dounin wrote:
>>
>> > CGI и HTTP - это два разных протокола.  В последних вариациях на
>> > тему спецификации CGI записано, что на HEAD-запросы тело
>> > возвращать не надо (а если вдруг вернули - то сервер его должен
>> > поскипать), https://tools.ietf.org/html/rfc3875#section-4.3.3:
>> >
>> > The HEAD method requests the script to do sufficient processing to
>> > return the response header fields, without providing a response
>> > message-body.  The script MUST NOT provide a response message-body
>> > for a HEAD request.  If it does, then the server MUST discard the
>> > message-body when reading the response from the script.
>> >
>> > Однако на момент собственно появления и активного распространения
>> > CGI никаких подобных требований не существовало, см.
>> > https://www.w3.org/CGI/ и в частности
>> > https://tools.ietf.org/html/draft-robinson-www-interface-00.
>>
>> Там написано:
>>
>> REQUEST_METHOD
>>
>>This variable is specific to requests made with HTTP.
>>
>>The method with which the request was made, as described in
>>section 5.1.1 of the HTTP/1.0 specification [3].
>>
>>   http-method  = "GET" | "HEAD" | "POST" | extension-method
>>
>> "described in HTTP/1.0 specification" - написано где смотреть семантику.
>> А в HTTP/1.0 specification написано, что "server must not return any
>> Entity-Body in the response".
>>
>> CGI и HTTP - это два разных протокола, но первый ссылается на второй.
>> При этом CGI протокол не запрещает бекенду отвечать на HEAD-запросы
>> так, как этого требует от веб-сервера спецификация HTTP протокола.
>>
>> > И на
>> > практике я не встречал скрипты, которые бы отдельно обрабатывали
>> > HEAD-запросы.
>>
>> Но они есть.
>> И их поведение ничем не противоречит спецификации FastCGI протокола.
>>
>> >>> Речь про какие-то фреймворки, которые обрабатывают
>> >>> HEAD автоматически, не донося соответствующую информацию до кода?
>> >>> Или про какой-то стандартный софт, который не возвращает тело для
>> >>> HEAD-запросов?
>> >>
>> >> Какая разница, сам софт или фрейморк используемый софтом в каждом
>> >> конкретном случае обрабатывает HEAD запросы согласно требований RFC?
>> >
>> > Никакой.  Но с этой точки зрения так же нет разницы, что именно
>> > написано в примерах в описании директивы fastcgi_cache_key.
>>
>> Вы не против, если я создам на хабре статью, в которой напишу
>> про эту проблему с ошибочными примерами в документации nginx
>> к директиве fastcgi_cache_key и ее аналогам?
>>
>> --
>> Best regards,
>>   Gena
>>
>> ___
>> nginx-ru mailing list
>> nginx-ru@nginx.org
>> http://mailman.nginx.org/mailman/listinfo/nginx-ru
>
> ___
> nginx-ru mailing list
> nginx-ru@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-ru


Прошу прощения, что влезаю.
Есть статья Дмитрия Котерова от октября 2009 года, посвещенная кешированию
в nginx http://dklab.ru/chicken/nablas/56.html
Если механизм кеширование не сильно изменился, то данные там акутальные.

На хабре, конечно, охват аудитории больше будет, если там появится подобная
статья.
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: Документация к директиве fastcgi_cache_key

2018-11-30 Пенетрантность Илья Шипицин
протоколы действительно разные.
но выглядит так, что предложение Гены поможет написать документацию, более
устойчивую к тупому копипасту (есть такой патерн, что глядя на пример
документации на авторитетном сайте, его копируют)

пт, 30 нояб. 2018 г. в 14:30, Gena Makhomed :

> On 29.11.2018 21:02, Maxim Dounin wrote:
>
> > CGI и HTTP - это два разных протокола.  В последних вариациях на
> > тему спецификации CGI записано, что на HEAD-запросы тело
> > возвращать не надо (а если вдруг вернули - то сервер его должен
> > поскипать), https://tools.ietf.org/html/rfc3875#section-4.3.3:
> >
> > The HEAD method requests the script to do sufficient processing to
> > return the response header fields, without providing a response
> > message-body.  The script MUST NOT provide a response message-body
> > for a HEAD request.  If it does, then the server MUST discard the
> > message-body when reading the response from the script.
> >
> > Однако на момент собственно появления и активного распространения
> > CGI никаких подобных требований не существовало, см.
> > https://www.w3.org/CGI/ и в частности
> > https://tools.ietf.org/html/draft-robinson-www-interface-00.
>
> Там написано:
>
> REQUEST_METHOD
>
>This variable is specific to requests made with HTTP.
>
>The method with which the request was made, as described in
>section 5.1.1 of the HTTP/1.0 specification [3].
>
>   http-method  = "GET" | "HEAD" | "POST" | extension-method
>
> "described in HTTP/1.0 specification" - написано где смотреть семантику.
> А в HTTP/1.0 specification написано, что "server must not return any
> Entity-Body in the response".
>
> CGI и HTTP - это два разных протокола, но первый ссылается на второй.
> При этом CGI протокол не запрещает бекенду отвечать на HEAD-запросы
> так, как этого требует от веб-сервера спецификация HTTP протокола.
>
> > И на
> > практике я не встречал скрипты, которые бы отдельно обрабатывали
> > HEAD-запросы.
>
> Но они есть.
> И их поведение ничем не противоречит спецификации FastCGI протокола.
>
> >>> Речь про какие-то фреймворки, которые обрабатывают
> >>> HEAD автоматически, не донося соответствующую информацию до кода?
> >>> Или про какой-то стандартный софт, который не возвращает тело для
> >>> HEAD-запросов?
> >>
> >> Какая разница, сам софт или фрейморк используемый софтом в каждом
> >> конкретном случае обрабатывает HEAD запросы согласно требований RFC?
> >
> > Никакой.  Но с этой точки зрения так же нет разницы, что именно
> > написано в примерах в описании директивы fastcgi_cache_key.
>
> Вы не против, если я создам на хабре статью, в которой напишу
> про эту проблему с ошибочными примерами в документации nginx
> к директиве fastcgi_cache_key и ее аналогам?
>
> --
> Best regards,
>   Gena
>
> ___
> nginx-ru mailing list
> nginx-ru@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-ru
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: Документация к директиве fastcgi_cache_key

2018-11-30 Пенетрантность Gena Makhomed

On 29.11.2018 21:02, Maxim Dounin wrote:


CGI и HTTP - это два разных протокола.  В последних вариациях на
тему спецификации CGI записано, что на HEAD-запросы тело
возвращать не надо (а если вдруг вернули - то сервер его должен
поскипать), https://tools.ietf.org/html/rfc3875#section-4.3.3:

The HEAD method requests the script to do sufficient processing to
return the response header fields, without providing a response
message-body.  The script MUST NOT provide a response message-body
for a HEAD request.  If it does, then the server MUST discard the
message-body when reading the response from the script.

Однако на момент собственно появления и активного распространения
CGI никаких подобных требований не существовало, см.
https://www.w3.org/CGI/ и в частности
https://tools.ietf.org/html/draft-robinson-www-interface-00.


Там написано:

REQUEST_METHOD

  This variable is specific to requests made with HTTP.

  The method with which the request was made, as described in
  section 5.1.1 of the HTTP/1.0 specification [3].

 http-method  = "GET" | "HEAD" | "POST" | extension-method

"described in HTTP/1.0 specification" - написано где смотреть семантику.
А в HTTP/1.0 specification написано, что "server must not return any
Entity-Body in the response".

CGI и HTTP - это два разных протокола, но первый ссылается на второй.
При этом CGI протокол не запрещает бекенду отвечать на HEAD-запросы
так, как этого требует от веб-сервера спецификация HTTP протокола.


И на
практике я не встречал скрипты, которые бы отдельно обрабатывали
HEAD-запросы.


Но они есть.
И их поведение ничем не противоречит спецификации FastCGI протокола.


Речь про какие-то фреймворки, которые обрабатывают
HEAD автоматически, не донося соответствующую информацию до кода?
Или про какой-то стандартный софт, который не возвращает тело для
HEAD-запросов?


Какая разница, сам софт или фрейморк используемый софтом в каждом
конкретном случае обрабатывает HEAD запросы согласно требований RFC?


Никакой.  Но с этой точки зрения так же нет разницы, что именно
написано в примерах в описании директивы fastcgi_cache_key.


Вы не против, если я создам на хабре статью, в которой напишу
про эту проблему с ошибочными примерами в документации nginx
к директиве fastcgi_cache_key и ее аналогам?

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: Документация к директиве fastcgi_cache_key

2018-11-29 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 29, 2018 at 08:35:18PM +0200, Gena Makhomed wrote:

> On 29.11.2018 18:30, Maxim Dounin wrote:
> 
> >> В документации к директиве fastcgi_cache_key приведен такой пример:
> >>
> >>  fastcgi_cache_key localhost:9000$request_uri;
> >>
> >> У этого примера есть несколько проблем:
> >>
> >> 1. Если кто-то сделает к бекенду HEAD-запрос, то в кеш запишется пустой
> >> ответ и на последующие GET-запросы будет отдаваться пустая страница.
> 
> > AFAIK, никакой специальной обработки HEAD-запросов в FastCGI не
> > предусмотрено.  И в том числе не предсмотрено в каком-нибудь PHP
> > из коробки.  Соответственно всё будет работать штатно.
> 
> Специальная обработка HEAD-запросов предусмотрена в HTTP протоколе:
> https://tools.ietf.org/html/rfc7231#section-4.3.2
> 
> The HEAD method is identical to GET except that the server MUST NOT
> send a message body in the response (i.e., the response terminates at
> the end of the header section).
> 
> В nginx присутствует workaround, который исправляет поведение бекендов,
> которые на HEAD-запрос *ошибочно* отвечают так же, как и на GET-запрос.
> 
> Но далеко не все бекенды содержат в себе эту ошибку, многие из них ведут
> себя именно так, как этого от них требует спецификация HTTP протокола.

CGI и HTTP - это два разных протокола.  В последних вариациях на 
тему спецификации CGI записано, что на HEAD-запросы тело 
возвращать не надо (а если вдруг вернули - то сервер его должен 
поскипать), https://tools.ietf.org/html/rfc3875#section-4.3.3:

   The HEAD method requests the script to do sufficient processing to
   return the response header fields, without providing a response
   message-body.  The script MUST NOT provide a response message-body
   for a HEAD request.  If it does, then the server MUST discard the
   message-body when reading the response from the script.

Однако на момент собственно появления и активного распространения 
CGI никаких подобных требований не существовало, см.  
https://www.w3.org/CGI/ и в частности
https://tools.ietf.org/html/draft-robinson-www-interface-00.  И на 
практике я не встречал скрипты, которые бы отдельно обрабатывали 
HEAD-запросы.

> > Речь про какие-то фреймворки, которые обрабатывают
> > HEAD автоматически, не донося соответствующую информацию до кода?
> > Или про какой-то стандартный софт, который не возвращает тело для
> > HEAD-запросов?
> 
> Какая разница, сам софт или фрейморк используемый софтом в каждом
> конкретном случае обрабатывает HEAD запросы согласно требований RFC?

Никакой.  Но с этой точки зрения так же нет разницы, что именно 
написано в примерах в описании директивы fastcgi_cache_key.

[...]

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: Документация к директиве fastcgi_cache_key

2018-11-29 Пенетрантность Gena Makhomed

On 29.11.2018 18:30, Maxim Dounin wrote:


В документации к директиве fastcgi_cache_key приведен такой пример:

 fastcgi_cache_key localhost:9000$request_uri;

У этого примера есть несколько проблем:

1. Если кто-то сделает к бекенду HEAD-запрос, то в кеш запишется пустой
ответ и на последующие GET-запросы будет отдаваться пустая страница.



AFAIK, никакой специальной обработки HEAD-запросов в FastCGI не
предусмотрено.  И в том числе не предсмотрено в каком-нибудь PHP
из коробки.  Соответственно всё будет работать штатно.


Специальная обработка HEAD-запросов предусмотрена в HTTP протоколе:
https://tools.ietf.org/html/rfc7231#section-4.3.2

   The HEAD method is identical to GET except that the server MUST NOT
   send a message body in the response (i.e., the response terminates at
   the end of the header section).

В nginx присутствует workaround, который исправляет поведение бекендов,
которые на HEAD-запрос *ошибочно* отвечают так же, как и на GET-запрос.

Но далеко не все бекенды содержат в себе эту ошибку, многие из них ведут
себя именно так, как этого от них требует спецификация HTTP протокола.


Речь про какие-то фреймворки, которые обрабатывают
HEAD автоматически, не донося соответствующую информацию до кода?
Или про какой-то стандартный софт, который не возвращает тело для
HEAD-запросов?


Какая разница, сам софт или фрейморк используемый софтом в каждом
конкретном случае обрабатывает HEAD запросы согласно требований RFC?

Эта проблема встречается не только у меня, вот например:

https://www.claudiokuenzler.com/blog/705/empty-blank-page-nginx-fastcgi-cache-head-get

https://serverfault.com/a/612729


Отдельно отмечу, что правильный вариант работы с HEAD-запросами
для целей кэширования - это отправлять на бэкенд GET-запросы, и
кэшировать ответ.  Именно так делает proxy-модуль.


В proxy модуле есть директива proxy_cache_convert_head, которая
имеет значение on по-умолчанию, поэтому там все работает нормально.
В fastcgi/uwsgi/scgi модулях аналогичной директивы нет.


В случае
FastCGI подобная автоматическая конвертация не работает, так как
метод запроса не отправляется на бэкенд иначе как через
произвольно заданный fastcgi_param,


Нет.

FastCGI - это расширение протокола CGI, а протокол CGI *требует*,
чтобы параметр REQUEST_METHOD присутствовал в каждом запросе:

https://tools.ietf.org/html/rfc3875#section-4.1.12

   The REQUEST_METHOD meta-variable MUST be set to the method which
   should be used by the script to process the request, as described in
   section 4.3.

  REQUEST_METHOD   = method
  method   = "GET" | "POST" | "HEAD" | extension-method
  extension-method = "PUT" | "DELETE" | token


да и сама конвертация
представляется ненужной, так как в типичном случае ответы на
HEAD-запросы не отличаются от таковых на GET-запросы.


Но ведь не все бекенды нарушают требование HTTP протокола,
есть и такие, которые обрабатывают HEAD-запросы правильно.


Однако если
вдруг она нужна - это можно сделать, просто передав в
fastcgi_param GET вместо HEAD.


Можете привести фрагмент конфига, как это можно сделать?


2. Как правило на современных серверах размещено больше одного сайта.
При такой настройке как рекомендуется в документации - кеш будет
представлять собой смесь из содержимого разных сайтов и нормально
работать не будет.



Вопрос тут в том, что именно является идентификатором
запрашиваемого ресурса.  Пример в документации предполагает, что
мы коннектимся на localhost:9000, и получаем там ответы,
идентифицируемые URI запроса.


Идентификатором ресурса является https://en.wikipedia.org/wiki/URI
который включает в себя и scheme и host и path[?query] ($request_uri)


Это в общем случае верно для конфигурации, которая приводится в
описании модуля fastcgi, и с этой конфигурацией приведённый пример
fastcgi_cache_key будет работать корректно.  Если конфигурация
другая - fastcgi_cache_key может потребоваться другой.  Однако
проблема в том, что без знания конфигурации - неизвестно, какой
именно fastcgi_cache_key потребуется.


Поэтому я и предлагаю написать в документации пример
директивы, который будет корректно работать *всегда*.


3. если бекенд возвращает для HTTP-версии сайта редирект на HTTPS версию
сайта, такое значение fastcgi_cache_key бужет приводить к проблемам,
так как для HTTPS-запроса будет возвращаться 301 редирект из кеша.

Можно ли исправить документацию и написать там в качестве примера
такой фрагмент:

   fastcgi_cache_key "$request_method $scheme://$host$request_uri";

такая директива работает нормально, нет трех вышеперечисленных проблем.



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


Идентификатор ресурса - это URI, в случае HTTP протокола.


В предложенном варианте -
отсутствует какая-либо информация о бэкенде вообще, так что он
представляется мне идеалогически неверным.


А в чем тут практическая проблема, если в fastcgi_cache_key
отсутствует информация о бекенде? Или проблемы никакой нет?


У нас, 

Re: Документация к директиве fastcgi_cache_key

2018-11-29 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 29, 2018 at 04:59:09PM +0200, Gena Makhomed wrote:

> Здравствуйте, All!
> 
> В документации к директиве fastcgi_cache_key приведен такой пример:
> 
> fastcgi_cache_key localhost:9000$request_uri;
> 
> У этого примера есть несколько проблем:
> 
> 1. Если кто-то сделает к бекенду HEAD-запрос, то в кеш запишется пустой
> ответ и на последующие GET-запросы будет отдаваться пустая страница.

AFAIK, никакой специальной обработки HEAD-запросов в FastCGI не 
предусмотрено.  И в том числе не предсмотрено в каком-нибудь PHP 
из коробки.  Соответственно всё будет работать штатно.

Речь про какие-то фреймворки, которые обрабатывают 
HEAD автоматически, не донося соответствующую информацию до кода?  
Или про какой-то стандартный софт, который не возвращает тело для 
HEAD-запросов?

Отдельно отмечу, что правильный вариант работы с HEAD-запросами 
для целей кэширования - это отправлять на бэкенд GET-запросы, и 
кэшировать ответ.  Именно так делает proxy-модуль.  В случае 
FastCGI подобная автоматическая конвертация не работает, так как 
метод запроса не отправляется на бэкенд иначе как через 
произвольно заданный fastcgi_param, да и сама конвертация 
представляется ненужной, так как в типичном случае ответы на 
HEAD-запросы не отличаются от таковых на GET-запросы.  Однако если 
вдруг она нужна - это можно сделать, просто передав в 
fastcgi_param GET вместо HEAD.

> 2. Как правило на современных серверах размещено больше одного сайта.
> При такой настройке как рекомендуется в документации - кеш будет
> представлять собой смесь из содержимого разных сайтов и нормально
> работать не будет.

Вопрос тут в том, что именно является идентификатором 
запрашиваемого ресурса.  Пример в документации предполагает, что 
мы коннектимся на localhost:9000, и получаем там ответы, 
идентифицируемые URI запроса.

Это в общем случае верно для конфигурации, которая приводится в 
описании модуля fastcgi, и с этой конфигурацией приведённый пример 
fastcgi_cache_key будет работать корректно.  Если конфигурация 
другая - fastcgi_cache_key может потребоваться другой.  Однако 
проблема в том, что без знания конфигурации - неизвестно, какой 
именно fastcgi_cache_key потребуется.

> 3. если бекенд возвращает для HTTP-версии сайта редирект на HTTPS версию
> сайта, такое значение fastcgi_cache_key бужет приводить к проблемам,
> так как для HTTPS-запроса будет возвращаться 301 редирект из кеша.
> 
> Можно ли исправить документацию и написать там в качестве примера
> такой фрагмент:
> 
>   fastcgi_cache_key "$request_method $scheme://$host$request_uri";
> 
> такая директива работает нормально, нет трех вышеперечисленных проблем.

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

У нас, конечно, уже есть подобная конструкция в описании 
proxy_cach_key, но там за счёт $cookie_user куда более очевидно, 
что это именно пример, а не что-то, отлитое в граните и пригодное 
для всех конфигов.  Возможно, по какому-то такому пути и стоит пойти.

> P.S.
> 
> Недавно в очередной раз столкнулся в проблемой, когда люди бездумно
> копируют в конфиг рекомендуемые варианты директивы fastcgi_cache_key
> из документации, не подозревая, что в документации записано в качестве
> рекомендуемого варианта то, что нормально работать у них не будет.

Кажется, что правильным будет для начала написать в описании 
fastcgi_cache_key (uwsgi_cache_key, scgi_cache_key), что ключ 
должен идентифицировать запрашиваемый ресурс, а не ставится "абы 
как, авось повезёт".

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru