今天遇到一个非常奇怪的站点
http://lianlunchang.com/
或者点击此处
该站点如果通过浏览器去访问则会一直在加载中,直到超时。但是浏览器会正常展示页面信息。小弟想知道如何来实现这类网站的原理。
请各位大大帮忙分析一下这类请求。
这里不涉及这个网站为什么会被拦截,请勿回复这个。我需要知道是为什么这个网站会一直加载,但是页面展示正常。以及如何来通过chrome扩展来判断这个请求是否完毕。
先说明一下这个网站奇怪的点。
一个正常的请求会在chrome的network里面直接展示出来状态以及网站内容大小,加载时间等。但这个网站很特殊。没有展示pending状态,tab栏一直在加载。页面却正常显示出来。且网络请求中并没有其他pending请求。
浏览器不需要等待页面完全加载完才去渲染。
所谓的“页面加载”实质就是一个 HTTP 请求。HTTP 虽然是一个文本协议,但也是基于 Socket 流式传输的。既然是流式的,那服务端就完全可以先只发送一部分数据、但是却不关闭这个流,这样客户端会认为没有接收完而选择继续等待,直到超时。
当然了,这是对于 HTTP/1.1 之前(先忽略 Keep-Alive,它不是重点)。在 HTTP/2 有了多路复用之后,多个 HTTP 请求底下对应的可能是同一个 Socket,这样就不能单纯地把“Socket 关闭”和“响应接收完毕”划等号了 —— A 请求的响应接收完了、B 请求的响应可未必也完了,此时 Socket 并不会关闭。
幸好制订 HTTP 协议时早就考虑好了和底层协议脱钩的事情,它是有
Content-Length
这个响应标头的,它指示了响应体应该有的实际长度,那么当客户端接收到符合的长度后,就认为本次 HTTP 的响应已经接收完毕了。那么反过来想,如果服务端返回了一个错误
Content-Length
,比如返回了 100,但是响应体却只有 99,客户端就会认为本次请求还没结束,那么它就会接着等。你可以用 Wireshark 之类的抓包看一下(需要直接抓 TCP,而不是 DevTools/Fiddler/Charles 这种基于 HTTP 的,因为如上文所言,这个 HTTP 报文会被认为是“不完整的”,所以这些基于 HTTP 的抓包工具是不能正确解析的),观察一下这个请求的实际收到的字节数是不是小于
Content-Legnth
的。回到问题本身,你在 JS 层面上无法判断的,因为浏览器本身屏蔽了底层 Socket 的细节。