Как удалить путь с помощью nginx proxy_pass

Как удалить путь с помощью nginx proxy_pass

У меня есть работающее веб-приложение на http://example.com/, и я хочу «смонтировать» другое приложение на отдельном сервере на http://example.com/en. Вышестоящие серверы, proxy_passкажется, работают, но есть одна проблема:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

При открытии example.com/enмое приложение upstream возвращает 404 not found /en. Это имеет смысл, так как у upstream нет пути /en.

Правильное ли proxy_pathрешение? Мне следует переписать "upstream", чтобы он слушал /enвместо этого, как корневой путь? Или есть директива, которая позволяет мне переписать путь, переданный в upstream?

решение1

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

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

решение2

Я хотел бы рассмотреть новый ответ на основе регулярных выражений, популярность которого растет.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

На первый взгляд решение может показаться симпатичным, но оно неверно по нескольким причинам.

  • Регулярное выражение выше будет соответствовать запросу uri /enjoy, перенаправляя его в /joyupstream. Это действительно так задумано?

  • Запрос на /enне приведет ни к каким перенаправлениям, напрямую обслуживая из восходящего потока (почти как если бы вместо этого был сделан /запрос на , но не совсем). Если вы используете относительные URI в пределах вашей корневой страницы восходящего потока (иначе, почему бы вам не иметь префикс прямо там, внутри восходящих URI?), например (который может ссылаться на специфичный для языка , например), то браузер запросит это как вместо . (Или даже если вы используете абсолютные URI везде, что, если кто-то ссылается на неизвестный полунеобязательный ресурс относительно?) Ой, внезапно сайт может не работать, но только иногда или в крайних случаях./en//en/src="style.css"url("menu.png")/style.css/en/style.css

  • По моему мнениюболее ранний совет по другому вопросу, уже упомянутый в собственном ответе ОП, использование регулярных выражений предотвращаетproxy_redirectдирективу от значения по умолчанию default, понизив его до off. Это означает, что если восходящий поток отвечает с , когда делается Location: http://127.0.0.1:8080/en/dir/запрос на , то это то, что увидит клиент, что, очевидно, не будет работать правильно. (Что было бы особенно иронично для запроса, который изначально предлагает использовать регулярное выражение, однако эта конкретная реализация вместо этого страдает от другой проблемы, как уже упоминалось выше.) Плюс, если вы уже используете/en/dir/enupstreamдиректива, то это может стать еще более уродливым, если вы просто попытаетесь использовать пользовательский, особенно если у вас может быть более одного сервера upstream — как вы можете иметь отдельный proxy_redirectдля каждого из них? Вы proxy_redirectтакже можете использовать регулярные выражения внутри , возможно, даже для сопоставления любого хоста, но что, если вы решите дать кросс-доменное перенаправление в будущем?

Чтобы попытаться решить некоторые из вышеперечисленных проблем с помощью одного местоположения на основе регулярных выражений, мы могли бы сделать следующее (обратите внимание, что proxy_passнам также пришлось удалить ссылку на сервер из upstreamдирективы -based, чтобы сделать задачу proxy_redirectболее простой):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

Итак, если вы меня спросите,оригинальное решение с двумя родственными локациями верхнего уровнявсе равно это будет лучшей идеей, чем копать себе кроличью нору, следуя пути регулярных выражений.

решение3

Итак, я нашелответ на stackoverflow:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

По сути: передача регулярного выражения в location и передача обратной ссылки в URL proxy_pass.

решение4

Я поигрался с принятым решением выше, но обнаружил, что оно вызывает подозрительные перенаправления для всех CSS и JS-активов. В конце концов, я нашел вдохновение в том, как сделаны конфигурации LinuxServer SWAG Nginx. Вы можете найти ихздесь. Взгляни на pihole.subfolder.conf.sample.

Таким образом, мое решение выглядит так:

location /en {
    return 302 $scheme://$host/en/;
}

location ^~ /en/ {
    set $upstream_app lixxxx.members.linode.com;
    set $upstream_port 9001;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    rewrite /en(.*) $1 break;
}

Связанный контент