如何在 nginx 的 IF 语句中使用 AND 运算符?

zad*_*ops 23 if-statement nginx and-operator

我正在尝试根据响应标头缓存请求。现在我想要的条件是如果响应同时具有 2 个标头 client-device 和 client-location,那么响应应该缓存在 nginx 端

所以我尝试使用这段代码

if ($http_client_device && $http_clocation) {
    set $cache_key "$request_uri$http_client_device$http_client_location";
}
proxy_cache_key $cache_key;
Run Code Online (Sandbox Code Playgroud)

但 nginx 不允许 nginx: [emerg] 意外的“&&”条件...

无论如何要解决这个问题吗?提前致谢

zad*_*ops 26

经过一整天的搜索后,我找到了一种解决方法,参考此主题 http://rosslawley.co.uk/archive/old/2010/01/04/nginx-how-to-multiple-if-statements/

所以一般来说我的代码将如下所示:

    if ($http_client_device) {
        set $temp_cache 1;
    }
    if ($http_client_location) {
        set $temp_cache 1$temp_cache;
    }
    if ($temp_cache = 11) {
        set $cache_key ...; 
    }
Run Code Online (Sandbox Code Playgroud)

但仍然想知道是否有更干净的方法在 nginx 中执行 AND 运算符

  • 有时候我觉得NGINX好蠢。我最终得到了同样的结果。 (5认同)

Ste*_*ing 20

方法一

if尽量少用。

  • 请注意,Nginx 在匹配时更改上下文块if更多详细信息

  • 为了避免if更改上下文块,使用map更好

# if ($arg_a == "" && $arg_b == "")

http {
  # map need in http context
  map "$arg_a$arg_b" $is_empty {
    default 0;
    "" 1;
  }
  server {
    if ($is_empty) {
      # ...
    }
    # ...
  }
}
Run Code Online (Sandbox Code Playgroud)

检查多个匹配

# if ($arg_a == "apple" && $arg_b == "boy")

http {
    # map need in http context
    map $arg_a $match_a {
        default 0;
        apple 1;
    }
    map $arg_b $match_b {
        default 0;
        boy 1;
    }
    map "$match_a$match_b" $match {
        default 0;
        11 1;
    }

    server {
        if ($match) {
            # ...
        }
        # ...
    }
}
Run Code Online (Sandbox Code Playgroud)

方法二

如果您确认您的配置有效,甚至if可以更改上下文块。

set $and 1;

if (<not condition>) {
    set $and 0;
}

if (<not condition>) {
    set $and 0;
}

if ($and) {
    # ...
}
Run Code Online (Sandbox Code Playgroud)

例如:

if ($arg_a = 1 && $arg_b = 2) { ... }
Run Code Online (Sandbox Code Playgroud)

可以实现

set $ab 1

if ($arg_a != 1) {
    set $ab 0;
}

if ($arg_b != 2) {
    set $ab 0;
}

if ($ab) {
    # ...
}
Run Code Online (Sandbox Code Playgroud)

参考:Nginx ifand

对于您的情况

set $set_cache_key 1;
if ($http_client_device = "") {
    set $set_cache_key 0;
}
if ($http_clocation = "") {
    set $set_cache_key 0;
}
if ($set_cache_key) {
    set $cache_key "$request_uri$http_client_device$http_client_location";
}
proxy_cache_key $cache_key;
Run Code Online (Sandbox Code Playgroud)