《Nginx 从入门到实践》系列二:Nginx location 匹配规则详解

  • 发布时间:2025年6月21日

上一篇讲了 Nginx 的安装和目录结构,这一篇写 location。为什么单独拿出来讲?因为我在它上面栽的跟头最多。当时给博客配 ThinkPHP 的伪静态,照着网上的文章抄了一段配置,结果有的页面能开、有的页面 404,折腾了一下午才搞明白是 location 匹配优先级的问题。这篇把我理解的规则完整梳理一遍。

一、location 的几种写法

location 块用来匹配请求的 URI,常见的写法有四种:

location = /uri     # 精确匹配,必须完全一致
location ^~ /uri    # 前缀匹配,命中后不再检查正则
location ~ /uri     # 正则匹配,区分大小写
location ~* /uri    # 正则匹配,不区分大小写
location /uri       # 普通前缀匹配

其中 = 和 ^~ 是"硬规则",~ 和 ~* 是正则,普通前缀最灵活。

二、匹配优先级

这是全文的重点,也是我踩坑的地方。Nginx 匹配 location 的顺序是这样的:

  1. 先找精确匹配 =,命中就直接用,不再继续。
  2. 再找 ^~ 前缀匹配,命中就直接用,不再继续。
  3. 然后按配置顺序依次尝试正则 ~ 和 ~*,第一个命中的正则胜出。
  4. 最后才是普通前缀匹配,取"最长匹配"的那个。

注意正则匹配是按书写顺序来的,谁先写谁优先,这和普通前缀的"最长优先"不一样,很容易记混。

我自己的记忆方法是:"精确最优先,正则按顺序,前缀看长短"。另外还有个容易忽略的点:如果命中 ^~,正则就被跳过了;如果命中普通前缀但后面还有正则,正则仍然有机会覆盖它。这个"正则能反超普通前缀"的规则,就是我当初 404 的根源——我以为写了个 / 前缀就万事大吉,结果被后面一条正则抢走了。

三、常见配置示例

实际配置里,我经常这样组合:

location = / {
    # 首页精确匹配,直接返回静态文件
}

location / {
    # 兜底规则,处理所有未匹配的请求
}

location ^~ /static/ {
    # 静态资源目录,命中后不检查正则,性能更好
    alias /var/www/blog/static/;
}

location ~* \.(jpg|png|gif|css|js)$ {
    # 按扩展名匹配静态文件,不区分大小写
    expires 30d;
}

location ~ \.php$ {
    # PHP 请求交给 fastcgi 处理
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

四、实战:ThinkPHP 伪静态

回到开头的坑。ThinkPHP 的 URL 是 index.php?s=/模块/控制器/动作 这样的形式,我希望用户访问 /user/detail/1 时能自动转过去。网上常见写法是:

location / {
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?s=$1 last;
    }
}

这段意思是:如果请求的文件不存在,就重写给 index.php。能用,但 Nginx 官方其实不建议在 location 里用 if,它的行为有不少边界情况。后来我改成了 try_files 的写法,更干净:

location / {
    try_files $uri $uri/ /index.php?s=$uri;
}

如果请求的路径既不是真实文件也不是真实目录,就交给 index.php 处理。这种写法我用了大半年,没有出过问题,推荐优先使用。

五、排错经验

最后分享几个排查 location 问题的小技巧:

  1. 先用 nginx -t 保证语法正确,再看 error.log,404 和 500 的原因会直接写出来。
  2. 用 curl -I 看返回的响应头,可以确认请求到底命中了哪个 location,配合 access.log 更直观。
  3. 注意 location /api/ 和 location /api 的区别:前者能匹配 /api/xxx 和 /api,后者只能匹配 /api 开头的路径,斜杠的位置会影响匹配范围,配置时要想清楚。
  4. 如果正则和前缀规则混在一起,先理清优先级再动手,不要边猜边试。

写在最后

location 匹配规则看着简单,细节其实不少。这篇我把优先级和常见坑都列出来了,希望能帮你少走弯路。下一篇写反向代理和负载均衡——这是 Nginx 最常用的生产场景,我会带上完整的配置示例。