nginx location正则匹配需用~或~*显式启用,按配置顺序匹配首个成功项;rewrite可引用location捕获组$1等,首参数匹配完整uri;避免循环重写应选break、last或permanent。

Nginx 的 location 块支持正则匹配,配合 rewrite 指令可实现灵活的 URL 重写。关键在于理解匹配顺序、捕获变量传递、以及重写作用域的边界。
用 ~ 和 ~* 启用正则匹配
默认 location 是前缀匹配,要启用正则需显式使用修饰符:
-
~:区分大小写的 PCRE 正则匹配(如location ~ ^/api/v\d+/users/.+$) -
~*:不区分大小写的正则匹配(如location ~* \.(jpg|png|gif)$) - 注意:正则 location 的优先级低于精确匹配(
=)和最长前缀匹配,但高于普通前缀匹配;多个正则按配置文件中出现的**顺序**匹配,第一个成功即停止
在 rewrite 中引用正则捕获组
location 中的正则捕获(用 () 包裹)可在同一块内的 rewrite 中通过 $1、$2 等引用:
location ~ ^/blog/(\d{4})/(\d{2})/(\d{2})/(.+)$ {
rewrite ^/blog/\d{4}/\d{2}/\d{2}/(.+)$ /posts/$1-$2-$3-$4 permanent;
}
更安全写法是直接复用捕获变量:
location ~ ^/blog/(\d{4})/(\d{2})/(\d{2})/(.+)$ {
rewrite ^ /posts/$1-$2-$3-$4 permanent;
}
注意:rewrite 的第一个参数是**匹配整个请求 URI 的正则**(不含 host),所以常用 ^ 起始;$1–$9 来自 location 正则,不是 rewrite 自身的捕获。
避免循环重写与作用域陷阱
rewrite 默认在当前 location 内执行,若重写后的新 URI 又匹配到该 location,会再次触发 —— 导致 500 或重定向循环。解决方式:
- 加
break终止后续 rewrite 和 location 匹配(适合内部重写) - 加
last终止当前 location,重新搜索匹配新 URI 的 location(适合需要走不同处理逻辑的场景) - 加
redirect或permanent发送 302/301 响应(外部跳转,URI 改变且浏览器可见) - 慎用
if块内嵌 rewrite:Nginx 官方不推荐在 if 中使用 rewrite,易出意料行为;优先用 location + rewrite 组合
实用示例:多条件路径归一化
比如统一处理带或不带 trailing slash 的 API 版本路径,并提取版本号:
location ~ ^/v(?<ver>\d+\.\d+)/api(/|$) {
# 去掉末尾 /,确保统一格式
rewrite ^/v(?<ver>\d+\.\d+)/api(/?)$ /api/v$ver/ break;
proxy_pass http://backend;
}</ver></ver>
这里用了命名捕获 (?<ver>...)</ver> 提高可读性,break 防止重复匹配,且重写后仍走 proxy_pass。











