如何使用 nginx proxy_pass 删除路径

如何使用 nginx proxy_pass 删除路径

我在 上有一个正在运行的 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;
  }
}

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

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

答案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,并将其重定向到/joy上游。这真的是有意为之吗?

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

  • 根据我的之前在另一个问题中的建议已经由原帖作者自己的回答提到过,使用正则表达式可以防止proxy_redirect指令的默认值为default,而将其调低为off。这意味着,如果上游在发出Location: http://127.0.0.1:8080/en/dir/请求时回复 ,那么客户端将看到 ,这显然无法正常工作。(对于首先提示使用正则表达式的请求来说,这尤其具有讽刺意味,但这种特定实现反而存在另一个问题,如上所述。)另外,如果您已经在使用/en/dir/enupstream指令,那么如果您只是尝试使用自定义指令,情况可能会变得特别糟糕,特别是如果您可能有多个上游服务器 — 您如何proxy_redirect为每个上游服务器单独设置一个?您也可以在 中使用正则表达式proxy_redirect,甚至可以匹配任何主机,但是如果您决定在将来提供跨域重定向怎么办?

为了尝试使用单个基于正则表达式的位置解决上述某些问题,我们可以执行以下操作(请注意,proxy_pass我们还必须从基于正则表达式的指令中删除对服务器的引用upstream,以使其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;
  }
}

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

答案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;
}

相关内容