nginx 默认合并多个斜杠,需通过 rewrite 或 map 实现 url 规范化:用 if 匹配 // 并 301 重定向,或用 map 预处理 uri 后比对跳转,避免 merge_slashes off 等错误配置。

Nginx 默认会自动合并 URL 中的多个斜杠(如 // → /),所以它本身不会生成或保留无协议头的双斜杠 URL,更不会“自动重写修正”这类 URL。你真正需要的,不是让 Nginx 修正双斜杠,而是:
当客户端意外发出含 // 的请求(如 example.com//api/v1)时,如何统一重定向为规范形式(如 example.com/api/v1)?
这属于 URL 规范化(Normalization),而非保留双斜杠——后者需关闭 merge_slashes off,但那是反向需求。
以下是实用、安全、可落地的配置方案:
显式检测并重定向双斜杠路径
用 rewrite 指令匹配 URI 中连续两个及以上斜杠(// 或 /// 等),强制 301 跳转到标准化路径:
server {
listen 80;
server_name example.com;
# 在 location 外或最外层 location 中处理,避免嵌套干扰
if ($request_uri ~ "^/+(.*)") {
set $clean_path $1;
rewrite ^/(.+)$ /$clean_path permanent;
}
# 更精准:只匹配含 "//" 的路径(不误伤根路径 "/")
if ($request_uri ~ "//") {
rewrite ^(.*)//+(.*)$ $1/$2 permanent;
}
location / {
# 正常代理或静态服务
proxy_pass http://backend;
proxy_set_header Host $host;
}
}
⚠️ 注意事项:
-
if块在server级使用是安全的(官方允许),但不要嵌套在location内滥用; -
permanent会返回 301,浏览器缓存该跳转,适合生产环境;若需临时调试,改用redirect(302); - 正则
^(.*)//+(.*)$可匹配任意位置的//(如/a//b///c→/a/b/c),一次清理所有多余斜杠。
更健壮的方案:用 map 预处理 + rewrite
避免 if 的潜在风险,推荐用 map 提前标准化 URI:
http {
map $request_uri $normalized_uri {
"~^([^?]*)//+(.*)$" "$1/$2";
"~^(.*)\?(.*)$" "$1?$2"; # 保留查询参数
default $request_uri;
}
server {
location / {
if ($normalized_uri != $request_uri) {
return 301 $scheme://$host$normalized_uri;
}
proxy_pass http://backend;
}
}
}
这个写法逻辑清晰:先映射出标准化 URI,再比对是否变化,变化则 301 跳转——无副作用,兼容带参数的 URL。
不推荐的做法
- 开启
merge_slashes off:这会让 Nginx 保留双斜杠,而不是修正它,与你的目标相反; - 在
if中混用rewrite和proxy_pass:易引发循环或不可控行为; - 依赖浏览器自动修正:不同客户端处理不一致,不可靠。
实际部署时,建议加一条日志确认效果:
log_format debug_uri '$remote_addr - $request_uri → $normalized_uri'; access_log /var/log/nginx/debug.log debug_uri;
这样就能稳定、可验证地把 // 请求转成标准单斜杠链接。











