Nginx location 匹配规则详解:=、^~、~、/ 的区别与优先级,配置不再踩坑


很多站长写 Nginx 配置,看到一堆 location 就头大:有的前面带 =,有的带 ^~,有的带 ~,到底什么区别?写错了规则,网站要么 404,要么配置完全不生效。location 是 Nginx 里出现频率最高、也最容易写错的配置块。这篇文章把匹配规则、优先级、实战写法一次讲清。

一、location 是干什么的

location 用来匹配请求的 URL 路径,并指定这一部分用什么规则处理(静态文件、转发后端、拒绝访问等)。一个请求过来,Nginx 会在所有 location 里挑一个最合适的来执行。

location / {
    root /www/html;
}

二、四种匹配符号的区别

Nginx 的 location 匹配分两大类:前缀匹配和正则匹配,写法如下:

1. 精确匹配 =

location = / {
    # 只匹配请求路径正好是 / 的
}
location = /login.html {
    # 只匹配 /login.html,不匹配 /login.html/xxx
}

2. 普通前缀匹配(无符号)

location /images/ {
    # 匹配以 /images/ 开头的
}

3. 前缀匹配且不再往下查正则 ^~

location ^~ /static/ {
    # 匹配 /static/ 开头,命中后不再尝试正则
}

4. 正则匹配 ~(区分大小写)和 ~*(不区分)

location ~ \.(gif|jpg|png)$ {
    # 以 .gif/.jpg/.png 结尾,区分大小写
}
location ~* \.(css|js)$ {
    # 以 .css/.js 结尾,不区分大小写
}

三、优先级:记住这张表

Nginx 匹配规则总结为一句口诀:精确 > ^~ > 正则 > 普通前缀 > 默认(/)。

匹配顺序:

  1. 先把所有普通前缀(=、无符号、^~)都匹配一遍,找到最长的那个
  2. 如果最长的是 ^~,直接用它,不再查正则
  3. 否则继续按配置文件里的先后顺序试正则(~/~*),一旦命中就停
  4. 没有正则命中,就用步骤 1 找到的最长前缀

优先级示例:

location = /            { ... }   # 1 精确最高
location ^~ /images/    { ... }   # 2 ^~ 次之
location ~ \.php$       { ... }   # 3 正则
location /images/       { ... }   # 4 普通前缀(与 ^~ 冲突时 ^~ 赢)
location /              { ... }   # 5 兜底

请求 /images/logo.png 会命中 ^~ /images/(因为 ^~ 不再查正则);请求 /index.php 会命中正则 ~ \.php$。

四、经典实战配置

1. PHP 站点(最标准写法):

server {
    listen 80;
    server_name example.com;

    # 静态资源:命中就直接用文件,不交给 PHP
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff2?)$ {
        expires 30d;
        access_log off;
    }

    # PHP 请求交给 php-fpm
    location ~ \.php$ {
        root /www/html;
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location / {
        root /www/html;
        index index.php index.html;
    }
}

2. 精确匹配放行/拒绝:

# 后台入口只允许白名单
location = /admin {
    allow 1.2.3.4;
    deny all;
}

3. 图片防盗链 + 匹配:

location ~* \.(gif|jpg|png|webp)$ {
    valid_referers none blocked example.com *.example.com;
    if ($invalid_referer) {
        return 403;
    }
}

4. 反向代理匹配:

location /api/ {
    proxy_pass http://127.0.0.1:8080;
}
location ^~ /websocket/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

五、常见坑与排查

Q1:为什么我的正则 location 没生效?

正则只有在没有 ^~ 且没有被更长前缀先命中时才生效。常见错误:写了个长普通前缀 /images/,又写正则 ~ \.jpg$,但请求先命中了普通前缀(因为普通前缀找最长,然后才试正则)——正则其实还是会试。真正跳过正则的只有 ^~ 和 =。检查你是否把规则写成了 ^~。

Q2:location / 里的配置不生效?

location / 是兜底,只有其他所有规则都没命中时才用。别把核心逻辑都放这,优先用更具体的匹配。

Q3:~ 和 ~* 写反了大小写行为?

~ 区分大小写(\.php$ 不匹配 .PHP),~* 不区分。静态资源一般用 ~* 更稳。

Q4:改完配置不生效?

nginx -t 检查语法,nginx -s reload 平滑重载。注意 location 里的缩进不影响语法,但大括号别丢。

Q5:proxy_pass 结尾带不带 / 的区别?

带 / 表示替换前缀,不带 / 表示拼接完整路径,这是经典坑。要转发目录建议直接看本站 Nginx 反向代理教程里的详细说明。

六、如何测试自己的匹配

改完用 curl 打真实路径验证:

curl -I http://127.0.0.1/logo.png
curl -I http://127.0.0.1/index.php

配合 tail -f /var/log/nginx/access.log 看请求命中了哪个 location(日志里看不出 location,但能确认返回码和是否走了 PHP)。

总结

location 四种写法、三层优先级:= 精确 > ^~ 前缀(不查正则)> 正则(~ / ~*)> 普通前缀 / 兜底。写配置时记住:静态文件用正则 ~*,PHP 用 ~ \.php$,目录转发用普通前缀,需要跳过正则时用 ^~。多动手测试,配错了用 nginx -t 和 curl 就能定位。配合本站 Nginx 反向代理、缓存、HTTPS 等教程,Nginx 就基本玩明白了。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

Linux 查看端口占用与进程排查教程:lsof、netstat、ss 三件套,找出谁在占端口

Nginx 开启 Gzip 压缩教程:带宽省一半、首屏秒开,一行配置就提速

评 论
更换验证码