location 匹配规则

location 是 Nginx 配置的"灵魂"——它决定了"什么样的 URL 走什么样的处理逻辑"。但 location 的匹配规则初看简单,组合起来却能绕晕老司机。这一章我们把 location 彻底讲透:四种匹配符、优先级、root/alias 区别、try_files、rewrite,全是高频面试题与生产必备。

1. location 是什么?

一句话:location 块根据请求 URI 决定怎么处理。它写在 server 块里,可以有多个。看一个最简单的例子:

这种"按路径分流"就是 location 的核心价值。

2. 四种匹配符

location 的语法是 location [修饰符] URI。修饰符决定匹配方式:

# location 块的四种匹配符(写在 URI 前面)

location = /favicon.ico {
    # 1. 精确匹配:只有完全等于 /favicon.ico 才命中
}

location ^~ /static/ {
    # 2. 前缀匹配(停止搜索正则):以 /static/ 开头的路径优先匹配这里
}

location ~* \.(gif|jpg|jpeg|png)$ {
    # 3. 正则匹配(不区分大小写):所有图片请求
}

location ~ ^/api/\d+/ {
    # 4. 正则匹配(区分大小写):/api/123/ 这样的路径
}

location / {
    # 5. 通用匹配:所有未命中的请求都走这里(兜底)
}

# 不带修饰符的叫"前缀匹配(普通)"
location /blog {
    # 以 /blog 开头的路径(普通前缀匹配,会被正则覆盖)
}

四种修饰符记牢:=(精确)、^~(前缀停止正则)、~(正则区分大小写)、~*(正则不区分大小写)。不带修饰符的就是普通前缀匹配

3. 匹配优先级(重要!面试必考)

Nginx 的 location 不是按配置顺序从上往下匹配的!它有严格的优先级规则:

# location 匹配优先级(从高到低)
# 假设请求 URI 是 /static/logo.png

server {
    location = /static/logo.png {
        # 1. 精确匹配(最高优先级),命中即停
    }
    location ^~ /static/ {
        # 2. 前缀匹配 + 标记停止正则搜索,命中即停
    }
    location ~* \.(png|jpg|gif)$ {
        # 3. 正则匹配(按配置文件出现顺序,先匹配到的胜出)
    }
    location /static/ {
        # 4. 普通前缀匹配(最长前缀胜出,但会被正则覆盖)
    }
    location / {
        # 5. 兜底(最短前缀)
    }
}

# Nginx 实际匹配流程:
# ① 先在所有 location 里找"精确匹配 =",命中就停。
# ② 没命中,记忆"最长前缀匹配"(无论是否带 ^~)。
# ③ 如果最长前缀带了 ^~,直接用它,跳过正则。
# ④ 否则,按正则 location 在配置文件里的出现顺序逐个匹配,命中即停。
# ⑤ 所有正则都不命中,回退到第②步记忆的最长前缀匹配。

一句话总结:精确 > 前缀(^~) > 正则(按顺序) > 普通前缀(最长) > /

一个常被忽略的细节:正则 location 按配置文件中的出现顺序匹配,谁先出现谁优先。所以正则 location 的书写顺序很重要,这点和普通前缀不同。

4. root vs alias:高频坑点

这两个指令都用来"指定文件在磁盘的位置",但行为不同。这一节务必理解,因为这是Nginx 工程师面试必问的题:

# === root 指令 ===
# 把完整 URI 追加到 root 后面找文件
location /images/ {
    root /data/wallpaper;
    # 请求 /images/cat.png → /data/wallpaper/images/cat.png
}

# === alias 指令 ===
# 把 location 匹配的部分"替换"为 alias 路径
location /images/ {
    alias /data/wallpaper/;
    # 请求 /images/cat.png → /data/wallpaper/cat.png(images/ 被替换掉)
}

# 一图理解:
#   root   = /data + /images/cat.png = /data/images/cat.png
#   alias  = /data/      (替换掉 /images/)

