直接在 log_format 中使用 $request_uri 或 $uri 变量即可安全记录含特殊字符的路径,Nginx 默认会对这些变量做 URL 解码前的原始字节转义,避免日志格式被破坏或解析异常。

直接在 log_format 中使用 $request_uri 或 $uri 变量即可安全记录含特殊字符的路径,Nginx 默认会对这些变量做 URL 解码前的原始字节转义,避免日志格式被破坏或解析异常。
为什么特殊字符不会导致日志错乱
Nginx 在填充日志变量时,对 $request_uri(完整原始请求 URI,含查询参数)和 $uri(解码后的路径部分)均做了内部转义处理。例如请求 /api/v1/users?name=张三&tag=%2Fadmin%3Fid%3D1,$request_uri 会如实记录为:/api/v1/users?name=%E5%BC%A0%E4%B8%89&tag=%2Fadmin%3Fid%3D1
其中空格、中文、斜杠、问号等均以 %xx 形式保留,不会干扰 JSON 结构或日志分隔符。
推荐的日志格式写法(兼顾可读性与安全性)
使用 escape=json 参数让 log_format 自动对字段内容做 JSON 转义,特别适合输出 JSON 日志:
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
log_format api_json escape=json '{ "time": "$time_iso8601", "uri": "$request_uri", "status": $status, "method": "$request_method", "user_agent": "$http_user_agent" }';
这样即使 $request_uri 含双引号、换行、控制字符,也会被自动转义为 \"、\n 等,确保每条日志是合法、单行、可被 Logstash / Fluentd / jq 正确解析的 JSON。
需要避免的写法
- 不要用 $args 单独拼接日志 —— 它不包含编码信息,且可能含未转义的 & = 等符号,易造成字段错位
- 不要在 log_format 中手动拼接未转义的变量(如
"$uri?$args")—— 查询参数中的特殊字符可能破坏引号结构 - 不要依赖 $document_uri 或 $request_filename 记录路径 —— 它们是文件系统路径,与客户端请求无关,且含服务器本地路径分隔符(如反斜杠),不具可追溯性
调试与验证方法
临时加一条测试 location,用 curl 发送含特殊字符的请求并实时查看日志:
location /test-log {
return 200 "ok";
access_log /var/log/nginx/test.log api_json;
}
执行:curl 'http://localhost/test-log/用户?id=1&path=/a/b/c?x=1'
然后检查 /var/log/nginx/test.log 是否生成单行、合法 JSON,且 "uri" 字段值完整、无截断或乱码。

















