如何使用 nginx proxy_pass 删除路径

ber*_*kes 128 nginx path proxypass

我在 上有一个正在运行的 Web 应用程序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;
  }
}
Run Code Online (Sandbox Code Playgroud)

打开时example.com/en,我的上游应用程序返回404 not found /en。这是有道理的,因为上游没有 path /en

proxy_path正确的解决方案吗?我应该重写“上游”以便它/en作为根路径监听吗?或者是否有指令允许我重写传递给上游的路径?

cns*_*nst 238

这可能是做你想做的最有效的方式,不使用任何正则表达式:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}
Run Code Online (Sandbox Code Playgroud)

  • @berkes,不,它不会——`proxy_pass` 中的斜杠是有区别的。此外,这个答案比你想出的答案更正确,因为它还确保 [`proxy_redirect`](http://nginx.org/r/proxy_redirect) 保持在 `default`,所以,你仍然可以使用`302` 等在你的后端,让它在任何地方都能正常工作。 (17认同)
  • 啊啊啊!尾随斜线! (8认同)
  • 搜索了 3 个小时,是的...这是尾部斜线。谢了哥们! (6认同)
  • 啊,我错过了尾部斜线:( (4认同)
  • @TheGuywithTheHat 它只是指定为映射指定了一个路径;否则,不假设任何映射,路径按原样传递。 (2认同)

cns*_*nst 18

我想解决一个越来越受欢迎的基于正则表达式的新答案。

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

该解决方案乍一看似乎更可爱,但由于多种原因,它是错误的。

  • 上面的正则表达式将匹配 的请求 uri /enjoy,将其重定向到/joy上游。这真的是故意的吗?

  • 请求 for/en不会导致任何重定向,直接/从上游提供服务(几乎就像是发出请求一样/en/,但不完全是)。如果您在上游的根页面中使用相对 URI(否则,为什么不在/en/上游 URI 中使用前缀?),例如src="style.css"(例如,可能引用特定url("menu.png")于语言的),那么浏览器将请求作为/style.css代替/en/style.css。(或者,即使您在任何地方都使用绝对 URI,如果有人相对地引用了一个模糊的半可选资源怎么办?)哎呀,突然该站点可能无法工作,但只是有时或在边缘情况下。

  • 根据我之前在 OP 自己的答案中已经提到的另一个问题的建议,使用正则表达式可以防止proxy_redirect指令具有默认值defaultoff而是将其改为。这意味着如果上游Location: http://127.0.0.1:8080/en/dir/在发出请求时回复/en/dir,那么这就是客户端将看到的,这显然无法正常工作。(这对于一开始/en就提示使用正则表达式的请求来说尤其具有讽刺意味,但是这个特定的实现却遇到了上面已经提到的另一个问题。)另外,如果您已经在使用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/;
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您问我,具有两个兄弟顶级位置原始解决方案仍然比走正则表达式路线将自己挖进兔子洞更好。


ber*_*kes 7

所以,我在 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

基本上:将正则表达式传递到 location 并将 backref 传递到 proxy_pass url。


小智 6

Nginx 文档的记账

要将请求传递到 HTTP 代理服务器,请在位置内指定 proxy_pass 指令。例如:

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}
Run Code Online (Sandbox Code Playgroud)

此示例配置会将在此位置处理的所有请求传递到指定地址的代理服务器。该地址可以指定为域名或IP 地址。该地址还可能包括端口:

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的第一个示例中,代理服务器的地址后面跟着一个 URI,/link/。如果 URI 与地址一起指定,它将替换请求 URI 中与位置参数匹配的部分。例如,这里带有 /some/path/page.html URI 的请求将被代理到http://www.example.com/link/page.html。如果指定的地址没有 URI,或者无法确定要替换的 URI 部分,则传递完整的请求 URI(可能经过修改)。