HTTP 400 错误 – 请求无效 (Bad request)
HTTP 400 错误 – 请求无效 (Bad request)
介绍—http 400错误.
您的Web服务器认为客户端发送的数据流 (例如您的浏览器或我们的 CheckUpDown 机器人 ) 是 ‘ 畸形的’,即没有完全遵守 HTTP 协议。 因此您的 Web 服务器无法理解和处理该请求。
该错误几乎总是意味着客户端系统以及 / 或者您的Web服务器编程失败。
HTTP 循环中的 400 错误
任何客户端 ( 例如您的浏览器或我们的 CheckUpDown 机器人 ) ,都需要通过以下循环:
从您站点的 IP 名称 ( 即您站点的网址-URL, 不带起始的 ‘http://’) 获得一个 IP 地址。这个对应关系 ( 即由 IP 名称向 IP 地址转换的对应关系 ) 由域名服务器 (DNSs) 提供。
打开一个 IP 套接字 (socket) 连接到该 IP 地址。
通过该套接字写 HTTP 数据流。
从您的Web服务器接受响应的 HTTP 数据流。该数据流包括状态编码, 其值取决于 HTTP 协议 。 解析该数据流得到 状态编码和其他有用信息。
该错误在以上所述的最后一步生成,即当客户端收到 HTTP 状态编码并识别其为 ‘ 400’ 时
解决 400 错误 – 一般方法
在客户端或是Web服务器,或者两端都存在一个低层程序漏洞 (bug) 。 如果您无法进入这些系统的源程序, 您唯一能做的是把该问题提交给开发这些系统的公司的技术支持人员。
==================================
从 nginx 访问日志中的400错误说起
最近在整nginx+php+mysql的网站架设,发现nginx的access.log文件(也就是访问日志)中有大量的400错误,知道HTTP状态码的童鞋都知道这个状态码表示错误的客户端请求,换句话说是服务器无法理解客户端的请求。
服务器中的错误记录类似于这种:
127.0.0.1 – – [01/Oct/2011:11:51:04 +0800] “-” 400 0 “-” “-” “-”
踩点:
经过分析nginx的log文件,发现都是在一次正常访问之后产生的数个400错误,每次有大概连续出现1-6个不等,而且也并不是每次客户访问都会产生400错误。
再观察产生400错误的前一次访问是很正常的,200状态码,正常的文件,正常的来路,正常的User-Agent… 一切都很和谐,那400是肿么来的呢?
通过仔细观察发现,所有产生400错误的前一次访问的User-Agent都是Google Chrome浏览器留下的,也就是说400错误是由Chrome浏览器产生的。但是经过本地抓包发现,chrome是没有向服务器发送异常请求或者数据包的。
在抓包分析中发现,Chrome在访问服务器时发起的连接不止一个,一般有5到6个不等,而如果请求的资源不需要那么多连接时,Chrome就会关闭未用的连接,这项技术叫做pre-connection“预先连接”。
通常我们访问一个网站时,第一个获取的是一个html主文件,而里面链接了网页所需要的css、js、图片等其他媒体资源文件,而一般资源文件和主 html文件是在一个域下的,预先连接就是在获取html之前就建立很多的tcp连接,而不是等到获取到html文件之后再去连接服务器获取其他的文件, 因为连接服务器是需要消耗一些时间的,所以这项技术可以很大程度上加快网页的呈现速度。
如果网页html链接的资源比较少,或者客户端有缓存,不需要连接下载,那么Chrome浏览器发出的5-6个连接很可能只有1个是需要的,其他的 都得关闭掉,这样就产生了一个问题:连接了服务器,而没有发送任何请求。对于这种情况,nginx是当做400错误来处理的,但由于连接已经关闭,错误信 息不会发送到客户端,这就产生了日志文件中记录了错误,而抓包分析中什么也看不到的现象。
测试:
要验证上面的分析结果很简单,打开命令行cmd.exe,在里面输入telnet serverip 80,等待连接成功之后直接关掉cmd,这时去查看nginx的log文件中就多了一条400错误记录。
一句评论:
pre-connection的优点已经很清楚了,但是它也是有缺点的,如果站长做了优化,使用了Cookie-free技术,或者网页和静态资源 使用不同的服务器,那么网页需要的css、js资源就和主html不在同一个域下,也可能不在同一个IP上,那么pre-connection不仅是鸡 肋,而且会对主html服务器产生不必要的负担。
文章出处:http://www.shily.net/topic/speaking-from-400-error-in-nginx-access-logs/