• http协议进阶(三)http报文


    一、报文流

    http报文是在http应用程序之间发送的数据块(也可称为数据包)、这些数据块以一些文本的元信息(meta-information)开头,描述了报文的内容及含义,后面跟着

    可选的数据部分,这些报文在客户端、服务器和代理之间流动;常说的术语“流入”、“流出”、“上游”、“下游”就是描述报文方向的

     

    1、报文流入源服务器

    http使用术语流入(inbound)和流出(outbound)来描述事务处理的方向;报文流入源服务器,工作完成后,流回用户的Agent代理中,如下图

     

    2、报文向下游流动

    不管是请求还是响应报文,所有报文都会向下游流动,所有报文发送者都在接收者的上游,如下图

     

    二、报文的组成

    http报文是简单的格式化数据块,如下图

    每条报文包含一个客户端请求或者服务端响应,由三部分组成:1)对报文进行描述的起始行;2)包含属性的首部(header)模块;3)可选的,包含数据的主体(body)部分

    起始行和首部就是由行分隔的 ASCII文本。每行都以一个由2个字符组成的行终止序列作为结束,包括一个回车符(ASCII码13)和一个换行符(ASCII码10),这个行终止

    序列可以写为CRLF。(稳健的应用程序也应该接受单个换行符作为行的终止)

    实体或报文的主体是一个可选数据块,与起始行和首部不同的是,主体中可包含文本或二进制数据,也可以为空

    如上图,Content-type行说明了主体是一个纯文本文档,Content-length说明了主体有19字节

     

    1、报文的语法

    所有的http报文都分为请求报文响应报文,请求报文会向服务器发送一个请求动作,响应报文会将请求结果返回给客户端,其结构基本相同;下图显示了获取一张GIF图所需的请求和响应报文

    这是请求报文的格式                                             这是响应报文的格式

    <method> <request-URL> <version>                            <method> <status> <version>

    <headers>                                                   <heraers> 

    <entity-body>                                               <entity-body>

    下面是对各部分的简述:

    方法(method):客户端希望服务器对资源执行的动作,是一个单独的词,比如GET、HEAD、POST等

    之前的博客http://www.cnblogs.com/imyalost/p/5630940.html中有简单介绍几种方法,不过后面会详细解释这些方法

    请求URL(request-URL):命名了请求资源,或者URL路径组件的完整URL;如果直接与服务器进行对话,只要URL的路径是决定路径,通常不会出现问题(上一篇随笔有详细介绍URL......)

    版本(version):报文所使用的http协议版本——HTTP/<major>.<minor>;其中主要版本号(major)和次要版本号(minor)都是整数,本篇后面详解

    状态码(status-code):3位数字,描述请求过程中发生的情况,每个状态码第一位描述状态的一般类别(成功/错误),本篇后面解释http规范的状态码及其含义

    之前的博客http://www.cnblogs.com/imyalost/p/5688169.html也有简单介绍

    状态码还有一种可读版本,包含终止序列之前的版本;比如HTTP/1.1 200 NOT OK和HTTP/1.1 200 OK中原因短语不同,但同样被当做成功指示处理

    首部(header):可以有0个或多个首部,每个首部包含一个名字,后面跟一个冒号,然后一个可选空格,接着一个值,最后是CRLF。首部由一个空行(CRLF)结束,表示首部列表的结束和实体主体的开始。

    实体主体(entity-body):包含一个由任意数据组成的数据块。

     

    2、起始行

    所有http报文都以一个起始行作为开始;请求报文说明了要做什么,响应报文说明发生了什么

    2.1 请求行

    请求报文请求服务器对资源进行一些操作。请求报文起始行,称为请求行,包含一个方法和一个请求。

    该方法描述了服务器应该执行哪些操作,请求URL描述了要对哪个资源执行这个方法,请求行中还包括http版本,告知服务器,客户端使用哪个版本http协议,由空格符分隔

    上图中,请求方法为GET,请求URL为test/hi-there.txt,http版本为1.1。

     

    2.2 响应行

    响应报文承载了状态信息和操作产生的所有结果数据,将其返回给客户端。响应报文起始行,称为响应行,包含了使用的http版本,数字状态码,以及描述操作状态或文本形式的原因短语。

    这些字段由空格符进行分隔,在上图中,http版本为1.0,状态码200(表示成功),原因短语为OK,表示文档被成功返回。

     

    2.3 方法

    请求的起始行以方法作为开始,方法用来告知服务器做什么。如上图,方法就是GET,下表列出一些现版本http有的一些方法

    具体的方法介绍下面会介绍

     

    2.4 状态码

    状态码用来告诉客户端,发生了什么事;状态码位于响应的起始行中。状态码在每条响应报文的起始行中返回的,以一个数字和一个可读的状态组成;数字码便于程序进行差错处理,原因短语则便于理解

    下面列出状态码的分类:

    具体的方法介绍下面会介绍

     

    2.5 原因短语

    原因短语为状态码提供了文本形式的解释,和状态码成对出现,是状态码的可读版本,应用程序将其传给客户,说明在请求期间发生了什么;稍后会整理出一些状态码和其建议使用的一些原因短语

     

    2.6 版本号

    版本号会以http/x、y的形式出现在请求和响应报文的起始行中,为应用程序提供了一种将自己遵循的协议版本告知对方的方式

    通信时最好使请求和响应的版本号保持一致,否则很容易造成误解,使程序无法识别

    PS:版本号不会被当做分数处理,每个数字都是独立的,比如,HTTP/2.22版本高于HTTP/2.3

     

    3、首部

    http首部字段向请求和响应报文中添加一些附加信息;本质来讲,他们知识一些名/值对的列表。

     

    3.1 首部分类

    通用首部:即可出现在请求报文中,也可出现在响应报文中

    请求首部:提供更多有关请求的信息

    响应首部:提供更多有关响应的信息

    实体首部:描述主体的长度和内容,或者资源本身

    扩展首部:规范中没有定义的新首部

    每个http首部都有一种简单的语法:名字后面是冒号(:),然后跟上可选的空格,再跟上字段值,最后以一个CRLF结束

     

    3.2 首部延续行

    将长的首部行分为多行可提高可读性,每行前面至少有一个空格或制表符(tab),例如

    HTTP/1.1 200 OK

    Conteng-Type: image/gif

    Content-Length: 8572

    Server: Test Server

    Version 1.0

    上面的例子,响应报文中包含一个Server首部,其值被划分为多个延续行,该首部完整值为Server: Test Server Version 1.0

     

    4、实体的主体部分

    http报文的第三部分为可选的实体主体部分,实体是主体的http报文的负荷,就是http要传输的内容,资源

    http报文可承载很多类型的数字数据:图片、视频、HTML文档、软件应用程序、电子邮件等

     

    三、方法

    1、GET

    GET是最常用的方法,通常用于请求服务器发送某个资源(资源是已被服务器识别或标识的)给客户端; 如下图

    服务器在获取GET请求参数时用Request.QueryString,意思为获取地址栏中的参数,就是“?”后面的参数,如果是多个,就用&连起来

     

    2、HEAD

    HEAD和GET方法类似,但在响应中只返回首部,不返回实体的主体部分。使用HEAD方法,可以

    *在不获取资源的情况下了解资源的实际情况(资源类型)

    *通过查看状态码,确认资源是否存在(有效性)

    *通过查看首部,测试资源是否被修改(如修改,资源修改时间等)

     

    3、PUT

    与GET相反,PUT方法会向服务器写入文档(有些系统会允许用户创建web界面,并用PUT方法直接将其安装到web服务器上)

    PUT方法实际上就是让服务器用请求中包含的主体部分来创建一个由请求的URL命名的新文档;或者URL已存在的话,就用这个主体来替代它。

    因为PUT允许用户对内容进行修改,所以现在很少用这个方法,如果使用了这个方法,都要求用户使用授权的密码登陆(后面会整理出来关于安全认证的相关内容)

     

    4、POST

    POST方法用来向服务器发送提交数据的请求,具体的内容这里就不赘述了,之前有写过关于这方面的随笔,里面介绍了post及它与get的区别等内容(http://www.cnblogs.com/imyalost/p/5630940.html

     

    5、TRACE

    客户端发起一个请求时,请求可能要穿过防火墙、代理、网关或者其他应用程序,每个中间节点可能都会修改原始的http请求,TRACE允许客户端在最终把请求发给服务器时,查看它最终的样子

    TRACE请求会在目的服务器端发起一个“回环”诊断。最后一站服务器会弹回一个TEACE响应,并在响应报文主体中携带原始请求报文,这样客户端就可以查看在所有中间节点上,原始报文是否被修改或毁坏

     

    6、OPTIONS

    请求web服务器告知其支持的各种功能;可以询问服务器支持哪些方法,或者对某些特殊资源支持哪些方法(有些服务器可能只支持对一些特殊类型的对象使用特定操作)

    为客户端提供了一种手段:不用实际访问资源就可判定访问各种资源的最优方式

     

    7、DELETE

    请求服务器删除请求URL所指定的资源;但客户端应用程序不一定会执行删除操作,因为http协议规范允许服务器在不通知客户端的情况下撤销请求。如下图

     

    8、扩展方法

    http被设计成可扩展的,这样新特性就不会使老的版本失效。扩展方法指的是没在HTTP/1.1中规范定义的,服务器为它管理的资源实现一些HTTP服务,为开发者提供了一种扩展这些HTTP服务能力的手段

    下表列出了一些常用的扩展方法:

    上面例子中的方法便于用过http将web内容发布到web服务器上

    不是所有的扩展都是在正式规范中定义的,因此,扩展方法秉持“对发送内容要求严格,对所接受的内容宽容点”来处理一般的HTTP扩展方法很重要

     

    四、状态码

    响应报文的返回状态码分为五类,之前的随笔进行了介绍,这里就当做是补充吧

    状态码是一种理解事务处理结果的便捷方式;下面列出一些常见的原因短语例子,都是目前最常用的HTTP/1.1规范推荐使用的

    1、100~199——信息性状态码

    100 Continue的目的是对这样的情况进行优化:http客户端应用程序有一个主体的实体部分要发送给服务器,但发送之前希望查看服务器是否会接受这个实体

     

    1.1 客户端与100 Continue

    如果客户端向服务器发送一个实体,并愿意在发送前等待100 Continue响应,那么客户端就要发送一个携带了值为100 Continue的EXpect请求首部;如果客户端没发送实体,

    就不应发送100 Continue Expect首部。因此客户端只有在避免向服务器发送一个服务器无法处理或使用的较大的实体时,才应使用100 Continue

    解决办法:发送了100 Continue的Expect首部值的客户端不应一直等待响应,超过一定时间(可设置),自动将实体发送出去;同时做好应对非预期100 Continue响应的准备

     

    1.2 服务器与100 Continue

    如果服务器收到带有值为100 Continue的Expect首部请求,它会用100 Continue或一条错误码来响应;服务器永远不应向没有发送100 Continue请求的客户端发送100 Continue状态码

    如果服务器在发送100 Continue响应前收到部分或全部实体,说明客户端决定继续发送数据,此时,服务器不需要发送这个状态码,但读完请求,应继续返回一个最终状态码(跳过100 Continue状态)

    如果服务器收到带有100 Continue的请求,且它决定在读完实体主体前结束请求,就不应仅仅发送一条响应并关闭连接,这样会影响客户端接收响应

     

    1.3 代理与100 Continue

    代理从客户端收到带有100 Continue期望的请求,有以下几种情况:

    如果知道下游服务器是http/1.1兼容或不清楚下游服务器与哪一个版本兼容,应将Expect首部放在请求中向下转发

    如果知道下游服务器只能与http/1.1以下的版本兼容,就应该以417 Expectation Failed错误进行响应

    如果代理决定代表与http/1.1或之前的版本兼容的客户端,在其请求中放入Expect首部和100 Continue值,那么它不应将100 Continue转发给客户端

     

    2、200~299——成功状态码

    下面列车一些服务器用来表示成功的状态码,分别对应不同的请求

     

    3、300~399——重定向状态码

    告知客户端使用替代位置来访问它感兴趣的资源;或提供一个替代的响应而不是资源内容

    或在资源已被移动情况下,发送一个重定向状态码和一个可选的Location首部告知客户端,资源已被移动,且在哪里可以找到寻找的资源,如下图:将请求重定向到新的位置

    可通过某些重定向状态码对资源的应用程序本地副本与源服务器上的资源进行验证;比如http应用程序可以查看本地资源是否是最新的或者是否被修改过

    总之,对那些包含了重定向状态码的非HEAD请求进行响应时,最好包含一个实体,其实体中包含描述信息和指向(多个)重定向URL的链接——如上图第一个响应报文

    下表列出已定义的重定向状态码:

    上面302、303于307状态码之间存在一些交叉,区别在于HTTP/1.0和HTTP/1.1对其的处理方式:

    HTTP/1.0发起一个POST请求,并在响应中收到302重定向状态码时,它会接受Location首部重定向的URL,并向那个URL发起一个GET请求

    如果HTTP/1.0服务器收到来自HTTP/1.0客户端的POST请求之后,发出302状态码,服务器希望客户端能接受重定向URL并向重定向URL发一个GET请求

    但是,HTTP/1.1规范使用303状态码来实现以上行为(服务器发送303状态码重定向客户端的POST请求,在其后面跟上一个GET请求)

    为规避上述问题,HTTP/1.1规范:对于HTTP/1.1客户端,用307来取代302状态码进行重定向(保存302状态码,留待HTTP/1.0使用→→服务器遇到类似情况需要先检查客户端HTTP版本)

     

    4、400~499——客户端错误状态码

    有时候客户端会发送一些服务器无法处理的请求,比如格式错误的报文或者不存在的URL,服务器会返回给我状态码告诉我们它的反应

    很多客户端错误都由浏览器处理,只有少量错误,比如404,会被用户看到;下表列出各种客户端错误状态码

     

    5、500~599服务器错误状态码

    有时客户端发起一个请求,但服务器由于本身缺陷或子元素出错时,会出现此类问题,服务器返回5XX代码来描述遇到的问题

    下表列出一些已定义的服务器错误状态码

     

     
  • 相关阅读:
    linux安装日志切割程序
    Linux下安装JDK
    深入理解Java注解类型(@Annotation)
    23种设计模式--代理模式-Proxy
    23种设计模式--建造者模式-Builder Pattern
    23种设计模式--工厂模式-Factory Pattern
    23种设计模式
    Java集合框架学习笔记
    MySQL入门笔记(一)
    二进制运算基础
  • 原文地址:https://www.cnblogs.com/insane-Mr-Li/p/10142465.html
Copyright © 2020-2023  润新知