用一条 Nginx 规则优雅拦截 /tool/*/*,同时放行 /tool/runcode/*

在后端接口或工具类服务中,我们经常会遇到一种需求:
限制某一类 URL 结构的访问,但对其中一个特例路径放行。
这类规则如果写不好,很容易踩 Nginx location 匹配优先级的坑,导致规则冲突、误拦或维护成本高。本文从开发者视角,分享一个 干净、单规则、可维护 的解决方案。
🎯 需求场景
我们有一类接口路径:
/tool/<module>/<action>现在希望:
- 所有
/tool/*/*这种两级路径 → 直接返回 404 - 但
/tool/runcode/*→ 允许正常访问 - 不能拆成多段
location,希望只用 一条规则
🧠 思路分析
普通写法通常是:
location /tool/runcode/ { ...放行... }
location ~ ^/tool/[^/]+/[^/]+ { return 404; }虽然可行,但这依赖 location 优先级规则:
- 前缀匹配
- 正则匹配
^~提升优先级
一旦团队成员不熟悉优先级,很容易误改导致线上规则失效。
所以更好的方式是:
在一个正则里直接排除
/tool/runcode/
这就用到了 负向前瞻 (Negative Lookahead) 。
💡 最终单规则解法
location ~ ^/tool/(?!runcode/)[^/]+/[^/]+ {
return 404;
}🔍 正则拆解
| 片段 | 含义 |
|---|---|
^/tool/ | 必须以 /tool/ 开头 |
(?!runcode/) | 负向前瞻 :接下来的路径不能是 runcode/ |
[^/]+/[^/]+ | 匹配两级任意路径 |
如果 URL 是 /tool/runcode/... ,负向前瞻失败 → 整条规则不匹配 → 自然放行。
✅ 行为验证
| URL | 是否匹配 | 结果 |
|---|---|---|
/tool/a/b | 匹配 | 404 |
/tool/test/run | 匹配 | 404 |
/tool/runcode/123 | 不匹配 | 放行 |
/tool/runcode/a/b | 不匹配 | 放行 |
/tool/a | 不匹配 | 不拦截 |
如果你只想拦截 刚好两级 (不含更深路径):
location ~ ^/tool/(?!runcode/)[^/]+/[^/]+/?$ {
return 404;
}⚙️ 性能与兼容性
- Nginx 正则使用 PCRE
- 负向前瞻
(?!...)原生支持 - 匹配开销极小,不会成为性能瓶颈
- 规则单一,维护成本低
🧩 为什么推荐这种写法?
从开发和运维角度,这种写法有几个优势:
- 没有 location 优先级陷阱
- 规则语义清晰
- 修改风险小
- 一眼看出排除逻辑
在多人协作或长期运维项目中,这点尤为重要。
🏁 总结
当你需要「匹配一类路径,但排除某个特例」时, 负向前瞻正则 是 Nginx 最优雅的解决方案。
最终规则牢记这一句就够了:
^/tool/(?!runcode/)[^/]+/[^/]+干净、精准、可维护。
如果你后续需要更复杂的白名单 / 黑名单路径控制,这种正则思路也可以继续扩展,十分好用 🚀
发布评论
发布评论前请先 登录。
评论列表 0

暂无评论



