Nginx无内置单元测试框架,需通过curl模拟请求+nginx -t校验语法+自定义日志观测变量,结合map替代if实现可穷举验证,达成隔离、自动化、可断言的Rewrite规则测试效果。
Nginx 本身不提供内置的单元测试框架,也没有原生支持 .test 文件或断言式测试语法。所谓“Rewrite 规则的单元测试”,实际是通过可重复、自动化、隔离环境下的请求—响应验证流程,模拟不同输入 URI 并检查输出状态码、重定向头、内部 URI 变化或日志痕迹,从而达成类似单元测试的效果。
真正可行的做法不是写“测试用例代码”,而是构建一套轻量、脚本化的验证机制,核心靠三类工具协同:curl + nginx -t/-s reload + 日志解析(或辅助模块)。
这是最常用、最直接的验证方式。每条 Rewrite 规则对应一个明确的“输入 URI → 期望输出”关系,可用 shell 脚本批量执行:
# 示例:验证 /old → 301 → /newtest_uri="/old"expect_code="301"expect_location="https://example.com/new"response=$(curl -s -o /dev/null -w "%{http_code} %{redirect_url}" "http://127.0.0.1:8080$test_uri")read actual_code actual_url <<< "$response"if [[ "$actual_code" == "$expect_code" ]] && [[ "$actual_url" == "$expect_location" ]]; thenecho "✅ PASS: $test_uri → $expect_code → $expect_location"elseecho "❌ FAIL: got $actual_code '$actual_url', expected $expect_code '$expect_location'"fi
Location 头)-L,用 -I 查看 HTTP/1.1 200 OK 且无 Location,再配合 log_format 确认 $uri 已变)Nginx 不支持返回变量值给客户端,但可通过自定义日志格式把关键变量打出来,实现“可观测性”:
log_format rewrite_debug '$remote_addr - $request_uri → $uri → $args';access_log /var/log/nginx/rewrite-test.log rewrite_debug;
重启后发起请求:
curl "http://127.0.0.1:8080/old?a=1"# 日志输出示例:127.0.0.1 - /old?a=1 → /new → a=1
这样就能确认:
rewrite ^/old(.*)$ /new$1 break; 是否捕获了 (.*)
$args 是否透传$uri 是否已更新为 /new
⚠️ 注意:$uri 是重写后的规范化路径(不含 query string),而 $request_uri 是原始请求完整字符串。
虽然不能测逻辑,但可防止低级错误:
test-rules.conf)nginx -t -c /path/to/test.conf 验证语法是否合法diff 对比修改前后 nginx.conf,确保只改了预期位置nginx -T(dump 全量生效配置)提取某 location 块内容,确认 rewrite 行存在且顺序正确当重定向规则达几十上百条时(如旧链接迁移),应放弃 if { rewrite ... },改用 map:
map $uri $redirect_target {/a /x;/b /y;/c?d /z;default "";}
此时验证就变成纯字符串映射表校验:
(input, output) 对curl -I http://localhost$input,断言 301 + Location: $output
这种方式本质是把“运行时正则匹配”降级为“启动时查哈希表”,既提升性能,又让验证变得确定、可枚举、易自动化。
不复杂但容易忽略:真正的“单元测试感”,来自每次只测一条规则、关闭其他干扰项、用最小配置复现、靠机器而非肉眼判断响应细节。