这就是我需要做的:
我使用以下配置:
location / {
if ($args ~* "^param-1=(.*)¶m-2=(.*)") {
set $paramVar "1";
set $args2 $2;
}
if ($http_user_agent ~* (facebookexternalhit)) {
set $paramVar "${paramVar}1";
}
if ($paramVar = "11") {
rewrite ^.*$ https://www.example.com/$args2? last;
}
root /usr/share/nginx/html/xyz;
try_files $uri /index.html;
}这在从facebook共享调试器调用时很好,但是普通调用返回404。我认为这是因为一个正常的调用满足了第一个调用,但失败了第二个调用。
我知道“IFISEVIL”,但在这种情况下是否有办法避免使用它。
发布于 2021-08-05 19:52:06
首先,您的示例不是“嵌套If”。如果是的话,那看起来就像
if ($cond1) {
if ($cond2) {
...
}
...
}那在Nginx是违法的..。
但是,通过使用Maps,您可以避免配置中的额外"ifs“。
地图逻辑基本上是(伪代码):
if $condtion1 = <param1> then set $var1 = <value1>
else if $condition1 = <param2> then set $var1 = <value2>
... <paramN> ... <valueN>
else set $var1 = <defaultValue>使用Nginx配置中的Http上下文中提供Global的几个映射,您可以执行如下操作:
# if ($args ~* "^param-1=(.*)¶m-2=(.*)") {
# set $paramVar "1";
# set $args2 $2;
# }
### Your logic reduces to: if query params begin with param-1=someVal
### then set $args2 = $2
### here is the equivalent map:
map $args $param_1 {
default "";
^~param-1¶m-2 $args2;
}
### now let's detect that fb external hit
map $http_user_agent $fb_route {
~*facebookexternalhit 1;
default 0;
}
### set $do_rw = 1 to implement our IF later using clean code
### note that Nginx is doing a literal concat of the 2 mapped vars
### thus "11" below means $param_1 = 1 AND $fb_route = 1
map $param_1$fb_route $do_rw {
11 1;
default 0;
}生成的单个"If“指令被放置在Server或Location上下文中:
### note that because $args2 and $do_rw are Global
### the following works:
if ($do_rw) {
rewrite ^.*$ https://www.example.com/$args2? last;
}对于最终的生产代码和最佳实践,我可以做一些呼吁,但是我已经尝试完全复制您的代码,就像它所暗示的那样,只在直接地图实现和"if's“之间减少它。
请注意,Maps确实有性能影响,但比"if's“要小,而且Maps比"if's”更干净。使用Maps,您还可以利用这些全局Vars设置一次,并可能消耗多个虚拟主机,如果您使用SNI.
最后--有点超出了OP的范围--我可以使用Ngx_lua模块来消除If完全在这个配置中.
https://stackoverflow.com/questions/40716426
复制相似问题