Вопрос: Обратный прокси Nginx + переписывание URL


Nginx работает на порту 80, и я использую его для обращения к URL-адресам прокси с помощью пути /foo к порту 3200 сюда:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $host;
}

Это отлично работает, но у меня есть приложение на порту 3200, для чего я не хочу, чтобы начальный /foo для отправки. То есть - когда я получаю доступ http://localhost/foo/bar, Хочу только /bar как путь, полученный приложением. Поэтому я попытался добавить эту строку в блок местоположения выше:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;

Это вызывает перенаправление 302 (изменение URL-адреса), но мне нужно 301. Что мне делать?


91
2018-04-15 17:31


Источник


Если у вас возникли проблемы с случаем Grafana, вы должны использовать этот рецепт: docs.grafana.org/installation/behind_proxy/... - mohsen saeedi


Ответы:


Любое перенаправление на localhost не имеет смысла в удаленной системе (например, в веб-браузере клиента). Итак переписать флаги постоянный (301) или перенаправление (302) не могут использоваться в вашем случае.

Попробуйте выполнить настройку с использованием прозрачного правила перезаписи:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}

использование curl -i чтобы проверить ваши перезаписи. Очень тонкое изменение правила может привести к тому, что nginx выполнит перенаправление.


109
2018-04-15 17:56



URL-адрес по-прежнему начинается с / foo в моем приложении, когда я это делаю ... - jeffreyveon
Должна быть другая проблема. Я воспроизвел этот сценарий успешно, всего несколько минут назад. Исходный URL: Http: // разработка / Foo / TestMe / 1234 - REQUEST_URI скрипта PHP, запущенного на Apache, подключенном как прокси-сервер: '/ testme / 1234' - Jens Bradler
Регулярное выражение, вероятно, должно быть /foo(.*), в противном случае example.com/foo не будут сопоставлены. (это, вероятно, то, что испытывал Джеффривеон) - Benno
Такие работы, но мое тело, которое я устанавливаю с помощью proxy_set_body, удаляется. - Justin Thomas
переписать / (.*) /socket.io/ break; СОХРАНИТЬ МОЙ ДЕНЬ ДЛЯ SOCKET.IO - user956584


Простое сопоставление префикса местоположения работает для этого без использования правила перезаписи до тех пор, пока вы укажете URI в директиве proxy_pass:

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

Обратите внимание на дополнительный / в конце proxy_pass директивы. NGINX удалит соответствующий префикс /foo и передать остаток на серверный сервер в URI /, Следовательно, http://myserver:80/foo/bar будет публиковать на http://localhost:3200/bar,

Из Документы NGINX на proxy_pass:

Если директива proxy_pass указана с помощью URI, тогда, когда   запрос передается на сервер, часть нормализованного URI запроса   соответствие местоположения заменяется URI, указанным в директиве:


81
2017-09-29 03:30



Работает для меня, чем я добавил / в location / foo / { - Andrei N
Это именно то, что я искал! - anbiniyar
Это очень чистое решение, я бы предпочел, чтобы это был канонический ответ на вопрос. - ralien
Слишком долго, чтобы осознать важность сохранения или удаления конечной косой черты. - Parvez
Это действительно пройдет //xyz если вы это сделаете. - Archimedes Trajano


Абсолютный наиболее правильный способ и наилучшая практика обычно заключаются в следующем:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • Обратите внимание на острое значение конечная косая черта proxy_pass, который автоматически изменяет $uri переменная, чтобы иметь /foo/ на интерфейсе соответствуют / на бэкэнде. Нет необходимости в явном rewrite директивы.

  • Кроме того, обратите внимание, что задний / в location также весьма важна - без него вы рискуете иметь странные URL-адреса на вашем сайте в какой-то момент (например, работать /fooen в дополнении к /foo/en).

    Кроме того, / в location с proxy_pass также обеспечивает специальная обработка, согласно документации location директивы, чтобы эффективно вызывать неявное location = /foo {return 301 /foo/;} также.

    Итак, определив location с завершающей косой чертой, как указано выше, вы не только гарантируете, что без косой черты /fooen будет недействительным, но также /foo без остальной косой черты будет продолжать работать.


Справочная документация:


24
2017-08-26 21:12



Это лучший ответ здесь! - Mo Friedrich
Это выглядит как $args потеряны: http://frontend/foo?bar=baz будет проксирован http://backend/, Обратите внимание, что args не являются частью URL-адреса - Vanuan
@ Вануан, ты в этом уверен? Я довольно уверен $args следует по-прежнему обрабатывать соответствующим образом, если вы используете код выше, поскольку они отделены от $uri, и должны быть собраны обратно, если вы не используете явные переменные в своем proxy_pass, - cnst
@ArchimedesTrajano, вы ошибаетесь, так как есть специальная обработка для /foo перенаправить на /foo/, так что, если вы не делаете что-то странное на бэкэнде, даже /foo запросы будут по-прежнему работать с вышеуказанным кодом. (На самом деле это уже часть ответа, BTW.) - cnst
Это лучший ответ! Это должно двигаться вверх. - phegde


пытаться

location /foo {
    proxy_pass http://localhost:3200/;
    ....

или

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....

0
2018-01-21 16:20



Этот ответ был бы хорош, если бы вы дали некоторое объяснение, почему оно должно быть настроено, как указано выше. - masegaloeh
Это действительно пройдет //xyz если вы это сделаете. - Archimedes Trajano