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

2026-01-13 49 浏览 0 评论

在后端接口或工具类服务中,我们经常会遇到一种需求:

限制某一类 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
  • 负向前瞻 (?!...) 原生支持
  • 匹配开销极小,不会成为性能瓶颈
  • 规则单一,维护成本低

🧩 为什么推荐这种写法?

从开发和运维角度,这种写法有几个优势:

  1. 没有 location 优先级陷阱
  2. 规则语义清晰
  3. 修改风险小
  4. 一眼看出排除逻辑

在多人协作或长期运维项目中,这点尤为重要。


🏁 总结

当你需要「匹配一类路径,但排除某个特例」时, 负向前瞻正则 是 Nginx 最优雅的解决方案。

最终规则牢记这一句就够了:

^/tool/(?!runcode/)[^/]+/[^/]+

干净、精准、可维护。


如果你后续需要更复杂的白名单 / 黑名单路径控制,这种正则思路也可以继续扩展,十分好用 🚀


发布评论

发布评论前请先 登录

评论列表 0

暂无评论