Подкаталог Nginx pass_proxy без расшифровки URL - программирование
Подтвердить что ты не робот

Подкаталог Nginx pass_proxy без расшифровки URL

Мне нужно написать директиву размещения nginx для прокси-запросов в подкаталог на другой сервер сохранение urlencoding и удаление предиката подкаталога.

Вот искусственный пример - запрос вроде этого:

http://1.2.3.4/api/save/http%3A%2F%2Fexample.com

должен пройти как

http://abcd.com/save/http%3A%2F%2Fexample.com

Я пробовал несколько разных способов. Вот пара из них:

location /api/ { rewrite ^/api(/.*) $1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; } Но он декодирует строку, поэтому http://abcd.com получает /save/http://example.com

  1. Из другого вопроса SO

location /api/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; }

Но он сохраняет подкаталог, поэтому http://abcd.com получает /api/save/http%3A%2F%2Fexample.com.

Что нужно, где-то посередине. Спасибо!

UPD: здесь ticket в отслеживателе ошибок nginx

4b9b3361

Ответ 1

  

Но нет простого способа исправить это поведение nginx. В nginx trac есть некоторые ошибки, вы можете добавить свои. trac.nginx.org/nginx/.... Итак, я думаю, что самый простой способ - иметь субдомен. - Алексей 10 февраля 24 '15 в 14:49

  
  

https://trac.nginx.org/nginx/ticket/727

Если вы хотите, чтобы nginx выполнял что-то обычай, вы можете сделать это, используя proxy_pass с переменными (и переменную $request_uri, которая содержит исходный UES-запрос, который не был запрошен клиентом, отправленный клиентом). В этом случае вы будете нести ответственность за правильные преобразования URI. Обратите внимание, что это может легко вызвать проблемы безопасности и должно быть сделано с осторожностью.

Вызов принят!

    location /api/ {
        rewrite ^ $request_uri;
        rewrite ^/api/(.*) $1 break;
        return 400;
        proxy_pass http://127.0.0.1:82/$uri;
    }

Что это, люди!


Здесь для полного доказательства.

Конфигурационный файл для nginx/1.2.1:

server {
    listen 81;
    #first, the solution
    location /api/ {
        rewrite ^ $request_uri;
        rewrite ^/api/(.*) $1 break;
        return 400; #if the second rewrite won't match
        proxy_pass http://127.0.0.1:82/$uri;
    }
    #next, a few control groups
    location /dec/ {
        proxy_pass http://127.0.0.1:82/;
    }
    location /mec/ {
        rewrite ^/mec(/.*) $1 break;
        proxy_pass http://127.0.0.1:82;
    }
    location /nod/ {
        proxy_pass http://127.0.0.1:82;
    }
}

server {
    listen 82;
    return 200 $request_uri\n;
}

Ниже приведены результаты выполнения запросов для каждого местоположения:

% echo localhost:81/{api,dec,mec,nod}/save/http%3A%2F%2Fexample.com | xargs -n1 curl
/save/http%3A%2F%2Fexample.com
/save/http:/example.com
/save/http:/example.com
/nod/save/http%3A%2F%2Fexample.com
%

Обратите внимание, что наличие дополнительного return 400; довольно важно — в противном случае вы рискуете иметь проблемы с безопасностью (доступ к файлам через //api и т.д.), как Максим кратко упомянул в вашем билетном кассе.


P.S. Если вы считаете, что использование механизма перезаписи в качестве автомата с конечным состоянием очень круто, вы также можете проверить мой проект http://mdoc.su/ или fork it github.