nginx

400 bad request The plain HTTP request was sent to HTTPS port解决办法

现象:https可以访问,但是http报400 bad request错误。
看报错:

400 bad request The plain HTTP request was sent to HTTPS port解决办法
The plain HTTP request was sent to HTTPS port

本以为是个牛逼的配置,没想到报错了。
先查400状态码的解释,HTTP/1.1对400 Bad Request的定义:
1、语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。
2、请求参数有误。

这就很好理解了,我们又没有参数,肯定是第一个原因,我们试图通过HTTP访问网站,这个请求被重定向到HTTPS。
if ($ssl_protocol = “”) {
rewrite ^ https://$server_name$request_uri? permanent;
}
Nginx的配置里是有“ssl on”这一条的,所以肯定使用SSL交互,但是你的request都是HTTP请求,所以就是bad request,于是就是80的请求无法被服务器的443理解。

so,把nginx里的ssl on注释掉,问题解决。


2019年11月2日更新:

最新情况发现,按照以上的解决办法简单注释ssl on,并没有效果,如果用chrome浏览器打开隐私窗口,访问https页面,依据报400错误。用curl来验证:

$ curl -I http://moneyslow.com

HTTP/1.1 400 Bad Request

Server: nginx/1.14.0 (Ubuntu)

Date: Sat, 02 Nov 2019 03:09:46 GMT

Content-Type: text/html

Content-Length: 280

Connection: close

header返回400错误依旧。

实际上,解决方法非常简单。在“listen”字符串下的服务器部分,我只需要添加:

错误页面 497 跳到 https://$host:$server_port$request_uri;

497代码的意思:发送到https端口的http请求,error_page处理此代码并重定向到https://$host:$server_port$request_uri;

这里有3个变量的解释:

$host是表示运行nginx的主机名的保留变量。

$server_port 是监听端口,默认可以不写。

$request-uri是完整的原始请求uri(带参数)。

所以在配置80端口的那部分nginx的配置文件里加一行即可:

server
{
listen 80;
server_name moneyslow.com www.moneyslow.com;
error_page 497 https://$host$request_uri;
rewrite ^(.*)$ https://${server_name}$1 permanent;

}

再次测试:

$ curl -I http://moneyslow.com

HTTP/1.1 302 Moved Temporarily

Server: nginx/1.14.0 (Ubuntu)

Date: Sat, 02 Nov 2019 03:32:32 GMT

Content-Type: text/html

Content-Length: 170

Connection: close

Location: https://moneyslow.com/

生效了。可以在浏览器隐私窗口验证。