可以通过 map 指令在 http 块中预定义 $ua_type 变量实现高效 ua 分类,再于 location 中通过 try_files、return 或 proxy_pass 动态响应,避免 if 嵌套、提升性能与可维护性。

可以通过 map 指令结合 if 或直接在 location 中判断 $http_user_agent,实现按 User-Agent 返回不同响应内容。核心在于高效匹配、避免重复解析,且不影响性能。
用 map 预定义 User-Agent 分类
推荐使用 map 指令在 http 块中预先映射 User-Agent 特征到自定义变量,比在 server 或 location 中用多个 if 更高效、更清晰。
- 在
http{...}块中定义:
map $http_user_agent $ua_type {
default "desktop";
~*curl|httpie "cli";
~*mobile|android|iphone "mobile";
~*wechat|micromessenger "wechat";
}注意:~* 表示大小写不敏感正则匹配;顺序重要,靠前的规则优先匹配;变量名(如 $ua_type)可在后续 server 块中直接引用。
在 server 块中根据分类返回不同内容
利用已定义的 $ua_type 变量,在 server 或 location 中做条件响应,例如返回不同页面或状态码:
- 返回不同静态文件:
location = / {
try_files /index.$ua_type.html /index.desktop.html =404;
}- 返回不同响应体(适合简单场景):
location = /api/hello {
if ($ua_type = "mobile") {
return 200 '{"msg":"Hello, mobile"}';
}
if ($ua_type = "wechat") {
return 200 '{"msg":"Hello, WeChat user"}';
}
return 200 '{"msg":"Hello, desktop"}';
}⚠️ 注意:Nginx 中 if 在 location 内可用,但不建议在 location 外嵌套复杂逻辑;更稳妥的方式是配合 error_page 或后端应用处理。
配合 rewrite 或 proxy_pass 实现分流
若需将不同 UA 请求代理到不同后端,可结合 proxy_pass 动态路径或 upstream:
- 按 UA 选择 upstream:
upstream backend_mobile { server 127.0.0.1:8001; }
upstream backend_desktop { server 127.0.0.1:8002; }
<p>location /app/ {
proxy<em>pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a></em>$ua_type;
proxy_set_header Host $host;
}</p>要求 upstream 名称与 $ua_type 值严格一致(如 backend_mobile),否则会报 502;建议搭配 default fallback 或健康检查。
调试与验证技巧
上线前务必验证匹配逻辑是否符合预期:
- 用 curl 模拟不同 UA 测试:
curl -H "User-Agent: Mozilla/5.0 (iPhone..." https://yoursite.com/ curl -H "User-Agent: curl/8.4.0" https://yoursite.com/api/hello
- 开启 Nginx 日志记录 UA 和分类变量,便于排查:
log_format ua_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_user_agent" "$ua_type"';
access_log /var/log/nginx/access.ua.log ua_log;日志能直观看出哪些 UA 被归类为哪一类,避免正则遗漏或误匹配。











