try_files + subrequest + proxy-handler
Maxim Dounin
mdounin at mdounin.ru
Tue Apr 21 19:11:35 UTC 2015
Hello!
On Mon, Apr 20, 2015 at 05:39:18PM +0300, Eugene Mychlo wrote:
> Добрый день,
>
> Столкнулся со странной поведением nginx при использовании subrequest в сочетании с try_files с proxy-хэндлером.
> В приведенной ниже конфигурации, ожидалось, что при наличии файла /tmp/tres, на запрос
>
> http://127.0.0.1:8080/uno
>
> nginx вернет строку "uno duo " или "tres tres ", но никак не "uno tres ".
>
> Т.е. URI основного запроса передается без изменений (как и описано в документации), а подзапроса - нет.
> Ситуация воспроизводится на nginx версий 1.7.9 - 1.7.12.
>
> Отсюда вопрос: является ли подобное поведение задуманным или это бага?
> Будет ли меняться? И не стоит ли отметить это в документации?
>
>
>
> server {
> listen 8081;
> default_type text/html;
>
> location /uno { return 200 "uno "; }
> location /duo { return 200 "duo "; }
> location /tres { return 200 "tres "; }
> }
>
>
> server {
> listen 8080;
>
> location / {
> root /tmp;
> try_files /tres =404;
> proxy_pass http://127.0.0.1:8081;
> add_after_body /duo;
> }
> }
Наблюдаемый эффект - следствие того, что try_files меняет URI
запроса. (Мне лично кажется, что это - скорее неправильное
поведение. По хорошему, ему следует оставлять URI тем же, а
менять только соответствующий текущему URI файл. Но именно так
оно сейчас реализовано, и не совсем понятно, хотим ли мы это
менять. Когда делался try_files - какая-либо дальнейшая
обработка, которая бы зависила от URI, просто не предполагалась,
насколько я понимаю.)
При этом try_files используется как для обработки основного
запроса, так и для подзапроса. Т.е. $uri в обоих случаях в
момент проксирования - "/tres".
Однако при этом URI основного запроса считается низменённым
(потому что по хорошему try_files URI менять не должен, см. выше),
и соответственно соединение с бекендом (ибо proxy_pass без URI)
использует исходный URI запроса в том виде, как он был передан
клиентом, "/uno". В подзапросе же URI заведомо изменён, и
proxy_pass в соответствии с документацией использует
нормализованный URI запроса целиком, т.е. "/tres".
Возможных решений представляется два:
- переделать try_files так, чтобы URI не менялся, тогда будет "uno
duo";
- узаконить текущее поведение try_files и при изменении им URI
сбрасывать флаг r->valid_unparsed_uri, тогда будет "tres tres".
Мне лично более правильным кажется первый вариант. Но, возможно,
существуют какие-то ситуации, когда менять URI - всё-таки
правильнее, надо подумать.
Ну и да, текущее поведение - явно баг, имеет смысл добавить на
trac.nginx.org.
--
Maxim Dounin
http://nginx.org/
Подробная информация о списке рассылки nginx-ru