我想解决一个越来越流行的基于正则表达式的新答案。
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,如果有人相对地引用了一个晦涩的半可选资源,该怎么办?)糟糕,该站点可能突然不起作用,但仅在某些情况下或在某些情况下才起作用。
根据我先前对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/?((?<=/).*)?$ {
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/;
}
因此,如果您问我,与两个同级顶级位置相对应的原始解决方案仍然比通过使用正则表达式路线而陷入一个兔子洞更好。