https請求報錯:The plain HTTP request was sent to HTTPS port
示例背景描述:
- www.test.com:11001服務需要對互聯網使用https提供服務
- 后端java服務不支持https請求,且后端程序無法修改,僅支持http請求
問題描述:
- 因此在訪問https://www.test.com:11001,URL會跳轉http://www.test.com:11001,然后報錯The plain HTTP request was sent to HTTPS port
報錯如下:
解決思路:通過nginx代理
此處暫時將后端服務器設定為192.168.1.1,具體配置如下:
server {listen 11001;server_name localhost;location / {proxy_pass http://192.168.1.1:11001/;proxy_set_header Host $host:$server_port; # 包含端口號防止丟失proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto https; # 強制設置協議為 HTTPSproxy_set_header X-Forwarded-Port $server_port; # 傳遞端口# 重定向修正proxy_redirect ~^(http://[^:/]+)(:([0-9]+))?/(.*)$ https://$host:$server_port/$4;proxy_redirect ~^(http://)([^/]+)/(.*)$ https://$host:$server_port/$3;# 可選:日志調試access_log /var/log/nginx/redirect_fix.log main;error_log /var/log/nginx/redirect_error.log debug;# 可選配置proxy_connect_timeout 60s;proxy_read_timeout 60s;}# 可選配置error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
關鍵配置說明
1、proxy_redirect 正則表達式?:
proxy_redirect ~^(http://[^:/]+)(:([0-9]+))?/(.*)$ https://$host:$server_port/$4;
- 匹配任何 HTTP 重定向:http://domain:port/path 或 http://domain/path
- 替換為:https://原始域名:11001/path
2、?備用規則?:?
proxy_redirect ~^(http://)([^/]+)/(.*)$ https://$host:$server_port/$3;
- 匹配格式:http://anything/path
- 替換為:https://原始域名:11001/path
3、?強制協議頭部?:
proxy_set_header X-Forwarded-Proto https;
- 即使后端服務不使用這個頭部,也設置它以保持一致性
測試與驗證方法
1、測試配置:
nginx -t
2、重載配置:
nginx -s reload
3、監控日志:
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/redirect_fix.log
tail -f /var/log/nginx/redirect_error.log
4、重新訪問測試
https://www.test.com:11001
常見問題排查表
問題現象 | 可能原因 | 解決方案 |
---|---|---|
重定向循環 | 后端服務也嘗試重定向 | 檢查后端響應是否已經是HTTPS |
端口號不正確 | 正則匹配失敗 | 添加更通用的匹配規則 |
HTTPS證書錯誤 | 證書不匹配 | 檢查SLB證書是否有效 |
404 錯誤 | 路徑被修改 | 檢查正則中的路徑捕獲組 如 $4 和 $3 |
如果上述配置仍有問題,使用這個更強大的版本:
proxy_redirect ~^http(://[^/]+)?(:\d+)?/(.*)$ https://$host:$server_port/$3;
proxy_redirect ~^http(://)([^/]+)/(.*)$ https://$host:$server_port/$3;
proxy_redirect default;
這個規則會:
- 匹配任何以 http 開頭的重定向
- 替換為 https + 原始域名 + 11001端口
- 保留原始路徑不變