一点一滴成长

导航

http首部字段

 以下内容大都转载和参考自《图解HTTP》

通用首部字段:

1、Cache-Control, 控制缓存的行为,多个指令之间通过“,”分隔,如Cache-Control: private, max-age=0, no-cache。缓存是指代理服务器(缓存服务器是代理服务器的一种)或客户端本地磁盘内保存的资源副本,即使存在缓存,也会因为客户端的要求或缓存的有效期等因素向源服务器确认资源的有效性。

缓存请求指令:

no-cache,防止接收过期的资源,指示代理服务器(缓存服务器)每次都向源服务器确认资源的有效期。
no-store, 不缓存该请求的任一部分,暗示请求中包含机密信息。
max-age=[秒], 参数值必须,如果缓存服务器上的缓存资源的时长比该值小则接收缓存的资源,该值如果为0的话通常缓存服务器会将请求转发给源服务器。http/1.1版本的服务器会优先处理max-age而忽略掉Expires,http/1.0版本服务器则相反。

                
max-stale(=[秒]),即使缓存资源已过期,只要在指定时间内则接收响应资源,不指定参数值的话表示不论过了多久都接收响应。
min-fresh=[秒],参数值必须,指定服务器返回还未过指定时间的缓存资源。
no-transform,缓存不能改变主体的媒体类型,防止代理压缩图片等操作。
only-if-cached, 只请求缓存服务器上的缓存资源,不对缓存资源有效期确认,如果缓存服务器的本地缓存无响应则返回状态码504 Gateway Timeout。

缓存响应指令:

public, 可以使用缓存。

private, 指示代理服务器(缓存服务器)只对特定用户提供资源缓存服务。
no-cache(=[value]), 参数值可选,当指定参数值后指示缓存服务器不再对资源进行缓存,如Cache-Control: no-cache=Location。
no-store, 不缓存该响应的任一部分,暗示响应中包含机密信息。
no-transform, 缓存不能改变主体的媒体类型,防止代理压缩图片等操作。
must-revalidate, 指示代理服务器在返回响应的缓存资源前向源服务器验证该缓存目前是否有效,如果代理无法连接源服务器的话会返回504 Gateway Timeout状态码,使用该指令会
忽略请求的max-stale指令。
proxy-revalidate,指示代理服务器对缓存资源的有效性进行确认。
max-age=[秒], 参数值必须,指示缓存的有效时间,缓存服务器在该时间内不必再向源服务器确认缓存资源的有效性。
s-maxage=[秒], 参数值必须,与max-age功能相同,不同的是该指令只适用于供多位用户使用的公共缓存服务器,使用该指令后会忽略对Expires首部字段及max-age指令的处理。

  另外,可以使用自定义的指令,但这种扩展的指令仅对能理解它的代理服务器有意义。如下的community指令,Cache-Control本身没有这个指令,如果缓存服务器不能理解这个指令,则会忽略它:

Cache-Control: private, community="UCI"

2、Connection,管理持久连接和控制不再转发的首部字段。如当服务器想明确断开连接的时候发送首部Connection: close。

    在http/1.1之前版本协议上使用持久连接的话客户端需要发送Connection: Keep-Alive(服务端会返回Connection:keep-alive的响应以指示客户端可以重用连接)。而在HTTP1.1中默认就是长连接(指定的时间内没有数据传输的话才关闭连接),如果客户端不希望使用长链接的话需要指定首部Connection: close。使用长连接的好处如下图所示:

         

    可以设置Keep-Alive模式的属性,通过Keep-Alive首部,如下所示表示这个TCP通道可以保持5秒,而且这个长连接最多接收100次请求就断开:

      Keep-Alive: timeout=5, max=100
      Connection: Keep-Alive

    下面是使用QQ浏览器向Tomcat服务发送一个普通请求和应答的HTTP包的首部和头,可以看到Tomcat返回的应答中Keep-Alive超时值为20秒,超过该值没有数据传输的话Tomcat服务会自动关闭该连接,Tomcat中配置该超时值的话在server.xml 中的Connector元素的keepAliveTimeout:

   

   

 

    Connection: Upgrade则是指示不再转发Upgrade首部。

3、Date,表明创建http报文的日期时间,如Date: Tue, 03 Jul 2012 04:40:59 GMT,还有另外一种格式与C中asctime()输出格式一致。

4、Pragma,http/1.1之前版本的遗留字段,只用在客户端发送的请求中,要求所有的中间服务器不返回缓存的资源:Pragma: no-cache。如果所有的中间服务器都使用http/1.1版本的话则应直接使用Cache-Control: no-cache。

