在 nginx 中,`internal` 指令用于限制 uri 只能由服务器内部请求访问,外部直接调用会返回 404。配合 `rewrite` 使用时,通常将公开入口(如 `/api`)通过 `rewrite` 重定向到内部处理逻辑(如 `/internal/handler`),并在该内部路径上应用 `internal` 指令,从而确保外部用户无法直接访问处理逻辑。

rewrite 如何重定向到 internal 路径
要实现这一限制,需要在配置文件中定义一个公开的路由规则,使用 `rewrite` 指令将请求转发到内部路径,然后在内部路径的 `location` 块中添加 `internal` 指令。这样,外部请求只能访问公开路径,而内部路径只能通过内部重定向或代理访问。

server {
listen 80;
# 公开入口:允许外部访问
location /api {
# 重写为内部路径
rewrite ^/api/(.*)$ /internal/handler/$1 last;
}
# 内部处理逻辑:禁止外部直接访问
location /internal/ {
internal;
# 实际处理逻辑,例如 proxy_pass 或 fastcgi_pass
# 这里仅作为示例,不执行具体操作
return 200 "Internal handler executed";
}
}
上述配置中,当外部请求 `/api/test` 时,Nginx 会通过 `rewrite` 将其重定向到 `/internal/handler/test`。由于 `/internal/` 路径设置了 `internal`,外部直接访问 `/internal/handler/test` 会返回 404,只有内部重定向才能成功。
如何验证 internal 是否生效
验证 `internal` 指令是否生效,可以通过两种方式测试:一是从外部直接访问内部路径,二是通过公开入口触发内部重定向。外部直接访问应返回 404,而通过公开入口访问应成功执行内部逻辑。

# 测试 1:外部直接访问内部路径(应返回 404) curl http://localhost/internal/handler/test # 预期输出:404 Not Found # 测试 2:通过公开入口访问(应成功) curl http://localhost/api/test # 预期输出:Internal handler executed
通过这两种测试,可以确认 `internal` 指令是否正确限制了外部直接访问。如果外部直接访问返回 404,而通过公开入口访问成功,则说明配置正确。
当 rewrite 使用 break 而非 last 时会发生什么
在之前的配置中,`rewrite` 使用了 `last` 标志,表示重写后重新匹配 `location`。如果使用 `break`,则重写后不会重新匹配 `location`,而是直接在当前 `location` 块中继续处理。这可能导致 `internal` 指令失效,因为请求仍在原始 `location` 上下文中。
server {
listen 80;
location /api {
# 使用 break 而非 last
rewrite ^/api/(.*)$ /internal/handler/$1 break;
}
location /internal/ {
internal;
return 200 "Internal handler executed";
}
}
在上述配置中,当外部请求 `/api/test` 时,`rewrite` 会将 URI 修改为 `/internal/handler/test`,但由于使用了 `break`,请求不会重新匹配 `/internal/` 的 `location`,而是在 `/api` 的 `location` 中继续处理。此时,`internal` 指令不会生效,因为请求并未进入 `/internal/` 的上下文。外部直接访问 `/internal/handler/test` 仍会返回 404,但通过 `/api/test` 访问也会失败,因为请求未正确路由到内部逻辑。











