Nginx - 使用查询参数嵌套

时间:2016-11-21 09:13:22

标签: nginx

这就是我需要做的事情:

  • 检查请求是否来自facebook
  • 使用我收到的参数作为查询参数重定向网址
  • 如果网址不是来自facebook,则返回正常网页

我使用以下配置:

location / {
            if ($args ~* "^param-1=(.*)&param-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',但在这种情况下有一些方法可以避免使用它。

1 个答案:

答案 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=(.*)&param-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&param-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 完全......