26 октября 2012 г.

Nginx, proxy_pass и urldecode

Есть у меня на проекте урл, который отвечает за поисковую строку. Но урл не обычный, а вида site.com/info/(.*). Внутри этой регулярки могут встречаться различные символы, которые необходимо энкодить (ну там пробелы, плюсы и так далее).
И всё бы работало нормально, не заведи админы вдруг nginx проксёй к апаче. Благодаря ему запросы вида /info/test+%2B+term (заэнкоженый плюс отделённый пробелами) стали доходить до апача как /info/test+++term, что после декодирования воспринималось уже как три пробела.

Долго пришлось отлавливать, как же это так происходит, поскольку сперва было грешили на само приложение. Когда дошли до самой точки входа - поняли что проблема в nginx.

Всезнающий гугл подсказал ответ.
тонкость заключалась в атрибуте proxy_pass:
Если proxy_pass указана с URI, то при передаче запроса серверу часть нормализованного URI запроса, соответствующая location, заменяется на URI, указанный в директиве
одного слеша на конце значения директвы хватило, чтобы nginx стал приводить запрос к нормализованному виду, то есть:
после декодирования текста, заданного в виде “%XX”, преобразования относительных элементов пути “.” и “..” в реальные, и возможной замены двух и более подряд идущих слэшей на один
Итак, nginx декодировал %2B в плюс, это понятно. Осталось загадкой, почему же он плюсы к пробелам не привёл? В общем несколько не логичное поведение привело к весьма трудно отловимой ошибке в приложении.
Вылечили убрав последний слеш:
proxy_pass http://127.0.0.1:88;

Комментариев нет: