通过实际示例解释 Nginx Location 匹配规则

Web2026-09-20TryQuickToolBox

你可能调整过 Nginx 配置,重新加载后却疑惑为什么你的 location 块似乎没有生效。也许静态文件请求打到了 PHP 处理器,或者 API 路由被一个 catch-all 吞掉了。罪魁祸首通常是 Nginx 的 location 匹配算法——它并不像看起来那么直接。

在本指南中,我们将通过可以测试的实际示例,分解 Nginx 如何选择 location 块。到最后,你将确切知道哪个块胜出以及为什么。

Nginx Location 匹配如何工作

当请求到达时,Nginx 会将 URI 与所有定义的 location 块进行比较。匹配过程遵循特定顺序:

  1. 精确匹配 (=) — 最高优先级。如果找到,Nginx 停止并使用它。
  2. 最长前缀匹配 — Nginx 记住最长的匹配前缀 location。
  3. 正则表达式匹配 (~ 或 ~*) — 按出现顺序检查。第一个匹配的正则胜出,覆盖前缀匹配(除非使用了 ^~)。
  4. 带 ^~ 的前缀匹配 — 如果最长匹配前缀带有 ^~,Nginx 跳过正则检查并使用它。
  5. 如果没有正则匹配,则使用最长前缀匹配。

这就是核心算法。让我们看看它的实际应用。

Location 修饰符:快速参考

修饰符语法匹配类型优先级
=location = /path精确最高
^~location ^~ /path前缀(无正则)高
~location ~ \.php$正则(区分大小写)中
~*location ~* \.(jpg|png)$正则(不区分大小写)中
无location /path前缀最低

实际示例 1:静态文件 vs. PHP

考虑这个常见设置:

server {
    listen 80;
    server_name example.com;

    location / {
        root /var/www/html;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

对 /index.php 的请求匹配正则 \.php$,因此它转到 PHP-FPM。对 /logo.png 的请求不匹配正则,因此回退到前缀 / 并提供静态文件。很简单,对吧?

但是如果你想将 /uploads/photo.php 作为静态文件提供(也许它实际上是一个图像)呢?你可以添加一个精确匹配:

location = /uploads/photo.php {
    root /var/www/html;
}

现在这个精确匹配优先于正则。

实际示例 2:使用前缀和正则的 API 路由

假设你有一个 /api/ 下的 API,并且你想将所有请求代理到后端,除了一个返回静态响应的健康检查。

location = /api/health {
    return 200 "OK";
}

location /api/ {
    proxy_pass http://backend;
}

location ~ ^/api/v[0-9]+/special {
    proxy_pass http://special-backend;
}

让我们追踪 /api/health:精确匹配胜出,返回 200。对于 /api/users:没有精确匹配,没有正则匹配(不匹配 special),因此使用最长前缀 /api/。对于 /api/v1/special:正则匹配,因此它覆盖前缀并转到 special-backend。

这演示了正则如何覆盖前缀匹配。如果你希望前缀始终胜出,你可以使用 ^~ 代替。

实际示例 3:^~ 的力量

想象你有一个目录 /static/,其中的文件永远不应由 PHP 处理,即使它们以 .php 结尾。使用 ^~ 确保 Nginx 不检查正则 location。

location ^~ /static/ {
    root /var/www/html;
}

location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

对 /static/script.php 的请求匹配前缀 ^~ /static/。由于 ^~,Nginx 跳过正则检查并直接提供文件。如果没有 ^~,正则将匹配并且 PHP-FPM 将执行它——一个潜在的安全风险。

常见陷阱及如何避免它们

调试 Location 匹配

如果你不确定正在使用哪个 location,请在 Nginx 中启用调试日志。在你的 server 块中添加 error_log /var/log/nginx/error.log debug;,重新加载,并检查日志。你会看到类似 test location: "/api/users" 和 using configuration "/api/" 的行。

或者,在每个 location 中临时使用 return 200 "matched: /api/"; 来查看哪个响应。

常见问题

Nginx location 修饰符的优先级顺序是什么?

精确匹配 (=) 最高,然后是带 ^~ 的最长前缀,然后是按顺序的正则 (~ 或 ~*),最后是不带 ^~ 的最长前缀匹配。

正则 location 可以覆盖前缀 location 吗?

是的,除非前缀 location 使用了 ^~。正则 location 在最长前缀匹配之后检查,如果正则匹配,它优先于常规前缀。

如何仅针对特定文件匹配 location?

使用 = 进行精确匹配,例如 location = /favicon.ico。这确保只匹配该精确 URI。

掌握你的 Nginx 配置

理解 location 匹配是可靠 Nginx 设置的关键。使用 nginx -t 测试你的配置,并在有疑问时使用调试日志。如果你正在处理 Nginx 日志并需要分析流量模式,试试我们的 Nginx 日志分析器 来快速解析和可视化你的日志。