工具箱Java学习笔记技术干货

《HTTP权威指南》学习总结(上)

2017-02-05  本文已影响3666人  EakonZhao

写在前面:
因为想了解一些关于反向代理以及负载均衡等中间件的知识,所以在此之前就打算把计算机网络相关的一些东西回顾一下。所以从刚放寒假那会儿就开始看《HTTP权威指南》(后面统称指南)。书中的内容非常丰富,关于HTTP的各个方面都有所涉及。但是由于出版时间较长,书中很多东西放到现如今来看已经是过时的东西了。故本人又买了一本《图解HTTP》(后面统称图解)。两书相较,其实内容大部分都相同,只不过后者针对HTTP 2.0等较新的知识做了简要介绍。其实个人觉得指南一书不必深究,但是基本知识必须掌握,可以当作字典用。而图解一书内容比较精炼,可以当作备忘使用手册使用。

因为最近一直在做客所以没有写读书笔记,一直拖到大年初六初七才动笔,实属不该。本文主要是针对本人学习《HTTP权威指南》一书的学习心得等进行记录。如果有表述不当或者是表达错误的地方,烦请在评论区指正!

总结我将分为两部分

HTTP概述

HTTP是什么?

HTTP是一种用于在通信双方(通常是客户端和服务器端)传输数据(包括但不限于图片、文本、音频等)的可靠的数据传输协议。值得注意的是,这里的可靠指的并不是信息不会被第三方窃取,而是说HTTP协议在大部分时候可以确保数据在传输的过程中可以保持有序和完整。若想保证使用HTTP协议传输数据不被窃取,需要一种安全的HTTP形式(后面会介绍)

略微详细地说说HTTP是如何工作的

客户端通过向服务器端发送HTTP请求报文请求所需资源。通常这个请求是通过访问URL发起的。服务器端接收到请求报文之后再解析报文,识别出客户端所需的资源并从对应的存储区域取到该资源,然后生成HTTP相应报文并附带状态码以及对应的资源返回给客户端,一次HTTP请求和相应的过程到此结束。有时客户端可能并不是想获得某种资源,而是想更改或者是删除服务器端上的某个资源。其实过程都是类似的,只不过是请求和响应报文中的内容有所不同。(这里的内容指的是报文本身,而不是单独说报文的主体部分。因为首部等也会有差别)

资源

Web服务器是Web资源的宿主。Web资源是Web内容的源头。最最简单的Web资源就是一些静态文件。这些文件可以包含任意内容:文本文档、HTML页面、各种格式的图片、音频等其他所有我们可以想到的格式。
但是呢,资源不一定是静态文件,也可以是根据我们的需要动态生成的内容。比如说股票行情的走势或者是天气预报等等。

媒体类型

Web服务器在回送HTTP对象数据的时候会加上一个MIME类型,即告诉客户端返回的是什么类型的数据。通常客户端都会查看响应报文中标明的MIME类型,以此来判断自己是否有能力处理服务器返回的内容。

与数据内容一起回送的MIME类型
部分MIME类型:常见的MIME类型有几百个,这里不一一列举
  • text/html:HTML格式的文本文档

URI(统一资源标识符)

每个Web服务器资源都拥有其特有的名字,这样才能使得客户端准确地向服务器端发送资源请求的报文。而服务器资源名被称为统一资源标识符(Uniform Resource Identifier),即URI。URI就像邮政地址一样,可以唯一标识对应的资源。

形如 http://jwc.jxnu.edu.cn/images/new/banner1.jpg 就是某网站中一张图片资源的URI:

其实URI有两种形式,分别为URL(Uniform Resource Locators)统一资源定位符和URN(Uniform Resource Names)统一资源名称。

URL(统一资源定位符)

URL是URI最常见的表现形式。URL描述了一台特定服务器上某资源的特定位置。它们可以明确地说明应该使用何种服务,如何从一个精确、固定的位置获取资源。其实http://jwc.jxnu.edu.cn/images/new/banner1.jpg就是一个URL。
大部分的URL都遵循一种特定的格式:

URN(统一资源名称)

URI的第二种形式就是URN。URN是作为特定资源的唯一名称使用的,与目前资源的存储地址无关。主要作用是用来标明资源的名称,这个名称在特定的命名空间中。因此,我们也许可以通过不同的协议来访问该资源。

那么URI、URL以及URN三者之间到底存在什么关系呢?

