nginx 默认自动解码url(如%20→空格、%e4%b8%ad→“中”),再匹配location和文件路径;解码后需确保文件系统支持对应编码(如utf-8),且正则匹配应针对解码后的字符串,避免元字符冲突,不支持关闭解码。

Nginx 默认会对 URL 中的特殊字符(如空格、中文、括号、方括号、波浪线等)进行百分号编码(URL encoding),并在内部自动解码后匹配文件路径。但某些情况下,比如静态文件名本身包含 [、]、~、 (空格)、+ 或非 ASCII 字符(如中文),Nginx 可能因解码失败、正则匹配误判或文件系统不支持,导致 404 或 400 错误。关键不是“关闭转义”,而是确保 Nginx 正确解码并安全映射到实际文件路径。
确认文件名是否被正确解码
Nginx 在 location 匹配和 alias/root 路径拼接前,会自动对请求 URI 进行一次标准 URL 解码(RFC 3986)。这意味着:
-
/file%20name.txt→ 解码为/file name.txt→ 查找磁盘上file name.txt -
/测试%e4%b8%ad%e6%96%87.pdf→ 解码为/测试中文.pdf→ 查找对应文件(需文件系统支持 UTF-8 编码) - 但
[(即[)和](即])也能正常解码,前提是未被 rewrite 或 proxy_pass 中途干扰
若出现 400 Bad Request(如含未编码的空格或原始 [),说明客户端发送了非法 URI —— Nginx 拒绝处理,此时应由前端或客户端修复编码,而非在 Nginx 层“绕过”校验。
避免 location 正则中的元字符冲突
当使用正则表达式 location ~ .pdf$ 等匹配时,若文件名含 [、]、.、+、? 等,在 URI 中虽已编码(如 [),但正则引擎匹配的是**解码后的路径字符串**。例如:
- 请求:
/report_v1[draft].pdf→ 解码后为/report_v1[draft].pdf - 若写
location ~ .pdf$,没问题;但若写location ~ ^/.*[.*].pdf$,方括号会被正则当作字符组,必须转义:location ~ ^/.*\[.*\].pdf$ - 更稳妥做法:用前缀匹配(
location /)+try_files,避开正则解析风险
确保文件系统与编码兼容
Nginx 解码后的路径会直接传递给操作系统 open() 系统调用。因此:
- Linux 文件系统(ext4/xfs)本身不强制编码,但 shell 和工具通常按 locale 解释字节 —— 建议服务器 locale 设为
en_US.UTF-8或zh_CN.UTF-8 - 确认静态文件名在磁盘上确实是 UTF-8 字节序列(例如中文名用
ls | hexdump -C验证) - 避免使用
alias拼接含用户输入的路径;优先用root+ 标准层级结构,减少路径构造环节
必要时显式控制编码行为(慎用)
绝大多数情况无需干预默认解码逻辑。仅在极少数场景(如反向代理到不规范后端)才考虑:
- 用
rewrite ... break显式重写 URI,确保目标路径合法(例如把%2B替换为%20) - 启用
underscores_in_headers on仅影响 header,与文件名无关 - 不要设置
decode_percent(该指令不存在)或尝试禁用解码 —— Nginx 不提供关闭 URI 解码的配置,强行规避会导致安全漏洞(如绕过路径限制)











