Re: Проксирование http и https в одном конигурационном файле, на порты отличные от 80 и 443

Maxim Dounin mdounin at mdounin.ru
Thu Dec 12 00:35:05 UTC 2013


Hello!

On Wed, Dec 11, 2013 at 03:45:17PM -0500, mnsold wrote:

> Maxim Dounin Wrote:
> -------------------------------------------------------
> > > Согласитесь, N количество блоков  server {} и N количество блоков
> > location
> > > {} проще изменить, меньше вероятности допустить ошибки и понимать
> > легче, чем
> > > N*2 количество блоков  server {} и N*2 количество блоков location {}
> > > сделанных отдельно для http и для https.
> > 
> > Не соглашусь.  Проще менять то, что само по себе просто.  А 
> > вероятность допустить ошибку - гораздо выше при редактировании 
> > сложного конфига.  Количество - не так важно, и принципиального 
> > значения не имеет.
> > 
> > Ну и не следует забывать, что все эти попытки "сокращения" 
> > конфигурации обычно выливаются в множество лишней работы при 
> > обработке запросов.  На всякий случай я оставлю эту ссылку здесь:
> > 
> > http://nginx.org/en/docs/faq/variables_in_config.html
> 
> 
> Я с вами тоже тут не соглашусь, т.к. конфиг вида:
> server {
> listen 80;
> listen 443 ssl;
> ...
> include app;
> ...
> }
> 
> файл app:
> location / {
> ...
> proxy_pass $schema://upstream:;
> ...
> }
> Очень простой и то, что вы написали "А вероятность допустить ошибку -
> гораздо выше при редактировании сложного конфига" тут несколько не уместно,
> т.к. вы правильно написали чуть выше "само по себе просто" и эти слова очень
> подходят для данной конфигурации. 

Использование proxy_pass с переменными - это совершенно отдельный 
режим работы proxy.  Различие с обычным proxy_pass куда как большее, чем 
может показаться на первый взгляд.

В частности, при задании URI запроса - его надо задавать, как 
справедливо написано в документации, полностью.  И на 
администратора при этом ложится обязанность обеспечить 
корректность этого URI, в частности - экранирование специальных 
символов.  На практике это означает, что, фактически, при 
использовании пременных URI должен передаваться "как есть".

Поэтому я крайне не рекомендую использовать proxy_pass с 
переменными для того, чтобы сократить количество строк в конфиге.  
Написанное по ссылке выше про переменные в конфиге - относится к 
этому случаю в первую очередь.

Ну и да, если мне не изменяет память, вы начали этот разговор с 
того, что так у вас - не работает.

> Не ясна тогда возможность указывать в директивы в одном блоке server {}
> server {
> listen 80;
> listen 443 ssl;
> С ваших слов получается - если удается заставить проксировать по схеме
> http->http + https->http то можно использовать такую конструкцию, в
> остальном - ее использовать не правильно, и нужно плодить блоки server{} и
> location{}.
> Я не утверждаю, что именно так вы сказали, это лишь вывод который сделал я
> на основе ваших наводок.

Логика очень простая: если виртуальные сервера обрабатываются 
одинаково - используйте один блок server{}, если по разному - 
используйте разные блоки server{}.  Блоки server{} существуют как 
раз для того, чтобы реализовывать разную обработку виртуальных 
серверов.

[...]

> Максим, вы не подумайте что я вас не понимаю, прекрасно понимаю, но хотелось
> бы найти решение для вопроса который я озвучивал ранее и был бы признателен
> за помощь:
> как проксировать одно приложение по http и https в одном блоке server {} и
> одном блоке location {} (без дублей), учитавая, что приложение на бэкэенде
> может быть доступно как в корне так и по контекстному пути, а порты
> отличаются от 80 и 443.

Если хочется обязательно сделать это в конфигах nginx'а, то в 
общем и целом всё сводится к тому, что замену путей надо будет 
делать самостоятельно, e.g., с помощью rewrite.  Как-то так должно 
сработать:

    location /foo/ {
        rewrite ^/foo/(.*) /bar/$1;

        if ($scheme = "https") {
            proxy_pass https://https-upstream;
            break;
        }

        proxy_pass http://plain-http-upstream;
        break;
    }

Или так:

    map $scheme $backend {
        http    http://plain-http-upstream;
        https   https://https-upstream;
    }

    location /foo/ {
        rewrite ^/foo/(.*) /bar/$1 break;
        proxy_pass $backend;
    }

Но, повторяю, это плохой путь.  Результирующий конфиг получится 
сложный и малопригодный к использованию, и тем паче модификации.

-- 
Maxim Dounin
http://nginx.org/



Подробная информация о списке рассылки nginx-ru