依照我的理解,我觉得URI(Uniform Resource Indentifier)重点在Indentifier,即标识。什么意思呢?就是URI可以确切地标识一个资源。它不仅可以通过网络地址标识资源,还可以在某个命名空间中对资源进行标识。URL和URN分别是URI的两种表现形式。URL的侧重点在对某个网络地址中的资源进行准确标识,而URN的侧重点则放在对某个命名空间中的资源名称进行标识。

事务

一条HTTP事务是由一条由客户端发往服务器端的请求命令和一条由服务器端返还给客户端的响应结果组成。

方法

HTTP支持一些不同的请求命令,这些命令被称为HTTP方法(HTTP method)。其实每条HTTP请求都会包含一个方法,这个方法会告诉服务器应该执行什么动作(获取一个Web页面、删除某个资源或者是运行一个网关程序等)。
常见的几个HTTP方法

  • GET 从服务器向客户端发送命名资源

咦??是不是突然发现PUT和POST这两个方法的作用看起来是不是很相似啊?的确,一开始我也糊涂了。既然都是将客户端数据发送到服务器端,那么二者的区别在什么地方呢?

经过一番搜索,我在stackoverflow上找到了一个关于HTTP中PUT和POST的讨论:
http://stackoverflow.com/questions/630453/put-vs-post-in-rest

在RESTful API的设计中,究竟是选择PUT还是POST?

其实我感觉PUT和POST的本质上的区别在于是否具有幂等性。因为二者都可以用于create和update,所以到底如何使用在于我们自己的考虑。如果您有更好的理解,欢迎在评论区进行探讨~

关于HTTP方法更详细的介绍我将放在HTTP报文部分

状态码

每条HTTP响应报文返回时都会携带一个状态码,用于告知客户端请求是否成功或者是否需要执行其他动作。状态码由三位数字组成。

HTTP报文

HTTP就如因特网中的信使,给通信双方传递信息。而HTTP报文就是它用来传递信息的包裹了。在这一模块,我大致将总结以下几个部分(在参照书中原有内容的基础上增加了自己的理解):

报文流

HTTP报文是在HTTP应用程序之间发送的数据块。这些数据块以一些文本形式的元信息开头。这些元信息描述了报文的内容以及含义,后面还跟着可选的数据部分。报文在客户端、服务器以及代理之间流动。因此,由于流动方向不同,“流入”、“流出”、“上游”以及“下游”的名词应运而生。

HTTP报文会像河水一样流动,不管是请求报文还是响应报文。在流动的过程中,报文可能会经过一级一级的代理(后面会介绍代理相关的知识)。但是值得注意的是,报文流只能从上游流向下游而不能逆过来。同时上游和下游也不是绝对的,而是要看报文流动的方向。比如说请求报文由客户端流向服务器端,那么对于后面的代理来说,客户端方向就是上游,服务器端方向就是下游。但是对于从服务器端发出的响应报文来说,服务器端方向就是上游,客户端方向就是下游。

HTTP报文的语法及结构

在详细介绍HTTP报文的语法及结构之前,我想先给大家看看HTTP报文到底长什么样子,在传递信息的过程中起到了什么样的作用。

一边打开wireshark一边登录学校的教务在线抓HTTP的包
学号和cookie等个人隐私信息已进行打码处理,不影响对这部分知识的理解

过滤出来的HTTP报文

打开编号为571的包可以发现,这个报文是客户端向服务器端请求用户编号为14080xxxx并且用户类型为学生的个人照片。

报文长度为622 并且使用了GET方法 请求报文主题内容

客户端向服务器端发送请求报文,询问该学号对应学生个人照片资源的URI是多少

紧接着服务器做出了相应,将正确的图片资源信息返还给了服务器。请注意此时状态码为302.其实3**状态码都是重定向状态码,关于为什么这里是302我会在后面进行介绍。

服务器关于个人照片资源的URI返还的响应报文 302 Found 报文主体中的Location指明了我们所请求资源对应的URI

后面就不详细介绍了,仅把有关图片的请求报文和响应报文贴出来

以GET方式请求学生个人照片 请求包主题内容 其中指明了图片的URI 200 OK 表明返回成功 响应报文主体内容
其实报文还包含有最后修改时间(Last-Modified)、版本号(ETag)等其它重要信息,这里不做赘述。在介绍代理和缓存时将对这些知识进行讲解。

下面开始针对报文进行详细介绍

报文的组成部分

起始行和首部其实就是由行分割的ASCⅡ文本。每行都以一个由两个字符组成的行终止序列作为结束,其中包括一个回车符(ACSⅡ码13)和一个换行符(ASCⅡ码10)。这个行终止序列可以写作CRLF。需要指出的是,尽管HTTP规范中说明应该用CRLF来表示行终止,但稳健的应用程序也应该接受单个换行符作为行的终止。有些老的或者是不完整的HTTP应用程序并不总是既发送回车符,又发送换行符。(存在CRLF注入攻击的风险)

