$scheme 是 Nginx 内置变量,值为 http 或 https,由 TLS 握手状态直接确定,准确轻量;相比 $server_port 和 $http_x_forwarded_proto,它不依赖端口或可信代理配置,不受伪造头干扰,是日志中识别真实协议最稳妥的选择。

$scheme 是 Nginx 内置的变量,用于表示当前请求所使用的协议类型,其值为 http 或 https(全小写,不含冒号或斜杠)。它不依赖于后端应用或重写规则,而是由 Nginx 在接受客户端连接时根据 TLS 握手状态直接确定,因此准确、轻量、无需额外配置。
为什么 $scheme 比 $server_port 或 $http_x_forwarded_proto 更可靠?
在反向代理或负载均衡场景下,仅靠端口(如 80/443)无法准确判断原始协议:例如 HTTPS 流量可能被边缘节点终止后以 HTTP 转发给 Nginx;而 $http_x_forwarded_proto 易被客户端伪造,需配合严格的信任代理列表(set_real_ip_from)才安全。
$scheme 始终反映 Nginx 实际处理请求时的协议层,不受上游头信息干扰,也不依赖 IP 白名单配置,是日志中区分真实协议最稳妥的选择。
如何在 access_log 中记录并统计 HTTP/HTTPS 占比?
在 Nginx 配置的 log_format 中加入 $scheme,例如:
log_format scheme_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $scheme';
然后在 server 或 http 块中启用该格式:
access_log /var/log/nginx/access.log scheme_log;
日志样例:192.168.1.100 - - [10/Jul/2024:14:22:35 +0800] "GET /api/v1/users HTTP/1.1" 200 1245 "-" "curl/8.6.0" https192.168.1.101 - - [10/Jul/2024:14:23:02 +0800] "GET /about.html HTTP/1.1" 200 3892 "https://example.com/" "Mozilla/5.0" http
后续可用脚本快速统计占比,例如用 awk:
awk '{print $13}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
常见误用与注意事项
-
不要在 rewrite 或 if 中依赖 $scheme 判断跳转逻辑:虽然可用,但更推荐用
listen 443 ssl分离配置,避免条件分支影响性能和可读性 -
HTTP/2 不改变 $scheme 值:即使启用了 HTTP/2,HTTPS 请求的
$scheme仍是https,无需额外适配 -
WebSocket 连接同样适用:当使用
Upgrade: websocket时,$scheme 仍正确反映底层协议(http或https) -
确保日志轮转不截断字段:若使用自定义分隔符(如 JSON 日志),注意
$scheme是纯字符串,无空格,不易引发解析错误