# 关键区别总结:
# 1. root 拼接整个 URI;alias 只替换匹配部分
# 2. alias 必须以 / 结尾(location 也是 /xxx/ 形式时)
# 3. location 用正则时只能用 root,不能用 alias
# 4. alias 性能略好(少一次拼接),但容易出错,新手建议先用 root

记忆口诀:root 是"全拼接",alias 是"局部替换"。新手上路建议只用 root,把 alias 留到正则匹配等高级场景。

5. try_files:找不到时的回退

try_files 让你按顺序尝试多个文件/路径,第一个找到的就用它。它是实现单页应用(SPA)路由、图片占位、维护页面的关键工具:

# try_files:按顺序尝试文件,找不到时回退
location / {
    root /var/www/mysite;
    index index.html;

    # 依次尝试:$uri(具体文件)→ $uri/(目录)→ 都没找到返回 404
    try_files $uri $uri/ =404;
}

# 经典用法 1:单页应用(Vue/React)路由支持
location / {
    try_files $uri $uri/ /index.html;
    # 访问 /users/123 这种前端路由时,文件不存在就返回 index.html,
    # 让前端 router 接管
}

# 经典用法 2:图片占位
location /avatars/ {
    alias /data/avatars/;
    try_files $uri /avatars/default.png;
    # 用户没上传头像时,回退到默认图
}

# 经典用法 3:维护页面
location / {
    try_files /maintenance.html $uri $uri/ =404;
    # 优先返回维护页面(如果文件存在)
}

注意几个细节:

6. rewrite 与 return:URL 重写

有时候需要根据规则修改请求路径,比如旧路径迁移到新路径、HTTP 强制跳转 HTTPS。这时用 rewrite 或 return:

# rewrite:重写 URI(可改变请求路径或跳转)
server {
    # 把 /old-path 重写为 /new-path(内部重写,URL 不变)
    location /old-path {
        rewrite ^/old-path(.*)$ /new-path$1 last;
        # last     表示重写后重新走一遍 location 匹配
        # break    表示重写后在当前 location 继续处理
        # redirect 返回 302 临时跳转
        # permanent 返回 301 永久跳转
    }

    # 把 /download/123 重写为 /api/file?id=123
    location /download {
        rewrite ^/download/(\d+)$ /api/file?id=$1 break;
    }

    # HTTP 强制跳转到 HTTPS(最常见用法)
    server {
        listen 80;
        server_name example.com;
        return 301 https://$host$request_uri;
    }
}

# return 指令比 rewrite 更高效,能直接返回就用 return
return 301 https://example.com/new-url;
return 403 "Forbidden";

性能经验:能 return 就不要 rewrite。return 是直接返回响应,rewrite 会触发重新匹配 location,开销更大。HTTP→HTTPS 跳转这种场景,永远用 return 301

7. 一个完整的多 location 实战

把上面学到的整合起来,下面是一个典型的前后端分离项目的配置——API 转发、静态资源长缓存、文件上传、SPA 路由,全都覆盖:

# 一个真实场景:API 服务 + 静态资源 + 前端路由
server {
    listen 80;
    server_name app.example.com;
    root /var/www/app;

    # API 请求转发给后端
    location /api/ {
        proxy_pass http://localhost:3000;
    }

    # 静态资源(带长缓存)
    location ~* \.(css|js|png|jpg|gif|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 上传文件大小限制(仅上传接口)
    location /api/upload {
        client_max_body_size 50m;
        proxy_pass http://localhost:3000;
    }

    # 前端单页应用路由
    location / {
        try_files $uri $uri/ /index.html;
    }
}

这种"按路径分发"的配置结构,几乎每个现代 Web 应用都用得到。理解透这一段,你就能写出 80% 的 Nginx 配置。

8. 常见坑与排查

小结

location 是 Nginx 配置里最复杂也最强大的部分。这一章你掌握了四种匹配符、优先级、root/alias、try_files、rewrite——这些足以应对 95% 的场景。下一篇我们进入反向代理,把 location 的知识用到 proxy_pass 上。

← 上一篇 server 块与虚拟主机

下一篇 反向代理与负载均衡

✈️💬