报文的组成部分

报文的语法

报文可以分为两大类-----请求报文和响应报文。

请求报文格式 响应报文格式

报文的各个部分

  • 方法(method): 客户端希望服务器端执行的动作,例如GET、DELETE等

其实要展开来讲的话,这一部分会有非常多的内容。因为起始行根据报文类型的不同可以分为请求行(请求报文特有)和响应行(响应报文特有),并且首部也可以分为请求首部、响应首部、拓展首部或者是实体首部等等。这里就不一一介绍了,感兴趣的读者可以自行查阅资料进行了解。在这里提醒一下,由于版本(如HTTP / 0.9和HTTP / 1.0)的差别,HTTP报文格式以及语法可能会有差异,所以要特别注意!

下面着重讲讲HTTP方法和状态码

HTTP方法

HTTP方法用来告诉服务器应该进行何种操作。HTTP方法定义了一组被称为安全方法的方法。GET方法和HEAD方法都被认为是安全的,这意味着使用GET方法和HEAD方法的HTTP请求都不会产生什么动作。

GET

GET是最常用的方法,通常用于请求服务器发送某个资源。HTTP/1.1要求服务器实现该方法。

请求报文 客户端使用GET方法 响应报文
HEAD

HEAD方法与GET方法比较类似,但服务器在回送响应的时候只返回首部,不会返回实体的主体部分。这样就允许客户端在暂未获取实际资源的时候对资源的首部进行检查。

PUT

PUT与GET相反,它会向服务器写入文档。PUT的语义就是让服务器创建一个由请求的URL命名的新文档。如果那个URL对应的资源存在的话,那么就用新的覆盖它。由于PUT允许用户对服务器内容进行修改,所以Web服务器在执行PUT操作之前,通常都要求用户进行登录从而对操作权限进行判别。

POST

POST方法用以向服务器提交数据,通常用于表单数据提交。虽然POST和PUT看起来类似,但是还是有比较大的区别。感兴趣的读者可以看看stackoverflow关于这两种方法的讨论--http://stackoverflow.com/questions/630453/put-vs-post-in-rest

方法为POST的报文信息 向服务器提交账号密码等重要数据 对应的登录提交表单
TRACE

TRACE方法可能没有那么常用,但是它的作用也非常大。众所周知,当客户端向服务器发送请求的时候,请求可能要穿过防火墙、代理、网关或者是其他一些应用程序。每一个中间节点都有可能会修改原有的HTTP请求。TRACE方法允许客户端在最后将请求发送给服务器时,看看它变成了什么样子。TRACE方法主要用于对请求/响应链进行诊断。

OPTIONS

此方法用于请求服务器告知其支持的各种功能,可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法。

DELETE

请服务器删除所请求URL对应的资源,如果有的话。

其他拓展的方法

HTTP被设计成字段可拓展的,拓展方法的意思就是有可能在HTTP规范中没有定义,但是可以由我们自己设计,并且服务器也支持的方法。

拓展方法示例

状态码

HTTP状态码被分为了五大类,下面会对着五大类进行略微详细地介绍---不仅会介绍状态码,还会列出其对应的原因短语。尽管没有实际的规范对原因短语进行确切地说明,下面所列的都是HTTP/1.0规范所推荐的原因短语。

100~199 信息性状态码
200~299 成功状态码

客户端向服务器进行请求时,通常都是成功的。服务器有一组用于表示成功的状态码,分别对应不同类型的请求。

300~399 重定向状态码

重定向状态码要么告知客户端使用替代位置来访问他们所感兴趣的资源,要么就提供一个替代的响应而不是资源的内容。如果资源已经被移走,可发送一个重定向状态码和一个可选的Location首部来告知客户端资源已经被移走,以及现在可以在哪里找到它。浏览器就可以在不影响用户浏览体验的情况下透明地在新的位置找到所需资源了。

当301、302、303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。301、302标准是禁止将POST方法改编成GET方法,但实际使用时大家都会这么做。

400~499 客户端错误状态码
500~599 服务器错误

以上为针对HTTP相关的只是做的第一部分的介绍,其余知识我放在《HTTP权威指南》学习总结(下)进行介绍。

最后在文章的末尾安利一下我的个人公众号:

Eakon先生的小板报

Eakon先生的小板报,一个不向邪恶势力低头的有趣公众号。欢迎关注噢~

上一篇下一篇

猜你喜欢

热点阅读