您的位置:

深入理解NGINX IF语句

一、nginx if判断无效

在使用nginx if语句时,有时候会发现if语句并没有按照预期执行,因此,在编写nginx规则时,请注意以下几点,以保证if语句可以正常运行:

1、if语句只能在 server、location、if 和 limit_except 块内使用。

2、if 后的条件必须用空格隔开。

3、if 后的条件不仅支持在 location 里设置,同时也支持在 server 块里设置。

4、在 location 里的 if 后如需使用反向代理,就不能用 try_files 。

如下所示,是一个if语句条件判断无效的例子:

server {
    listen 80;
    server_name example.com;
    if ($host = 'www.example.com') {
        return 301 $scheme://example.com$request_uri;
    }
    ...
}

上述代码中,$host变量应该是通过nginx自动获取的,而它没有用空格隔开if语句的条件,因此if语句无效。正确的写法应该是:

server {
    listen 80;
    server_name example.com;
    if ($host = 'www.example.com') {
        return 301 $scheme://example.com$request_uri;
    }
    ...
}

二、nginx iframe跨域

在前后端分离的项目中,为了保证安全性,通常会使用同源策略去限制页面的操作,例如防止跨域访问,但是有时候我们还是需要跨域访问,这时就需要用到 iframe 了。

当 iframe 的src属性的域名与父页面的域名不一致时,会出现跨域问题,此时,我们就可以利用nginx来解决这个问题。下面是一个利用nginx解决iframe跨域问题的示例:

location = /cross-domain.html {
    add_header 'Access-Control-Allow-Origin' 'http://target-site.com';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Credentials' 'true';
    alias /path/to/cross-domain.html;
}

上述代码中,另一个网站(target-site.com)想要在自己的网站上嵌入一个content-site.com的内容,此时需要访问包含在 cross-domain.html 文件中的 iframe,并且这个iframe要在target-site.com网站中访问,而访问时需要添加 Access-Control-Allow-Headers 和 Access-Control-Allow-Origin 等头信息,来实现某些getCredientials等操作。

三、nginx if判断

nginx if语句不仅可以判断变量,还可以根据自定义表达式进行判断,下面是其语法:

if(表达式1) {...} // 表达式   可以使用正则表达式来匹配字符串
if(表达式2) {...} // 表达式2  可以使用变量名,判断变量的值
if(表达式3) {...} // 表达式3  可以使用数字,判断变量是否等于/小于/大于指定数字

可以用来进行 if 判断的变量主要有:

1、$request_uri:请求uri

2、$host:请求的主机名

3、$http_x_forwarded_for:使用了proxy_pass代理后,客户端的Ip地址会被添加到http请求头的X-Forwarded-For字段中,使用$http_x_forwarded_for 来获取这个字段的值。

下面是一个使用if语句进行判断的示例:

location /path1 {
     if ( $host != 'www.example.com' ) {
         return 404;
     }
     proxy_pass http://backend2;
}

上述代码中,只有当请求的主机名为www.example.com时,才会反向代理到http://backend2 去。

四、小结

通过以上的文章内容可以看到,nginx if语句的使用与运用有很多优点,如可以进行简单的判断操作,以及可以解决一些跨域问题。但需要注意if语句只能在server、location、if 和 limit_except 块内使用,并且if语句后的条件必须要用空格隔开。

代码示例:

server {
    listen 80;
    server_name example.com;
    if ($host = 'www.example.com') {
        return 301 $scheme://example.com$request_uri;
    }
    location = /cross-domain.html {
        add_header 'Access-Control-Allow-Origin' 'http://target-site.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Credentials' 'true';
        alias /path/to/cross-domain.html;
    }
    location /path1 {
         if ( $host != 'www.example.com' ) {
             return 404;
         }
         proxy_pass http://backend2;
    }
}