5、Trailer,指示在报文主体之后记录了那些首部字段,Trailer用在http/1.1响应首部中允许发送方在分块发送的消息后面添加额外的元信息,如:

    

6、Transfer-Encoding,设置传输报文主体时的编码方式为分块编码传输:Transfer-Encoding: chunked。

  通常情况下,HTTP的响应消息体 message body 是作为整包发送到客户端的,用头『Content-Length』 来表示消息体的长度, 这个长度对客户端非常重要,因为对于持久连接TCP并不会在请求完立马结束,而是可以发送多次请求/响应,客户端需要知道哪个位置才是响应消息的结束,以及后续响应的开始,因此Content-Length显得尤为重要,服务端必须精确地告诉客户端 message body 的长度是多少, 如果Content-Length 比实际返回的长度短,那么就会造成内容截断,如果比实体内容长,客户端就一直处于pendding状态,直到所有的 message body 都返回了请求才结束。

  分块编码传输是另一种解决方案:它把数据分解成一系列数据块,并以多个块发送给客户端,服务器发送数据时不再需要预先告诉客户端发送内容的总大小,只需在响应头里面添加Transfer-Encoding: chunked,以此来告诉浏览器我使用的是分块传输编码,这样就不需要 Content-Length 了,这就是分块传输编码 Transfer-Encoding 的作用。分块编码必须以0长度的块结束,如下指定了使用分块传输编码,且被分成3312字节和914字节大小的两块数据:

  HTTP 1.1引入分块传输编码提供了以下几点好处:

 ①、HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久连接。通常,持久链接需要服务器在开始发送消息体前发送Content-Length消息头字段,但是对于动态生成的内容来说,在内容创建完之前是不可知的。[动态内容,content-length无法预知]

 ②、分块传输编码允许服务器在最后发送消息头字段。对于那些头字段值在内容被生成之前无法知道的情形非常重要,例如消息的内容要使用散列进行签名,散列的结果通过HTTP消息头字段进行传输。没有分块传输编码时,服务器必须缓冲内容直到完成后计算头字段的值并在发送内容前发送这些头字段的值。[散列签名,需缓冲完成才能计算]

 ③、HTTP服务器有时使用压缩 (gzip或deflate)以缩短传输花费的时间。分块传输编码可以用来分隔压缩对象的多个部分。在这种情况下,块不是分别压缩的,而是整个负载进行压缩,压缩的输出使用本文描述的方案进行分块传输。在压缩的情形中,分块编码有利于一边进行压缩一边发送数据,而不是先完成压缩过程以得知压缩后数据的大小。[gzip压缩,压缩与传输同时进行]

  比如下面为使用浏览器(70.21)向服务器(70.5:8080)请求一个页面的抓包,一开始浏览器创建了两个连接(一个端口为2388,一个为2389),这应该是浏览器为了提高效率所以提前多创建一个连接,这个跟浏览器特性有关,其它浏览器可能只会建立一个连接。可以看到,564-569为三次握手,790-934为四次挥手,570-573是浏览器请求网页数据和服务的应答,574-577为浏览器请求图标和服务的应答。

   在571行有"tcp segment of a reassembled pdu"信息,表示HTTP分块传输,点击该行如下可以看到里面有头Transfer-Encoding: chunked,实体之前有首块的长度,可以看到这个长度文本显示为"18",是十六进制,转换成十进制的话是24,与要发送的实体数据大小相同:

  

   点击572行可以看到分块的提示以及0长度的结尾块:

 上面的测试Web服务使用的是Tomcat,所以Tomcat默认会使用分块编码?

7、Upgrade,检测能否使用更高版本的协议进行通信,因为Upgrade仅限于客户端和连接服务器之间,所以还需要额外指定Connection: Upgrade:

  可以使用Upgrade来建立WebSocket通信方式。传统的HTTP协议是一种请求-响应模型,如果浏览器不发送请求,那么服务器无法主动给浏览器推送数据。如果想要定期或不定期给浏览器推送数据的话,可以使用WebSocket。

  客户端发送请求时,附带如下的几个头,就表示客户端希望升级连接,变成长连接的WebSocket:

  服务器返回如下的响应表示升级成功,客户端收到成功响应后表示WebSocket“握手”成功,服务器可随时向浏览器推送消息,浏览器也可随时向服务器推送消息:

 

  WebSocket是建立在Http基础上的协议,因此,连接的发送方仍是客户端,确立WebSocket通信连接后服务端可以不必等待请求而直接向客户端推送数据,而且WebSocket是一直保持连接状态,首部信息量比Http要小。为了实现WebSocket通信,需要在HTTP连接建立后完成一次“握手”步骤:如下所示客户端通过使用HTTP的Upgrade首部字段,Upgrade用来告诉服务器通信协议发生改变,Sec-WebSocket-Key字段内记录着握手过程中必不可少的值,base64 编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,Sec-WebSocket-Protocol字段内记录使用的子协议。

   

  对于客户端的握手请求,服务器返回状态码101 Switching Protocols的响应,如下所示,Sec-WebSocket-Accept字段值是由客户端握手请求中的Sec-WebSocket-Key的字段值生成的(采用与客户端一致的密钥计算)。

   

  成功握手确立WebSocket连接之后,通信不再使用Http的数据帧,而采用WebSocket的数据帧。

   

  JavaScript可以调用"The WebSocket API"(W3C标准制定)内提供的WebSocket程序接口,以实现WebSocket下的全双工通信:

