Nginx Location 匹配优先级详解

本文摘自 deepseek

一、Location 匹配规则总览

Nginx 按以下顺序匹配 location(从高到低):

bash 复制代码
 1. 精确匹配 (location = /path)
 2. 前缀匹配 (location ^~ /path)
 3. 正则匹配 (区分大小写) (location ~ pattern)
 4. 正则匹配 (不区分大小写) (location ~* pattern)
 5. 普通前缀匹配 (location /path)
 6. 通用匹配 (location /)

二、每种匹配类型的详细解释和示例

1. 精确匹配 (Exact Match) location = /path

特点:
  • 只匹配完全相同的路径
  • 优先级最高
  • 匹配成功后立即停止搜索其他 location

示例配置:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 精确匹配首页
    location = / {
        return 200 "This is homepage";
    }
    
    # 精确匹配登录页
    location = /login {
        return 200 "This is login page";
    }
    
    # 其他匹配
    location / {
        return 200 "General match";
    }
}

测试结果:

bash 复制代码
请求 /          → "This is homepage"    (精确匹配)
请求 /login     → "This is login page"  (精确匹配)  
请求 /login?user=abc → "This is login page"  (忽略查询参数)
请求 /login/    → "General match"       (不是精确匹配,多了斜杠)
请求 /api       → "General match"       (没有精确匹配)

2. 前缀匹配 (带 ^~) location ^~ /path

特点:
  • 匹配以指定路径开头的 URI
  • 优先级高于正则匹配
  • 匹配成功后不再检查正则表达式

示例配置

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 前缀匹配(高优先级)
    location ^~ /static/ {
        return 200 "Static files (prefix match)";
    }
    
    # 正则匹配
    location ~ \.(jpg|png|gif)$ {
        return 200 "Image file (regex match)";
    }
    
    location / {
        return 200 "General match";
    }
}

测试结果

bash 复制代码
请求 /static/logo.jpg   → "Static files (prefix match)"  (前缀匹配优先于正则)
请求 /images/photo.jpg  → "Image file (regex match)"     (正则匹配)
请求 /static/css/style.css → "Static files (prefix match)"
请求 /static/           → "Static files (prefix match)"

3. 正则匹配 (区分大小写) location ~ pattern

特点:
  • 使用正则表达式匹配
  • 区分大小写
  • 多个正则匹配时,按配置文件中的顺序匹配

示例配置:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 正则匹配:图片文件
    location ~ \.(jpg|jpeg|png|gif)$ {
        return 200 "Image (case-sensitive regex)";
    }
    
    # 正则匹配:PHP文件
    location ~ \.php$ {
        return 200 "PHP file (case-sensitive regex)";
    }
    
    # 普通前缀匹配
    location /api/ {
        return 200 "API prefix";
    }
    
    location / {
        return 200 "General match";
    }
}

测试结果:

bash 复制代码
请求 /image.jpg         → "Image (case-sensitive regex)"
请求 /image.JPG         → "General match"  (大小写不匹配)
请求 /api/test.php      → "PHP file (case-sensitive regex)"  (正则优先于前缀)
请求 /api/users         → "API prefix"
请求 /docs/page.html    → "General match"

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

特点:
  • 使用正则表达式匹配
  • 不区分大小写
  • 优先级与区分大小写的正则匹配相同,按顺序决定

示例配置:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 不区分大小写的正则匹配
    location ~* \.(jpg|jpeg|png|gif)$ {
        return 200 "Image (case-insensitive regex)";
    }
    
    # 区分大小写的正则匹配
    location ~ \.pdf$ {
        return 200 "PDF file (case-sensitive regex)";
    }
    
    # 普通前缀匹配
    location /downloads/ {
        return 200 "Downloads directory";
    }
}

测试结果:

bash 复制代码
请求 /image.jpg         → "Image (case-insensitive regex)"
请求 /image.JPG         → "Image (case-insensitive regex)"  (大小写不敏感)
请求 /document.PDF      → "General match"  (大小写不匹配,pdf 需要小写)
请求 /document.pdf      → "PDF file (case-sensitive regex)"
请求 /downloads/image.png → "Image (case-insensitive regex)"  (正则优先于前缀)

5. 普通前缀匹配 location /path

特点:
  • 匹配以指定路径开头的 URI
  • 优先级最低(除了通用匹配)
  • 多个匹配时,使用最长匹配原则

示例配置:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 普通前缀匹配 - 较长路径
    location /api/v2/ {
        return 200 "API v2";
    }
    
    # 普通前缀匹配 - 较短路径
    location /api/ {
        return 200 "API v1";
    }
    
    # 通用匹配
    location / {
        return 200 "General match";
    }
}

测试结果:

bash 复制代码
请求 /api/v2/users      → "API v2"        (最长匹配原则)
请求 /api/users         → "API v1"        (匹配/api/)
请求 /api               → "General match" (不匹配/api/,因为没有斜杠)
请求 /api/              → "API v1"        (匹配/api/)

