移动端路由重写通过识别user-agent实现设备适配,nginx借助$http_user_agent配合if+rewrite(内部重写)或return(外部重定向)完成路径或域名跳转,推荐用map预定义$is_mobile提升性能与可维护性。

移动端路由重写,核心是识别用户设备类型(如手机、平板),再把请求导向适配的路径或域名,整个过程对用户透明(内部重写)或显式跳转(301/302重定向)。Nginx 本身不检测设备,但可通过 $http_user_agent 变量匹配常见移动端标识,结合 rewrite 或 return 实现精准路由。
用 if + rewrite 做内部路径重写
适合前后端分离或同一站点内提供不同入口逻辑的场景。比如所有移动端访问 / 都自动走 /mobile/ 下的资源,但浏览器地址栏不变:
- 在
location /或 server 块中添加判断 - 使用不区分大小写的正则匹配主流 UA 关键词(
mobile、android、iphone、ipad、blackberry等) - 搭配
last标志,确保重写后重新匹配 location
示例配置:
location / {
if ($http_user_agent ~* "(mobile|android|iphone|ipad|blackberry|iemobile)") {
rewrite ^/(.*)$ /mobile/$1 last;
}
root /var/www/html;
index index.html;
}注意:if 在 location 中可用,但不能嵌套;若需更健壮识别,建议配合 map 指令预定义变量(避免重复正则开销)。
用 return 做客户端重定向(推荐用于跨域名)
当移动端需独立域名(如 m.example.com)或强制跳转 HTTPS+移动版时,return 更轻量、安全且语义清晰:
- 直接返回 302(临时)或 301(永久)状态码
- 用
$scheme、$host、$request_uri组合新 URL,保持路径和参数不变 - 比
rewrite ... redirect性能略优,且不会触发二次 location 匹配
示例(HTTP 请求自动跳转到 m 子域):
server {
listen 80;
server_name example.com;
if ($http_user_agent ~* "(mobile|android|iphone|ipad)") {
return 302 https://m.example.com$request_uri;
}
}若已启用 HTTPS,可合并进主 server 块,或用单独的 server { server_name www.example.com; } 块统一处理。
用 map 预判设备类型,提升可维护性
避免在多个 location 中重复写 if 判断,把 UA 解析提到 http 块顶层,生成一个布尔变量(如 $is_mobile),后续直接引用:
- map 的匹配发生在请求解析早期,性能稳定
- 支持正则、字符串精确匹配、默认值设定
- 便于后期扩展(如按屏幕宽度、语言等细分)
示例:
http {
map $http_user_agent $is_mobile {
default 0;
"~*mobile" 1;
"~*android" 1;
"~*iphone" 1;
"~*ipad" 1;
}
<pre class="brush:php;toolbar:false;">server {
location / {
if ($is_mobile) {
rewrite ^/(.*)$ /mobile/$1 break;
}
# 其他非移动端逻辑
}
}}
break 表示重写后不再执行后续 rewrite,仍在当前 location 内继续处理(适合静态文件或 proxy_pass 场景)。
注意事项与避坑点
实际部署中容易忽略的关键细节:
-
UA 字符串可能被伪造或精简:部分浏览器或爬虫会隐藏 UA,建议结合
$http_x_wap_profile或$http_profile辅助判断(需客户端支持) - 不要在 if 中使用 return 4xx/5xx 后再写 rewrite:return 会立即终止处理,后续指令无效
- HTTPS 下注意 $scheme 一致性:若从 HTTP 跳转到 HTTPS 的移动端地址,确保证书覆盖目标域名(如 m.example.com)
- 缓存影响:301 会被浏览器强缓存,测试阶段优先用 302;上线后再切为 301
-
PC 端回退入口:移动端页面应提供“桌面版”链接,且服务端需支持通过 cookie 或参数绕过 UA 判断(如
?desktop=1)