var ws = new WebSocket(“ws://echo.websocket.org:12010”); //Websocket 依然使用 80 端口,运行在 TLS 上则使用 443 端口,也可以指定新的端口
 ws.onopen = function(){ws.send(“Test!”); }; //客户端连接成功触发 onopen 消息
 ws.onmessage = function(evt){console.log(evt.data);ws.close();}; //收到服务端数据触发onmessage消息
 ws.onclose = function(evt){console.log(“WebSocketClosed!”);}; //关闭连接触发onclose消息
 ws.onerror = function(evt){console.log(“WebSocketError!”);}; //连接/发送/接收失败触发onerror消息

8、报文在经过代理或网关时,会在首部字段Via中附加该服务器的信息(使用的http版本等),Via首部是为了追踪传输路径,其经常和TRACE方法一起使用,比如代理服务器收到由TRACE方法发送过来的请求,当Max-Forwards: 0时代理服务器不再转发该请求,这时代理服务器将自身信息写入Via首部后返回该请求的响应。

 

9、Warning,该首部通常告知用户一些与代理缓存相关的问题的警告,Warning首部的格式及警告码内容如下:

 

 

请求首部字段:

  1、Accept,通知服务器 用户代理(浏览器)能处理的媒体类型及其优先级,如text/*,image/*,*/*表示所有,媒体类型之间使用逗号分隔。常见的媒体类型如下所示,其中q用来指示优先级,q的值从0.0到1.0,默认为1.0:

  

  

  2、Accept-Charset, 通知服务器 用户代理(浏览器)支持的字符集及字符集的优先级,如Accept-Charset: iso-8859-5, unicode-1-1;q=0.8。

  3、Accept-Encoding,通知服务器 用户代理(浏览器)支持的内容编码(压缩类型)及编码的优先级,常见的内容编码有gzip、compress、deflate、identity(不执行压缩的默认编码格式),如Accept-Encoding: gzip, deflate,另外除了可以使用q来指定优先级外也可以使用通配符*来指定任意的编码格式。

  4、Accept-Language, 通知服务器用户代理(浏览器)支持的自然语言集及其优先级,如Accept-Language: zh - CN, zh; q = 0.8, en; q = 0.2 表示优先选择简体中文,其次选择中文,最后选择英文,q表示权重。

  5、Authorization, 告知服务器用户代理的认证信息(证书值),如下所示,关于Authorization认证的具体可以参考https://www.cnblogs.com/milanleon/p/9868684.html 中用户身份认证部分:

  

  6、Expect, 客户端发送Expect:100-Continue握手的目的,是为了在客户端在发送请求内容之前,判断源服务器是否愿意接受请求(基于请求头部)。 xpect:100-Continue握手需谨慎使用,因为遇到不支持HTTP/1.1协议的服务器或者代理时会引起问题。

  7、From,告知服务器使用用户代理的用户的电子邮箱地址。

  8、Host,  告知服务器请求的资源所处的互联网主机名和端口,如Hots: www.hackr.jp:80,端口号省略的话http则使用默认端口80,https使用默认端口443。Host首部字段是HTTP/1.1中唯一一个必须包含在请求内的首部字段,如果服务器未设定主机名则Host值为空即可。

        如下图表示使用GET方法请求域名为www.hackr.jp的根目录里的index.html文件,服务器收到后返回index.html文件。

       

       首部字段Host和以单台服务器分配多个域名的虚拟主机的工作机制有很密切的关联,这是首部字段Host必须存在的意义。请求被发送至服务器时,请求中的主机名会用IP地址直接替换解决。但如果这时,相同的IP地址下部署运行着多个域名,那么服务器就会被无法理解究竟是哪个域名对应的请求。因此,就需要使用首部字段Host来明确指出请求的主机名。

  9、If-Match, 只有当If-Match的字段值跟请求资源的ETag值匹配时服务器才接受请求(这时的服务器无法使用弱ETag值),否则返回状态码412 Precondition Failed响应:

  

  If-None-Match, 只有当If-Match的字段值跟请求资源的ETag值不匹配时服务器才接受请求,使用它可以获取最新的资源。

  If-Modified-Since,请求的资源在指定日期后发生了更新服务器才接受请求,否则返回304 Not Modified(首部字段Last-Modified可以获取资源的更新日期),其作用与If-Match类似:

  

  If-Unmodified-Since, 请求的资源在指定日期后未发生更新服务器才接受请求,否则返回412 Precondition Failed响应。

  If-Range、Range, 请求的资源指定的ETag值或时间匹配时则可作为范围请求处理,否则返回全部资源:

  

  10、Max-Forwards,通过TRACE或OPTIONS方法发送包含首部字段Max-Forwards的请求时,可以指定经过的服务器最大数目,当服务器收到收到值为0的请求时不再进行转发,直接返回响应,对此我们可以确定那台终点服务器的通信状态:

  

  

  11、Proxy-Authorization, 接收到从代理服务器发来的认证质询时,客户端会发送包含该首部字段的请求,以告知认证所需要的信息,客户端与服务器之间的认证则使用首部字段Authorization。

  12、Referer,告知服务器请求的原始资源的URI,告诉服务器我是从哪个页面链接过来的,服务器藉此可以获得一些信息用于处理,比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站:

  

  13、TE,告知服务器客户端能够处理响应的传输编码方式及相对优先级,与Accept-Encoding相像,但是用于传输编码。

  14、User-Agent,传达浏览器或代理服务器的种类或名称,例如Chrome浏览器的标识类似Mozilla/5.0 ... Chrome/79,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...) like Gecko 。由网络爬虫发起请求时,有可能在该字段内添加爬虫作者的电子邮件地址:

  

