我在http://example.com/上有一个正在运行的Web应用程序,并想在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!
}


评论


据我所知,最后一部分仍将“ / en”作为路径传递给代理,不是吗?

– Berkes
2013年12月21日在13:17

@berkes,不,它不会-proxy_pass中的斜杠是有所不同的。另外,此答案比您想出的答案更正确,因为它还确保proxy_redirect保持默认状态,因此,您仍然可以在后端使用302 et al,并使它在任何地方都能正常工作。

–cnst
2013年12月21日在18:27

啊,我错过了斜杠:(

–万安
16年5月2日在23:54

啊!拖尾!

– Barrymac
17年5月26日在16:27

经过3个小时的搜索,是的。。。是斜线。谢了哥们!

–卢卡斯·P。
18-10-15在16:09

#2 楼

我想解决一个基于正则表达式的新问题,并且这个问题越来越流行。原因。

上面的正则表达式将匹配/enjoy的请求uri,并将其重定向到上游/joy
/en的请求不会导致任何重定向,直接从上游为/提供服务(几乎就像是对/en/的请求一样,但不完全如此)。如果您在上游的根页面中使用相对URI(否则,为什么在上游URI中没有/en/前缀呢?),例如src="style.css"(例如,它可能引用特定于语言的url("menu.png")),那么浏览器将要求使用/style.css而不是/en/style.css。 (或者,即使您在所有地方都使用绝对URI,如果有人相对地引用了一个晦涩的半可选资源,该怎么办?)糟糕,该站点可能突然不起作用,而仅在某些情况下或在某些情况下有效。
根据我先前对OP自己的答案已经提到的另一个问题的建议,使用正则表达式可防止proxy_redirect伪指令具有默认值default,而将其默认值改为off。这意味着,如果在请求Location: http://127.0.0.1:8080/en/dir/时上游回复/en/dir,则客户端将看到此内容,这显然无法正常工作。 (对于首先提示正则表达式使用的/en请求,本来会特别具有讽刺意味,但是此特定实现却遇到了如上所述的另一个问题。)另外,如果您已经在使用upstream指令,则可能如果仅尝试使用自定义服务器,则会变得更加丑陋,尤其是如果您可能有多个上游服务器时,您将如何为每个服务器分别设置proxy_redirect?您也可以在proxy_redirect中使用正则表达式,甚至可以匹配任何主机,但是如果将来您决定进行跨域重定向该怎么办?

要尝试解决上述问题点具有基于正则表达式的单个位置,我们可以执行以下操作(请注意,在proxy_pass中,我们还必须从基于upstream的指令中删除对服务器的引用,以使proxy_redirect更为简单): >
location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$is_args$args;  # OOPS!
}


因此,如果您问我,最初的解决方案是将两个同级顶层位置作为兄弟,而不是通过使用regex路线而陷入困境。 />

评论


这将导致异常:nginx:[emerg]位置“ / en”在位置“ ^ / en /?((?<=/).*

–阿斯兰
16年7月5日在11:41

@Athlan,因为您一开始就不应该真正使用它!如果仍然愿意,可以将该位置放在正则表达式之外。

–cnst
16年7月5日在11:59

将本地化= / en放在外面工作真的很好!谢谢

–塞巴斯蒂安·韦伯(Sebastian Webber)
18年1月12日在13:16

#3 楼

因此,我在stackoverflow上找到了答案:

评论


我认为“ proxy_pass luscious / $;”应为“ proxy_pass luscious / $ 2”

– Zafer
18 Mar 19 '18 at 12:51

@Zafer是正确的,以上答案给了我一个错误

–法国
18-09-28在10:50

我已经更改了答案,但是手边没有可尝试使用的服务器ATM,因此未经过验证。

– Berkes
18年10月2日在8:09

这似乎将/ english代理到http:// luscious / glish,但这似乎并不理想。

–杰西·奇斯霍尔姆(Jesse Chisholm)
20年6月19日在15:04

#4 楼

对Nginx文档进行计费

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

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}


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

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}


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

#5 楼

我在上面接受的解决方案中进行了尝试,但发现它导致所有CSS和JS资产都进行了躲避重定向。您可以在这里找到它们。看看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(.*)  break;
}