这就是我需要做的事情:
我使用以下配置:
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',但在这种情况下有一些方法可以避免使用它。
答案 0 :(得分:0)
首先,您的示例不是“嵌套如果”。如果是这样,那看起来像
if ($cond1) {
if ($cond2) {
...
}
...
}
这在 Nginx 中是非法的...
但是,您可以通过使用地图来避免配置中额外的“ifs”。
映射逻辑基本上说(伪代码):
if $condtion1 = <param1> then set $var1 = <value1>
else if $condition1 = <param2> then set $var1 = <value2>
... <paramN> ... <valueN>
else set $var1 = <defaultValue>
在 Nginx 配置中使用几个从 Http 上下文提供全局变量的映射,您可以执行以下操作:
# 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”指令被放置在服务器或位置上下文中:
### note that because $args2 and $do_rw are Global
### the following works:
if ($do_rw) {
rewrite ^.*$ https://www.example.com/$args2? last;
}
关于最终的生产代码和最佳实践,我可以做出一些说明,但我已经尝试完全按照暗示的方式复制您的代码,仅就直接的 Maps 实现而言减少它的工作对比“如果”
请注意,地图确实对性能有影响,但不如“if”,而且地图比“if”更干净。使用 Maps,您还可以利用这些全局变量设置一次并可能被多个虚拟主机使用(如果您使用 SNI)...
最后——有点超出了 OP 的范围——我可以使用 Ngx_lua 模块来消除这个配置中的 If 完全......