响应首部字段:

  1、Accept-Ranges, 范围请求可不可以被处理,Accept-Ranges: none表示不能处理范围请求,Accept-Ranges: bytes表示可以处理范围请求。

  2、Age, 告知客户端资源缓存的时间,如Age: 600表示资源距上次请求已经过了600秒,代理创建响应时必须加上该首部字段。

  3、ETag, 告知客户端实体标识,ETag值是服务器给每个资源分配的唯一性标识,如ETag: "82e323200c392ff89323acd12",当资源更新后其ETag值也会变化,如下。强ETag值是指实体发生细微变化就会改变ETag值,弱ETag值只有当资源发生根本改变产生差异时才会更新,弱ETag值会在字段值前加一个"W/",如ETag: W/usagi-1234。

  

  4、Location, 提示浏览器重定向到另一个URI位置,该字段一般会配合3xx: Redirection的响应:

  

  5、Proxy-Authenticate,将代理服务器所要求的认证信息发送给客户端,如Proxy-Authenticate: Basic realm="Usagidesign Auth"。服务器与客户端之间进行认证时,首部字段WWW-Authorization有着相同的作用。

  6、Retry-After,告诉客户端在指定的秒数后或指定的时间(GMT格式)再次发起请求,主要配合状态码503 Service Unavailable响应或3xx Redirect响应使用。

  7、Server, 告知客户端http服务器信息,如Server: Apache/2.2.6。

  8、Vary, 对缓存进行控制,源服务器会向代理服务器传达关于本地缓存使用方法的命令:

  9、WWW-Authorization,通知客户端适用于请求URI所指定资源的认证方案(Basic或Digest)和带参数提示的质询,状态码401 Unauthorized响应中肯定带有该首部字段,如WWW-Authorization: Basic realm="Usagidesign Auth"。

实体首部字段:

  在请求和响应的HTTP报文中都含有与实体相关的首部:

  1、Allow,当服务器收到不支持的方法请求时,会返回405 Method Not Found,并将其支持的方法写入到Allow首部字段中,如Allow: GET, HEAD。

  2、Content-Encoding,告知客户端服务器对实体主体部分选用的内容编码方式,如Content-Encoding: gzip。

  Content-Language, 告知客户端实体主体使用的语言,如Content-Language: zh-CN。

  Content-Length, 实体主体部分的大小(字节),对实体主体进行内容编码传输时,不能使用该首部字段。

  Content-Location, 指定报文主体返回资源对应的URI,比如,当返回的内容页面与实际请求的对象不同时,在该首部字段内写入URI。

  Content-MD5,报文主体的MD5值,使用Base64编码。

  Content-Range, 针对范围请求,告知客户端返回的实体的范围及整个实体的大小,如:Content-Range: bytes 5001-10000/10000。

  Content-Type, 实体主体内对象的媒体类型,和首部字段Accept一样采用type/subtype形式,如Content-Type: text/html; charset=UTF-8。

  3、Expires,告知客户端或缓存服务器资源失效时间,超出该时间后缓存服务器应该从源服务器获取该资源,如Expires: Wed, 23 May 2012 09:59:55 GMT。源服务器不希望缓存服务器缓存的时候可以将该字段写入与Date相同的时间值。

  4、Last-Modified, 指明资源最新修改的时间,如Last-Modified: Wed, 23 May 2012 09:59:55 GMT。

