第一次看HTTP报文时,理解不是很深刻,只是有了一个基本的概念,当看了cowboy(Web 服务器)中的相关源代码后,觉得对其中的HTTP报文概念理解不是很明了,反过来带着问题再去看HTTP报文的相关概念时,就感觉清楚了很多,但还是有一点问题没有明白,再去看看代码,看看理论,会明白的……
把其中用到的相关知识点整理如下:
报文的组成部分
HTTP报文是简单的格式化数据块。
HTTP报文分为请求报文(request message)和响应报文(response message)。它们都有三个部分组成:对报文进行描述的起始行(start line), 包含属性的首部块(header),以及可选的,包含数据的主体(body)部分。
起始行和首部是由行分隔符的ASCII文本。每行都以一个有两个字符组成的行终止序列作为结束,其中包括一个回车符(ASCII码13)和一个换行符(ASCII码10),这个行终止序列可以写作CRLF。
实体的主体或报文的主体(或者成为主体)是一个可选的数据块。与起始行和首部不同的是,主体中可以包含文本或二进制数据,也可以为空。
报文的语法
请求报文的格式
下面是一个请求报文的样例:
<<"GET /test.txt HTTP/1.1\r\n Host: 172.16.81.107:8080\r\n Connection: keep-alive\r\n Pragma: no-cache\r\n Cache-Control: no-cache\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36\r\n Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\n\r\n">>
响应报文
如下,响应报文的样例:
<<"HTTP/1.1 200 OK\r\n">>[[<<"connection">>,<<": ">>,<<"keep-alive">>,<<"\r\n">>],[<<"server">>,<<": ">>,<<"Cowboy">>,<<"\r\n">>],[<<"date">>,<<": ">>,<<"Mon, 02 Mar 2015 10:07:52 GMT">>,<<"\r\n">>], [<<"content-length">>,<<": ">>,"18",<<"\r\n">>],[<<"content-type">>,<<": ">>,[<<"text">>,<<"/">>,<<"plain">>,<<>>], <<"\r\n">>],[<<"etag">>,<<": ">>,[34,<<"2727243677">>,34],<<"\r\n">>],[<<"last-modified">>,<<": ">>,<<"Sat, 28 Feb 2015 14:46:31 GMT">>,<<"\r\n">>]]<<>>
首部(header):
可以是零个或多个首部,每个首部都包含一个名字,后面跟着一个冒号(:);然后是一个可选的空格,接着是一个值,最后是一个CRLF。首部是一个空行(CRLF),表示了首部列表的结束和主体部分的开始。有些HTTP版本,比如HTTP/1.1,要求有效的请求或响应报文中必须包含特定的首部。
3. 起始行
请求行:请求报文的起始行,或称为请求行,包含了一个方法和一个请求URL,这个方法描述了服务器应该执行的操作,请求URL描述了要求对哪个资源执行这个方法。请求行中还包含HTTP的版本,用来告知服务器,客户端使用的是哪种HTTP。
如:
"GET /test.txt HTTP/1.1\r\n
方法: 请求的起始行以方法作为开始,方法用来告知服务器要做些什么。
如下: 常用的HTTP方法
方法 | 描述 | 是否包含主体 |
GET | 从服务器获取一份文档 | 否 |
HEAD | 只从服务器获取文档的首部 | 否 |
POST | 向服务器发送需要处理的数据 | 是 |
PUT | 将请求的主体部分存储在服务器上 | 是 |
TRACE | 对可能经过代理服务器传送到服务器上去的报文进行追踪 | 否 |
OPTIONS | 决定可以在服务器上执行哪些方法 | 否 |
DELETE | 从服务器上删除一份文档 | 否 |
响应行:响应报文承载了状态信息和操作产生的所有结果数据,将其返回给客户端。响应报文的起始行,或称为响应行,包含了响应报文使用的HTTP版本,数字状态码,以及描述操作状态的文本形式的原因短语。
如:
"HTTP/1.1 200 OK\r\n"
状态码:方法是用来告诉服务器做什么事情的,状态码则用来告诉客户端,发生了什么事情。状态码位于响应的起始行中。
状态码分类:
整体范围 | 已定义范围 | 分类 |
100~199 | 100~101 | 信息提示 |
200~299 | 200~206 | 成功 |
300~399 | 300~305 | 重定向 |
400~499 | 400~415 | 客户端错误 |
500~599 | 500~505 | 服务器错误 |
常见状态码:
状态码 | 原因短语 | 含义 |
200 | OK | 成功。请求的所有数据都在响应主体中 |
304 | Not Modified | 资源为被修改。 |
400 | Unathorized(未授权) | 需要输入用户名和密码 |
404 | Not Found | 服务器无法找到所请求URL对应的资源 |
304: Not Modified :客户端可以通过所包含的请求首部,使其请求变成有条件的。如果一个客户端发起了一个条件GET请求,而最近资源未被修改的话,就可以用这个状态码来说明资源未被修改。带有这个状态码的响应不应该包含实体的主体部分。(在有关缓存的内容时会用到,
对304理解的文章:)
4. 首部
请求首部是只在请求报文中有意义的首部。用于说明是谁或什么在发送请求,请求源自何处,或者客户端的喜好及其能力。服务器可以根据请求首部给出的客户端信息,试着为客户端提供更好的响应。
下面是一个请求头,其中有些首部代表的意思是什么呢?
User-Agent:将发起请求的应用程序名称告知服务器。
Connection : 允许客户端和服务器指定与请求/响应连接相关的选项。
Accept首部
为客户端提供了一种将其喜好和能力告知服务器的方式,包括它们想要什么,可以使用什么,以及最重要的,它们不想要什么。这样,服务器就可以根据这些额外信息,对要发送的内容做出更明智的决定。Accept首部会使连接的两端都受益。客户端会得到它们想要的内容,服务器则不会浪费其时间和带宽来发送客户端无法使用的东西。
Accept首部:
条件请求首部
有时客户端希望为请求加上某些限制。比如,如果客户端已经有了一份文档副本,就希望只在服务器上的文档与客户端拥有的副本有所区别时,才请求服务器传输文档。通过条件请求首部,客户端就可以为请求加上这种限制,要求服务器在对请求进行响应之前,确保某个条件为真。如下:列出了各种条件请求首部。
下面时一个响应头,相关首部对应的内容是什么?
Connection: 允许客户端和服务器指定与请求/响应连接相关的选项。
Data : 提供日期和时间标志,说明报文是什么时间创建的。
Etag : 与此实体相关的实体标记,实体标记本质上来说就是某个特定资源版本的标识符。
Server : 服务器应用程序软件的名称和版本。
参考文章:
http://my.oschina.net/u/1403215/blog/549123