HTTP协议
网上有很多与HTTP协议有关的博客或文章。
里面很多讲了关于HTTP的历史,请求和响应的格式等内容,但是我本身觉得这些博客在关于请求和响应方面没有讲得很详细,要么是这个博客写了一部分,那个博客写了一部分,就是没有找到一个博客比较完整的讲清楚段头中每一个字段的具体作用。
因此,在这里忽略了HTTP协议的历史,综合大家的观点和自己的理解,专门陈上关于HTTP协议中报文封装的内容。
PS:本来我是想与计算机网络中的TCP/IP协议结合起来讲的,但是担心有的人看不懂,如果可以的话以后的博客再补充。
请求
从段头中可以看出由3部分组成:请求行,请求头,请求正文
格式:请求方式 资源路径 HTTP版本号<CRLF>举例:GET/test.html HTTP/1.1请求方式:POST,HEAD,OPTIONS,DELETE,TRACE,PUT
2.请求头部格式
关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:用来指定这个请求报文是由谁产生的,通常来说,一般这里设置的是用户所使用的浏览器类型。如User-agent:Mozilla/4.0
Accept:客户端可识别的内容类型列表。如Accept:image/gif,则表明客户端希望接收gif图片数据。Accept:text/html,表明客户端希望接受html文本。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。如www.baidu.com
Location:实现重定向。Location响应报头域常用在更换域名的时候
Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302;
Cache-Control:用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。
Connection:指定与连接相关的属性,如Connection:Keep-Alive,告诉服务器端,我客户端不想使用持久连接,
请服务器端在完成这次请求响应后不要关闭此连接。 Connection:close//关闭连接
Accept-Charset:通知服务器可以发送的编码格式
Accpet-Encoding:通知服务器可以发送的数据压缩格式
Accept-Language:通知服务器可以发送的语言。如Accept-Language:zh_cn
If-Modified-Since:用在缓存策略,记录浏览器本地缓存的文件最后修改的时间。
If-None-Match:浏览器本地缓存数据的某种运算结果,如MD5。
3.回车换行
可以自己用浏览器的开发者功能(F12键)查看不同的信息
响应
200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。
Server:服务器应用程序软件名称和版本Content-Type:响应正文的类型,如Content-Type:text/html;charset=GB2312Content-Length:响应正文的长度,指出数据部分的字节数,即单位ByteContent-Charset:响应正文使用的编码Content-Encoding:响应正文使用的数据压缩格式Content-Language:响应正文使用的语言Date:响应报文被发送出去的时间点Expires:服务器端可以使用Expires域来告诉客户端最多缓存这个数据到什么时间,如果超过这个时间点的话,客户端就不要再缓存这个数据了,而是向服务器端重新发起新的请求。Cache-Control:响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage.Last-Modified:实体报头域用于指示资源的最后修改日期和时间。Etag:通过数据的某个属性值进行某种运算的结果,如MD5。当然不是每一个响应都必定有的必定有的,不同的响应方式不同。
浏览器本地会缓存一些数据,包括网页、图片等,而且还会同时存储这些缓存数据在服务器端的最后修改时间(Last-Modified)。当浏览器再向服务器端发起这些数据的请求时,会同时把这些数据的最后修改时间通过If-Modified-Since一起传给服务器端,服务器端一旦看到这个头部域,就会先拿这个时间戳和相应资源的最后修改时间比较下,如果相同,就说明这个资源一直以来都没有改动过,于是服务器端就不用再把这个数据重复的传给客户端了,而是直接在响应报文中返回304即可,避免了重复传输带来的带宽消耗。区别在于,Last-Modified域是响应报文中使用的,由服务器端发给客户端的;而If-Modified-Since则是用在请求报文中的,由客户端发给服务器端的。这两者都是用绝对时间来表示的,所以存在时间同步的问题。第二点是更好的方案。
这一对兄弟的关系和“Last-Modified/If-Modified-Since”的关系一样,Etags(Entity Tags)是用于响应报文中的,而If-None-Match是用于请求报文中的。这对兄弟的好处在于,他们不是以绝对时间来判断数据是否被修改过,而是通过数据的某个属性值来判断,例如数据的MD5值,这样就可以很好的避免时间不同步的问题了。(除了If-None-Match外,请求报文的头部域中还可以用If-Match、If-Range来表示希望获取的Etag值
其一是Server/User-Agent,Server是服务器端用来亮明身份的,而User-Agent是客户端用来亮明身份的;另一对是Set-Cookie和Cookie,Set-Cookie用于服务器端向客户端设置cookie的,而Cookie则是客户端告诉服务器端自己的cookie的。