Вимкнення розшифровки URL-адреси у nginx проксі


21

Коли я переходжу до цієї URL-адреси: http://localhost:8080/foo/%5B-%5Dсервер ( nc -l 8080) отримує його як є:

GET /foo/%5B-%5D HTTP/1.1

Однак, коли я проксі цей додаток через nginx (1.1.19):

location /foo {
        proxy_pass    http://localhost:8080/foo;
}

Той самий запит, який направляється через порт nginx, передається з декодованим шляхом:

GET /foo/[-] HTTP/1.1

Розшифровані квадратні дужки на шляху GET викликають помилки на цільовому сервері ( HTTP Status 400 - Незаконні символи у шляху ... ), коли вони надходять без уникнення.

Чи є спосіб відключити декодування URL-адреси або кодувати його назад, щоб цільовий сервер отримував такий самий шлях при маршрутизації через nginx? Якесь розумне правило перезапису URL-адреси?


Повідомлено про помилку на nginx: trac.nginx.org/nginx/ticket/262
Tomasz Nurkiewicz

Відповіді:


19

Цитуючи Валентина Васильовича Бартенева (який повинен отримати повну оцінку за цю відповідь):

Цитата з документації :

  • Якщо proxy_pass вказано з URI , при передачі запиту на сервер частина нормалізованого URI запиту, що відповідає розташуванню, замінюється URI, зазначеним у директиві

  • Якщо proxy_passвказано без URI , URI запиту передається серверу в тій же формі, що і надіслана клієнтом при обробці оригінального запиту

Правильною конфігурацією у вашому випадку буде:

location /foo {
   proxy_pass http://localhost:8080;
}

8
Мені довелося перейти http://localhost:8080/на http://localhost:8080випадок, якщо хтось має таку ж ситуацію, як і я.
herrtim

4
Чому Nginx розшифровує URI перед тим, як передавати його на сервер заходу? Чи не було б більше сенсу, якби він зберігав URI недоторканим?
мечоносець

@platypus, він залишається недоторканим, поки ви явно не почнете проводити заміну
cnst

2

Зауважте, що розшифровка URL-адрес, зазвичай відома як $uri"нормалізація" в документації на nginx, відбувається перед початковим IFF:

  • або будь-який URI вказаний всередині proxy_passсебе, навіть якщо лише остання коса риса сама по собі,

  • або URI змінюється під час обробки, наприклад, через rewrite.


Обидві умови чітко задокументовані на веб-сайті http://nginx.org/r/proxy_pass (міна акценту):

  • Якщо proxy_passдиректива вказана з URI , тоді, коли запит передається серверу, частина нормалізованого URI запиту, що відповідає розташуванню, замінюється URI, зазначеною в директиві

  • Якщо proxy_passвказано без URI , URI запиту передається серверу в тій же формі, що і надіслана клієнтом при обробці оригінального запиту, або повний нормалізований URI запиту передається під час обробки зміненого URI


Рішення полягає в тому, щоб або опустити URI, як у випадку з ОП, або, дійсно, використовувати розумне rewriteправило:

# map `/foo` to `/foo`:
location /foo {
    proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
}

# map `/foo` to `/bar`:
location /foo {
    rewrite  ^  $request_uri;            # get original URI
    rewrite  ^/foo(/.*)  /bar$1  break;  # drop /foo, put /bar
    return 400;   # if the second rewrite won't match
    proxy_pass    http://localhost:8080$uri;
}

Ви можете побачити його в прямому ефірі у відповідній відповіді на переповнення стека , включаючи контрольну групу.


Документація тут заплутана. Обидві форми містять URI. Це компонент шляху, який присутній в одному і відсутній в іншому.
Майкл Хемптон

@MichaelHampton, я не згоден - PATH взагалі називають URI, тому той, який не має шляху, не містить URI.
cnst

Звичайно, відносний шлях також може бути дійсною URL-адресою. Справа в тому, що решта також є дійсним URI (наприклад http://localhost:8080). Якщо ви не погоджуєтесь, ви можете погодитися з авторами RFC 3986.
Майкл Хемптон

@MichaelHampton Незручно, здається, що схема та шлях обов'язкові для того, щоб бути URI, повноваження, аргументи, фрагмент - необов’язкові
Норман Сю
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.