Nginx 用 map 指令替代 if 嵌套实现多条件缓存绕过:通过顺序匹配、变量拼接(如 "$cookie_vip$arg_debug$request_method")生成布尔型变量 $bypass_flag,配合 proxy_cache_bypass 和 proxy_no_cache 控制读取与写入,支持分层 map 和响应头动态判断。

Nginx 本身不支持 if 嵌套或逻辑运算符(如 &&、||),但 map 指令能用顺序匹配+变量组合,把多个条件“编译”成一个布尔型或字符串型变量,再交给 proxy_cache_bypass 或 proxy_no_cache 使用——这是实现复杂绕过逻辑最稳定、高性能的方式。
用 map 合并多个请求特征做统一判断
比如要对“非 VIP 用户 + 带调试参数 + 请求方法为 GET”的组合才绕过缓存,不能写 if (xxx && yyy),而是把所有条件映射到一个变量里:
- 先定义一个中间变量,比如
$bypass_flag,只在满足全部条件时设为"1",其余情况为空或"0" - 利用
map的顺序匹配特性:把最具体的规则写在前面,用正则或精确值判断;default放最后兜底 - 例如:
map "$cookie_vip$arg_debug$request_method" $bypass_flag {<br> "~*^(?![vV]).*debug.*GET$" "1"; # 非 VIP(cookie_vip为空)且含 debug 参数且为 GET<br> default ""; # 其他情况不绕过<br>}
分层 map 组合:先拆解,再拼装
当条件太多、单个 map 难以维护时,可分步构造:
- 第一步:用
map提取各维度状态,比如$is_debug、$is_mobile、$is_admin - 第二步:再用一个 map 把这些变量拼成字符串(如
"${is_debug}${is_mobile}${is_admin}"),根据组合值决定是否绕过 - 注意:
map变量拼接必须用双引号包裹,否则会被当作字面量;空变量拼出来是空字符串,不影响匹配
绕过读取 vs 禁止写入:两个指令配合使用
proxy_cache_bypass 控制“是否跳过缓存读取”,proxy_no_cache 控制“是否禁止写入缓存”。两者常共用同一变量,但语义不同:
- 只要变量值是非空、非
"0"、非"off"字符串,就会触发绕过或禁写 - 例如管理员请求设
$cache_ttl为"0s",既可用于proxy_cache_valid表示不缓存,也能让proxy_cache_bypass $cache_ttl生效(因为"0s"是非空字符串) - 推荐显式定义绕过变量,如
$skip_cache,值为"1"或空,避免语义混淆
结合响应头或后端返回动态绕过
有些绕过逻辑依赖后端响应(比如某接口返回 X-Skip-Cache: 1),Nginx 无法在请求阶段获取,但可通过 proxy_ignore_headers 配合 add_header 回传给下一次请求:
- 在 location 中加
proxy_pass_request_headers off;和proxy_set_header X-Forwarded-For $remote_addr;等基础透传 - 用
proxy_hide_header X-Skip-Cache;防止该头暴露给客户端 - 再用
add_header X-Skip-Cache $upstream_http_x_skip_cache;把响应头转为响应头,供后续 map 使用(需配合map $upstream_http_x_skip_cache $bypass_by_header)


















