nginx可通过解析user-agent字符串并结合map指令提取chrome、firefox、safari等浏览器版本号,再用if指令或nginx-lua实现基于版本的请求分流;但原生if不支持数值比较,需借助正则匹配或lua进行精确版本判断。

Nginx 本身不直接识别浏览器版本,但可以通过解析 User-Agent 字符串,结合正则匹配和内置变量,实现基于浏览器类型与版本的请求分流。关键在于准确提取版本号并做条件判断。
提取浏览器版本号
Nginx 的 $http_user_agent 变量包含完整 UA 字符串。需用 map 指令预处理,提取主流浏览器(如 Chrome、Firefox、Safari)的版本号,避免在每个 location 中重复正则解析,提升性能。
示例(写在 http 块中):
map $http_user_agent $chrome_version {
default "";
~*Chrome/([0-9]+)\. $1;
}
map $http_user_agent $firefox_version {
default "";
~*Firefox/([0-9]+)\. $1;
}
map $http_user_agent $safari_version {
default "";
~*Version/([0-9]+)\. Safari $1;
}
注意:Safari 的 UA 在 macOS/iOS 上格式不一,需兼顾 Version/X.X 和 Safari/X.X 等变体;Chrome 和 Firefox 的版本通常紧随斜杠后,取第一位数字即可粗略区分大版本。
在 location 中做版本判断分流
利用 if 指令结合提取出的版本变量,配合 return 或 proxy_pass 实现不同路径或后端的路由。注意:if 仅支持简单比较(=、!=、~、!~),不能嵌套或做数值大小比较(如 $chrome_version > 110 不合法)。
可行做法:
- 用正则直接匹配特定版本范围(如
~ ^11[0-9]$表示 Chrome 110–119) - 将版本映射为分级标识(如
legacy/modern),再按标识分流 - 对老版本(如 Chrome
示例(在 server 块内):
location /app/ {
if ($chrome_version ~ ^10[0-9]$) {
proxy_pass http://old_backend;
break;
}
if ($chrome_version ~ ^1[2-9][0-9]$) {
proxy_pass http://new_backend;
break;
}
proxy_pass http://default_backend;
}
更健壮的方案:用 Lua 模块做数值比较
若需精确判断版本号大小(如 Chrome >= 115),纯 Nginx 配置较难实现。推荐使用 nginx-lua(OpenResty)扩展:
- 用
ngx.re.match提取完整版本字符串(如"115.0.5790.170") - 用 Lua 分割并转为数字,逐段比较主版本、次版本
- 设置自定义变量(如
$browser_score),再在location或if中使用
这样可规避 Nginx 原生 if 的限制,也比纯正则更可靠。
注意事项与常见坑
UA 字符串易被伪造,该方案适用于客户端可信或内部灰度场景,不建议作为安全控制依据。
移动端 UA 差异大(如微信内置浏览器、QQ 浏览器),需单独适配其 UA 特征(如含 MicroMessenger、MQQBrowser)。
if 在 location 内使用时,务必加 break 或 return 终止后续匹配,否则可能意外落入其他 location。
测试时用 curl -H "User-Agent: ..." 模拟不同 UA,配合 log_format 输出 $chrome_version 等变量,验证提取是否正确。











