资讯动态

Nginx 学习笔记:Location 配置详解,五种修饰符与优先级规则实战

发布时间:2026/10/14 9:54:21 来源:尧图企业网站定制
本文首发于 栏轩·阁欢迎访问阅读原文获取更好的阅读体验。一、Location 是什么为什么重要Location 是 Nginx 中最核心的配置指令之一它决定了一个请求 URL 应该由谁来处理。location [修饰符] /path/ { # 匹配后的处理逻辑 proxy_pass http://backend; # 或 return、root、try_files 等 }无论是静态文件服务、反向代理、URL 重写还是访问控制都离不开 location。理解 location 的匹配规则是掌握 Nginx 的必经之路。本文目标搞懂五种 location 修饰符的区别掌握 location 优先级排序规则通过Docker 实战测试验证每一个知识点了解命名 location、try_files、root/alias 等进阶用法二、五种 Location 修饰符详解Nginx 的 location 共有5 种修饰符也可以说 4 种 无修饰符每一种都有不同的匹配行为。1. 精确匹配location /exact { # 只匹配 URI 为 /exact 的请求 }特点说明严格相等URI 必须完全等于指定的路径不扩散/exact不匹配/exact.html或/exact/优先级最高一旦匹配就立即处理不再检查其他 location2. 优先前缀匹配^~location ^~ /api/ { # 匹配以 /api/ 开头的所有请求 }特点说明前缀匹配只要 URI 以指定路径开头就匹配阻止正则匹配成功后不再检查正则 location~和~*优先级仅次于精确匹配3. 正则匹配~区分大小写location ~ \.html$ { # 匹配所有 .html 结尾的 URI区分大小写 }特点说明正则匹配URI 必须匹配正则表达式区分大小写.HTML不会被匹配顺序敏感多个正则按配置顺序匹配先命中先处理优先级低于^~高于普通前缀4. 正则匹配~*不区分大小写location ~* \.(jpg|jpeg|png|gif|webp)$ { # 匹配所有图片文件不区分大小写 }与~的唯一区别不区分大小写。.JPG、.jpg、.Jpg都会被匹配。5. 普通前缀匹配无修饰符location /prefix { # 匹配以 /prefix 开头的 URI }特点说明前缀匹配只要 URI 以指定路径开头就匹配正则优先如果也有正则匹配上了正则胜出优先级仅高于默认/6. 默认兜底/location / { # 匹配所有未匹配的请求 }这是最后的兜底方案所有没有被其他 location 匹配的请求都会走到这里。优先级最低。三、Location 里的常用指令匹配之后做什么Location 决定了谁来处理请求但匹配到之后做什么由里面的指令决定。这些指令才是 location 的真正内容。1.return— 直接返回响应return是 Nginx 里最简单的指令直接返回一个响应不再执行后面的任何指令。return 状态码 [文本] [URL];三种用法# 1. 只返回状态码 return 403; return 404; # 2. 返回状态码 文本浏览器直接显示这段文字 return 200 请求成功; return 403 你没有权限; # 3. 返回状态码 URL浏览器跳转到新地址 return 301 /new-page; return 302 http://example.com;常见状态码状态码含义return 配合什么200OK 正常返回文本204无内容什么都不加301永久重定向URL浏览器会缓存这个跳转302临时重定向URL下次还问原地址403Forbidden 禁止访问文本 或 什么都不加404Not Found 找不到文本 或 什么都不加500服务器内部错误文本 或 什么都不加502Bad Gateway 后端挂了文本 或 什么都不加关键特性return之后的指令全部被忽略。location /api/ { return 403 拒绝访问; proxy_pass http://backend; # ← 这行永远不会执行 add_header X-Custom val; # ← 这行也永远不会执行 }这就是为什么本文大量用return来测试 location 匹配——它只返回一句话不干别的事一眼就能看出来当前请求命中了哪个 location。2.proxy_pass— 反向代理最常用location /api/ { proxy_pass http://backend-server:3000; }把请求转发给后端服务器后端处理完再把结果返回给客户端。这是 Nginx 作为反向代理的核心用法。重点路径拼接规则很多人搞不清proxy_pass的路径是怎么拼的。规则只有一句话proxy_pass的 URL 有路径包括/→ 替换 location 匹配部分没有路径 → 原样传完整 URI情况 1proxy_pass 没有路径 → 原样转发location /api1/ { proxy_pass http://backend:3000; # ← 末尾没有 / } # 请求 /api1/users # 后端收到 /api1/users原样情况 2proxy_pass 有/→ 替换掉 location 路径location /api2/ { proxy_pass http://backend:3000/; # ← 末尾有 / } # 请求 /api2/users # 后端收到 /users/api2/ 被替换成 /情况 3proxy_pass 有具体路径 → 替换成指定路径location /api3/ { proxy_pass http://backend:3000/app/; # ← 有具体路径 } # 请求 /api3/users # 后端收到 /app/users/api3/ 被替换成 /app/快速记忆proxy_pass 后端没有路径 → 传完整 URI proxy_pass 后端有路径 → 替换掉 location 匹配部分这和之前讲的alias是同一个逻辑有路径就替换没路径就原样。3.root— 指定静态文件目录location /static/ { root /var/www; } # 请求 /static/js/app.js → 找 /var/www/static/js/app.jsroot是root路径 请求URI拼接去找文件。4.alias— 路径别名location /static/ { alias /var/www/html/; } # 请求 /static/js/app.js → 找 /var/www/html/js/app.jsalias是替换把 location 的路径替换成 alias 的路径。注意末尾/的问题之前已经讲过。5.try_files— 依次尝试找文件location / { try_files $uri $uri/ /index.html; }按顺序尝试$uri— 先找当前 URI 对应的文件$uri/— 找不到就试目录下的 index/index.html— 再找不到就返回 SPA 入口6.rewrite— URL 重写location /old-path/ { rewrite ^/old-path/(.*)$ /new-path/$1 permanent; }把 URL 从一种格式重写为另一种。permanent返回 301redirect返回 302不加就内部重写。7.index— 默认首页location / { index index.html index.htm; }访问目录时默认显示哪个文件。Nginx 会按顺序找找到哪个返回哪个。8.add_header— 自定义响应头location ~* \.(css|js|jpg)$ { add_header Cache-Control public, max-age86400; add_header X-Custom hello; }给响应加 HTTP 头常用于缓存控制、CORS 跨域、安全策略。9.expires— 缓存过期时间location ~* \.(jpg|png|css|js)$ { expires 30d; }相当于add_header Cache-Control的快捷方式。告诉浏览器这个资源可以缓存 30 天。10.deny / allow— 访问控制location /admin/ { deny all; allow 192.168.1.0/24; }按 IP 控制访问权限。顺序重要先允许后拒绝。11.if— 条件判断location / { if ($request_method DELETE) { return 405; } }在 location 里做条件判断通常配合$invalid_referer、$request_method等变量使用。12.set— 设置变量location / { set $cache_key $uri; set $debug true; }自定义变量用于后面的逻辑判断或日志记录。小结一个真实 location 里能放什么location ^~ /api/ { # 访问控制 deny all; allow 192.168.1.0/24; # 设置变量 set $backend http://app-server:3000; # 转发到后端 proxy_pass $backend; proxy_set_header Host $host; # 自定义响应头 add_header X-Upstream app-server; # 超时控制 proxy_connect_timeout 5s; proxy_read_timeout 10s; }一个 location 里可以组合多个指令它们按顺序执行。但return是特例——遇到 return 就直接返回了后面的指令不执行。四、Location 优先级规则核心这是 location 配置中最重要的部分。Nginx 的 location 匹配遵循以下优先级顺序精确匹配 () ← 优先级最高 ↓ 未匹配 优先前缀 (^~) ← 如果匹配跳过正则 ↓ 未匹配 正则匹配 (~ / ~*) ← 按配置顺序匹配命中即停 ↓ 未匹配 普通前缀无修饰符 ← 取最长的匹配 ↓ 未匹配 默认兜底 (/) ← 优先级最低匹配流程详解收到请求 URI │ ├─ 第 1 步检查所有 精确匹配 │ └─ 匹配 → 直接响应 ✅ │ ├─ 第 2 步检查所有 ^~ 优先前缀 │ └─ 匹配 → 跳过正则直接响应 ✅ │ ├─ 第 3 步检查所有 ~ / ~* 正则按配置顺序 │ └─ 匹配 → 直接响应 ✅ │ ├─ 第 4 步检查所有普通前缀取最长匹配 │ └─ 未匹配 → 走到 / │ └─ 第 5 步走到 / 默认兜底关键规则正则之间谁先定义谁处理同一个请求只会被第一个匹配的正则处理普通前缀取最长的匹配但如果有正则也匹配正则胜出^~一旦匹配完全跳过正则检查五、Docker 实战测试验证理论说再多不如动手测一遍。下面我用 Docker 启动 Nginx实测验证每一条规则。启动测试环境# 启动 nginx 容器dockerrun-d--namenginx-location-p19092:80 nginx:latest# 复制配置文件dockercpnginx.conf nginx-location:/etc/nginx/nginx.conf# 重载配置dockerexecnginx-location nginx-sreload测试配置# 五种修饰符 location /exact { return 200 精确匹配 () 命中; } location ^~ /api/ { return 200 优先前缀 (^~) 命中; } location ~ \.html$ { return 200 正则 (~) 命中; } location ~* \.(jpg|jpeg|png|gif|webp)$ { return 200 正则 (~*) 命中; } location /prefix { return 200 前缀匹配命中; } location / { return 200 默认兜底 (/) 命中; }测试结果测试 1精确匹配 /exactcurlhttp://localhost:19092/exact精确匹配 () 命中 规则: location /exact 特点: URI 必须完全等于 /exact 优先级: 最高结论 /exact只匹配/exact精确无误。测试 2精确匹配不扩散curlhttp://localhost:19092/exact.html正则 (~) 命中 规则: location ~ \.html结论 /exact不会匹配/exact.html精确匹配是严格相等。测试 3优先前缀^~ /api/curlhttp://localhost:19092/api/test优先前缀 (^~) 命中 规则: location ^~ /api/ 特点: 匹配以 /api/ 开头不再检查正则测试 4^~阻止正则检查 ⭐# /api/test.html 同时匹配 ^~ /api/ 和 ~ .htmlcurlhttp://localhost:19092/api/test.html优先前缀 (^~) 命中这是最重要的测试之一即使.html正则也匹配但^~命中后不再检查正则。测试 5正则区分大小写curlhttp://localhost:19092/test.html# 匹配 ✅curlhttp://localhost:19092/test.HTML# 不匹配 ❌.HTML不会被~ \.html$匹配会走到默认兜底。测试 6正则不区分大小写curlhttp://localhost:19092/image.JPGcurlhttp://localhost:19092/image.jpg两者都会被~* \.(jpg|jpeg|png|gif|webp)$匹配。测试 7前缀 vs 正则冲突 ⭐# /prefix 和 .html 都匹配curlhttp://localhost:19092/prefix/test.html正则 (~) 命中关键知识点普通前缀和正则都匹配时正则胜出。测试 8正则顺序location ~ ^/order1 { return 200 第一个正则在前面; } location ~ ^/order1 { return 200 第二个永远不会执行; }curlhttp://localhost:19092/order1顺序测试: 第一个正则在前面正则按配置顺序匹配先定义先处理。后面的同名正则永远没有机会执行。六、进阶用法1. 命名 Location命名 location不能从外部直接访问只能通过内部跳转try_files、error_page 等调用。location /test-fallback { try_files /nonexistent error_page; } location error_page { return 200 这是备用处理逻辑; }curlhttp://localhost:19092/test-fallback命名 location error_page 命中用途统一的错误处理、备用逻辑、请求收尾。2. try_files 链式查找location /tryfiles { try_files /test.html /backup.html final_fallback; }按顺序尝试先找/test.html→ 找到就返回找不到找/backup.html→ 找到就返回都找不到 → 跳到final_fallback非常适用于 SPA单页应用的优雅降级和静态文件 fallback。3. root vs alias 的区别这是 location 配置中非常容易混淆的两个指令。指令路径拼接方式示例rootroot URIroot /var/www;→ 请求/images/1.jpg→/var/www/images/1.jpgaliasalias (URI - location路径)alias /var/www/;→ 请求/images/1.jpg→/var/www/1.jpgroot 示例location /root-test/ { root /usr/share/nginx/html; } # 请求 /root-test/index.html → /usr/share/nginx/html/root-test/index.htmlalias 示例location /alias-test/ { alias /usr/share/nginx/html/; } # 请求 /alias-test/index.html → /usr/share/nginx/html/index.html⚠️ 重要alias 末尾的/决定了能不能找到文件alias的路径末尾必须带/否则路径拼接会出错。实测对比# ❌ 错误alias 末尾没有 / location /alias-test/ { alias /usr/share/nginx/html; } # 请求 /alias-test/index.html # → alias 把 /alias-test/ 替换成 /usr/share/nginx/html # → 结果/usr/share/nginx/htmlindex.html斜杠没了 # → 404 Not Found ❌ # ✅ 正确alias 末尾有 / location /alias-test/ { alias /usr/share/nginx/html/; } # 请求 /alias-test/index.html # → alias 把 /alias-test/ 替换成 /usr/share/nginx/html/ # → 结果/usr/share/nginx/html/index.html # → 200 OK ✅为什么 root 没这个问题location /test/ { root /usr/share/nginx/html; }root的拼接方式是root路径 完整URI/usr/share/nginx/html/test/index.html两个路径之间自然有/分隔所以root不需要纠结末尾斜杠配置请求结果原因alias /path/;带//test/200 ✅拼接正确alias /path;无//test/index.html404❌/usr/share/nginx/htmlindex.html少了个斜杠root /path;无//test/index.html200 ✅root 拼接方式自带斜杠简单记法alias是做替换把 location 路径替换成 alias 路径替换后斜杠要自己保证root是做拼接root URI斜杠天然有。其他注意alias不支持命名 location用在正则 location 时行为也不同建议能用root的地方优先用root。4. 防盗链实战组合结合valid_referers在 location 中做防盗链location ~* \.(jpg|jpeg|png|gif|webp)$ { valid_referers none blocked localhost; if ($invalid_referer) { return 403; } root /usr/share/nginx/html; }测试效果# 带本地 Referer → 允许 ✅curl-ehttp://localhost/page.htmlhttp://localhost:19092/image.JPG# 无 Referer → 允许 ✅因为有 nonecurlhttp://localhost:19092/image.JPG# 盗链 Referer → 拒绝 ❌curl-ehttp://evil.comhttp://localhost:19092/image.JPG# 输出: 盗链检测到请求被拒绝七、常见场景与最佳实践场景 1静态文件服务# 精确匹配根路径 location / { index index.html; } # 静态资源用正则匹配缓存策略 location ~* \.(css|js|jpg|png|woff2)$ { expires 30d; add_header Cache-Control public, immutable; } # API 反向代理用 ^~ 避免正则干扰 location ^~ /api/ { proxy_pass http://backend; }场景 2SPA 单页应用location / { try_files $uri $uri/ /index.html; }所有找不到文件的请求都 fallback 到index.html由前端路由处理。场景 3动静分离# 静态资源直接由 Nginx 处理 location ~* \.(jpg|png|css|js)$ { root /var/www/static; expires 30d; } # 动态请求转发给后端 location / { proxy_pass http://backend:3000; }最佳实践总结建议说明精确路径用如 /favicon.ico避免正则检查开销API 路径用^~避免被正则意外拦截文件类型用正则~* .(jpg正则不要重复同一个模式不要写两个正则后面的不会执行/放最后默认兜底始终放在 server 块的最后测试后再上线优先级的坑很容易踩用 curl 逐条验证八、总结Location 优先级速查表优先级 修饰符 示例 说明 ───────────────────────────────────────────────────── 高 │ location /exact 精确匹配 │ ^~ location ^~ /api/ 优先前缀阻止正则 │ ~ / ~* location ~ \.html$ 正则匹配顺序敏感 │ 无修饰符 location /prefix 普通前缀最长优先 低 │ / location / 默认兜底核心要点要点说明 最高完全相等的 URI 用性能最好^~ 阻止正则一旦^~匹配所有正则都不再检查正则顺序敏感正则之间谁先定义谁处理前缀比不过正则普通前缀匹配到的请求如果也有正则匹配正则胜出命名 locationname只能内部跳转不能外部访问推荐组合^~保护 API 正则处理静态资源 /兜底Nginx 的 location 配置看似简单但优先级规则在实践中很容易踩坑。记住一句话最高 →^~跳过正则 → 正则顺序匹配 → 普通前缀 →/兜底。动手用 Docker 测一遍比死记硬背有效一百倍。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