非http/1.1标准首部字段

  一些非http/1.1标准首部字段常用的有Cookie、Set-Cookie、Content-Dispositison、X-Frame-Options,其它还有X-XSS-Protection、DNT、P3P等。

1、Cookie、Set-Cookie用来为Cookie服务,Cookie是由服务器端生成,发送给User-Agent,浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器。Set-Cookie属于响应首部字段,包含了状态管理所使用的Cookie信息,Cookie属于请求首部字段,用来通知服务端当前页面的域生效中的cookie,如下为一个包含cookie信息的响应报文:

HTTP/1.1 302 Found
Date: Mon, 13 Nov 2017 00:46:23 GMT
Server: Apache/2.2.22 (Win32) PHP/5.3.13
X-Powered-By: PHP/5.3.13
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: CHNCOOKUID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/my
Set-Cookie: CHNCOOKSTA=Y; expires=Mon, 13-Nov-2017 00:46:22 GMT; path=/my
Set-Cookie: PHPSESSID=ufhulbiv2oa0fcb1m06kfm7851; path=/
Set-Cookie: _beta_view_id=2; expires=Tue, 14-Nov-2017 00:46:25 GMT; path=/
Set-Cookie: CHNPOPUREG=yiyiyide%40163268.com; expires=Wed, 13-Dec-2017 00:46:25 GMT; path=/; domain=charmdate.com
Set-Cookie: vpstat_c=4MA%3D%3D; expires=Tue, 14-Nov-2017 00:46:25 GMT; path=/
Set-Cookie: vpstat_l=8QzEwMDAwMA%3D%3D; expires=Tue, 14-Nov-2017 00:46:25 GMT; path=/
Set-Cookie: CHNCOOKUID=yiyiyide%40163268.com; expires=Wed, 14-Nov-2018 00:46:25 GMT; path=/
Set-Cookie: CHNCOOKSTA=Y; expires=Wed, 14-Nov-2018 00:46:25 GMT; path=/
Location: /my/overview.php
Content-Length: 0
Keep-Alive: timeout=5, max=96
Connection: Keep-Alive
Content-Type: text/html

  Set-Cookie字段的属性必须包含赋予cookie的名称和值,其它属性有:

    expires,cookie的有效期,不指定的话则默认为浏览器关闭为止,如果设置一个过去的时间,浏览器会立即删除该cookie。
    path,将服务器上指定文件目录作为cookie的适用对象,若不指定则默认为文档所在的文件目录。
    domain,作为cookie适用对象的域名(结尾匹配,比如指定example.com后,除example.com外,www.example.com和www2.example.com都可以发送Cookie),若不指定则默认为创建cookie的服务器的域名。
    secure,仅在https通信下才会发送cookie,指定secure属性的方式如:Set-Cookie: name=value, secure。
    HttpOnly,使JavaScript脚本无法获得cookie,其主要目的是为防止跨站脚本攻击(XSS)对cookie信息的窃取。

2、Content-Dispositison用来指示如何显示附加的文件,即设置Content-Disposition告诉浏览器下载文件的名称和是否在浏览器中内嵌显示,如:

  Content-disposition: inline; filename=1502849449726.jpg表示浏览器内嵌显示一个文件。

  Content-disposition: attachment; filename=1502849449726.xlsx表示弹出下载提示对话框来下载文件。

3、X-Frame-Options属于http响应首部,用来控制网站内容在其它web网站的Frame标签内的显示,其主要目的是为了防止点击劫持(clickjacking)攻击,如将其设为字段值DENY的话就是拒绝,页面不能被嵌入到任何iframe或frame中,SAMEORIGIN则为页面只能被本站页面嵌入到iframe或者frame中(比如当指定http://hackr.jp/sample.html页面为SAMEORIGIN时,hackr.jp上所有页面的frame都被允许可加载该页面,其它域名的页面就不行),ALLOW-FROM:页面允许frame或frame加载。

posted on 2019-05-21 15:56  整鬼专家  阅读(944)  评论(0编辑  收藏  举报