6. 通用匹配 location /

特点:
  • 匹配所有请求
  • 优先级最低
  • 作为默认配置使用

示例配置:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 精确匹配
    location = /admin {
        return 200 "Admin page (exact)";
    }
    
    # 正则匹配
    location ~ \.php$ {
        return 200 "PHP handler";
    }
    
    # 通用匹配(兜底)
    location / {
        return 200 "Default handler";
    }
}

测试结果:

bash 复制代码
请求 /admin            → "Admin page (exact)"
请求 /index.php        → "PHP handler"
请求 /about            → "Default handler"
请求 /contact          → "Default handler"

三、综合示例和匹配流程

综合配置示例:

bash 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 1. 精确匹配
    location = / {
        return 200 "Homepage (exact match)";
    }
    
    # 2. 前缀匹配(高优先级)
    location ^~ /static/ {
        return 200 "Static content (priority prefix)";
    }
    
    # 3. 正则匹配(区分大小写)
    location ~ \.(php|php5)$ {
        return 200 "PHP script (case-sensitive regex)";
    }
    
    # 4. 正则匹配(不区分大小写)
    location ~* \.(jpg|jpeg|png|gif|ico)$ {
        return 200 "Image file (case-insensitive regex)";
    }
    
    # 5. 普通前缀匹配
    location /admin/ {
        return 200 "Admin area (prefix match)";
    }
    
    # 6. 普通前缀匹配
    location /api/ {
        return 200 "API endpoint (prefix match)";
    }
    
    # 7. 通用匹配
    location / {
        return 200 "Everything else (general match)";
    }
}

匹配流程演示:

bash 复制代码
请求 / → 
  1. 检查精确匹配: location = / ✓ 匹配!返回结果

请求 /static/css/style.css → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): location ^~ /static/ ✓ 匹配!返回结果
  (不检查正则匹配)

请求 /static/image.PNG → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): location ^~ /static/ ✓ 匹配!返回结果
  (虽然也匹配正则 location ~* \.(jpg|jpeg|png|gif|ico)$,但不检查)

请求 /index.php → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): 无
  3. 检查正则匹配: location ~ \.(php|php5)$ ✓ 匹配!返回结果

请求 /IMAGE.jpg → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): 无
  3. 检查正则匹配: location ~ \.(php|php5)$ 无
  4. 检查正则匹配(不区分大小写): location ~* \.(jpg|jpeg|png|gif|ico)$ ✓ 匹配!返回结果

请求 /admin/users → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): 无
  3. 检查正则匹配: 无
  4. 检查正则匹配(不区分大小写): 无
  5. 检查普通前缀匹配: location /admin/ ✓ 匹配!返回结果

请求 /api/v1/users → 
  1. 检查精确匹配: 无
  2. 检查前缀匹配(^~): 无
  3. 检查正则匹配: 无
  4. 检查正则匹配(不区分大小写): 无
  5. 检查普通前缀匹配: location /api/ ✓ 匹配!返回结果

请求 /about → 
  1-6步都不匹配
  7. 通用匹配: location / ✓ 匹配!返回结果

四、重要注意事项

  1. 匹配顺序是固定的,Nginx 严格按照优先级顺序检查
  2. 前缀匹配 (^~) 会跳过所有正则匹配,一旦匹配就不再检查正则
  3. 正则匹配按配置顺序,第一个匹配的正则表达式被使用
  4. 普通前缀匹配使用最长匹配原则
  5. 查询参数不影响路径匹配,/path 和 /path?query=1 匹配相同的 location
  6. 尾部斜杠有影响,/path 和 /path/ 是不同路径

五、调试技巧

可以添加调试头来查看匹配情况:

bash 复制代码
location ~* \.(jpg|jpeg|png|gif)$ {
    add_header X-Location-Match "Case-insensitive regex for images";
    # ...
}

location /static/ {
    add_header X-Location-Match "Prefix match for static";
    # ...
}

这样可以通过响应头查看实际匹配的是哪个 location。

相关推荐
露临霜3 小时前
Docker安装nginx
nginx·docker·容器
AlianNiew3 小时前
Nginx 反向代理 403 问题复盘
nginx
早川9198 小时前
Nginx反向代理
nginx
云和数据.ChenGuang11 小时前
运维工程师技术之nginx搭配php
运维·nginx·php·运维技术·数据库运维工程师·运维教程
我要精通C++11 小时前
从源码看nginx的缓存功能
运维·nginx·缓存
阿海5741 天前
卸载nginx的shell脚本
linux·nginx
吃喝不愁霸王餐APP开发者1 天前
霸王餐API网关层缓存:Nginx Proxy Cache与Cache-Control细节
nginx·spring·缓存
松莫莫1 天前
Nginx 学习笔记
笔记·学习·nginx
悟能不能悟1 天前
Apache和nginx的区别
运维·nginx