nginx proxy_pass с использованием подпапки

Вопрос или проблема

Ок, эта задача должна быть простой, но я просто не могу добиться ее выполнения. Я хотел бы иметь подпапку после моего доменного имени (на самом деле, после IP этого доменного имени), которая перенаправляет на определенный порт на том же сервере. В сущности, я хочу избавиться от необходимости использовать множество портов.

Вот моя конфигурация nginx для этого

server {
    listen 80;

    index index.html index.htm index.nginx-debian.html index.php;

    server_name aaa.bbb.ccc.ddd;

    location ^~ /app2 {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://aaa.bbb.ccc.ddd:8001;
    }
}

Таким образом, при доступе к aaa.bbb.ccc.ddd/app2, я хотел бы, чтобы это разрешалось на http://aaa.bbb.ccc.ddd:8001.

Не должно быть так сложно. Что я упускаю здесь?

Спасибо
Пат

Поскольку вы пометили это как вопрос о обратном прокси, я предполагаю, что вы хотите проксировать запрос так, чтобы пользователь видел только http://aaa.bbb.ccc.ddd/app2 в своем браузере.

Вы можете изменить свой location блок на этот:

location ~/app2(.*)$ {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
    proxy_pass http://aaa.bbb.ccc.ddd:8001$1;
}

Здесь мы захватываем часть URI после /app2 в переменную $1 и используем ее в директиве proxy_pass.

Ответ Теро Килканена отличный. Однако в некоторых ситуациях неименованная группа регулярных выражений (например, $1) может быть не найдена. Мы можем использовать именованную группу (например, $sub_dir), чтобы избежать этой ошибки.

location ~/app2(?<sub_dir>.*)$ {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
    proxy_pass http://aaa.bbb.ccc.ddd:8001$sub_dir;
}

В приведенном выше примере используется (?<sub_dir>.*) для установки именованной группы, мы можем использовать $sub_dir, чтобы получить значение этой группы Regex.

Текущий ответ по какой-то причине не сработал для меня правильно (параметры запроса, похоже, пропали), но оказывается, есть и способ сделать это, который не использует регулярные выражения:

server {
    listen 80;

    index index.html index.htm index.nginx-debian.html index.php;

    server_name aaa.bbb.ccc.ddd;

    location ^~ /app2/ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://aaa.bbb.ccc.ddd:8001/;
    }
}

Что делает это работающим и отличает от конфигурации в вопросе, так это два завершающих слэша. Как объясняется в документации nginx, если вы укажете фактический путь в директиве proxy_pass, то он переписывает запрос, заменяя ту часть пути, которая соответствует секции location, на то, что указано в proxy_pass. Завершающий слэш в proxy_pass активирует это поведение, а завершающий слэш в совпадении location необходим для получения правильных результатов.

Ответ или решение

Конечно! Давайте разберем, как настроить nginx для работы с подкаталогом при проксировании на другой порт, чтобы всё работало безупречно.

Ваша цель — настроить nginx так, чтобы при доступе к http://aaa.bbb.ccc.ddd/app2 запрос перенаправлялся на http://aaa.bbb.ccc.ddd:8001, но при этом в адресной строке оставалось http://aaa.bbb.ccc.ddd/app2.

Ваша первоначальная конфигурация имеет правильный подход, однако вам нужно немного изменить настройки location и proxy_pass. Правильная настройка может выглядеть следующим образом:

server {
    listen 80;

    index index.html index.htm index.nginx-debian.html index.php;

    server_name aaa.bbb.ccc.ddd;

    location ^~ /app2/ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://aaa.bbb.ccc.ddd:8001/;
    }
}

Объяснение изменений:

  1. location ^~ /app2/: Этот блок определяет, что если URL начинается с /app2/, то nginx будет обрабатывать его в этом блоке. Обратите внимание на слэш, который следует за app2. Он важен для того, чтобы правильно проксировать запросы.

  2. proxy_pass http://aaa.bbb.ccc.ddd:8001/: Включение слэша в конце URL в proxy_pass указывает nginx, что нужно заменить часть пути, соответствующую location, на этот URL, сохраняя остальную часть URI. Это значит, что если у вас есть запрос к http://aaa.bbb.ccc.ddd/app2/some/path, он будет отправлен на http://aaa.bbb.ccc.ddd:8001/some/path.

Почему это работает:

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

  • Если в запросе присутствуют параметры, они также будут корректно переданы на сервер, работающий на порту 8001.

Возможные проблемы:

Если у вас возникают проблемы при использовании данного подхода (например, параметры запроса не передаются), вы можете проверить логи nginx для диагностики. Логи могут помочь определить, что именно происходит с вашими запросами.

Заключение:

Убедитесь, что ваши порты открыты и ваш сервер настроен на прослушивание внешних запросов. Этот метод позволит вам эффективно и удобно использовать подкаталоги для проксирования, избегая множества портов. Если у вас возникнут другие вопросы, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...