HTTP协议之报文(二)
有一个经典的问题:在浏览器地址栏输入地址,然后回车,最后看见页面这个过程到底发生了什么?这个过程,用书面语来讲就是一个完整的__浏览器事务__。一个事务由一条请求命令(浏览器发往服务器)和一条响应结果(服务器发往浏览器)组成,而这种通信是通过__HTTP报文__进行的。学习HTTP,最基本的目标就是需要看懂HTTP报文。
学习报文的时候,最好顺手打开一个网页(推荐Chorme浏览器),F12
打开开发者工具,然后切换到Network
面板,然后下方左侧Name
列表随便选择一条,然后在右侧切换到Header
面板,现在就可以愉快地学习啦。
基本语法
HTTP报文是浏览器和服务器之间发送的数据块,一条报文可能是请求报文,也可能是响应报文,但是他们都由三部分组成:
- 对报文进行描述的__起始行__
- 包含属性的__首部块__
- 可选的,包含数据的__主体部分__
下面是具体语法(从书上抄过来的):
// 请求报文
<method><request-URL><version> // 起始行
<header> // 首部行
<entity-body> // 主体
// 响应报文
<version><status><reason-phrase> // 起始行
<header> // 首部行
<entity-body> // 主体
起始行
请求报文和响应报文最主要的结构区别在于起始行不一样:
- 请求报文的首部行包含请求方法,资源URL和HTTP版本号
- 响应报文包含HTTP版本号,请求资源的响应状态(一个三位数)和原因短语(一个英语短语文本)
HTTP版本号
在报文中提供版本号的目的是为了让使用HTTP的应用程序了解双方的的协议能力和报文格式:采用老版本的协议可能无法实现新版本协议的某些特性。HTTP从开始到现在的版本包括HTTP0.9
,HTTP1.0
,HTTP1.1
(目前最常用),HTTP2.0
(二十来年就这么几个版本,可见学习基础的东西是非常划算的)。另外,需要注意的是HTTP协议貌似是一个十分考虑向后兼容的协议
资源URL
就是前面所提到的请求资源的路径。既然是请求报文,肯定是请求资源啦,不带上URL的话HTTP怎么知道把这个报文扔哪去
请求方法
请求报文中的请求方法表明服务器针对该请求应当执行的操作,常见的请求方法有:
方法 | 描述 |
---|---|
GET | 从服务器获取一份文档 |
HEAD | 只从服务器获取文档的首部 |
POST | 向服务器发送需要处理的数据 |
PUT | 将请求的主体放在服务器上 |
TRACE | 追踪报文经过的代理服务器 |
OPTIONS | 决定可以在服务器上执行哪些方法 |
DELETE | 删除一份文档 |
最常用的方法大概就是GET
和POST
方法了。HTML文档中表单method属性的get
和post
,在数据传输过程中分别对应了HTTP协议中的GET和POST方法,区别在于:
- 目的不同,Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据。
- 传递请求数据的方式不同,GET将参数添加在URL的查询字段后(URL位于请求报文的起始行),而POST将请求数据放在请求报文的主体部分
- 由于浏览器可能缓存带有查询字段的URL,因此不能保证安全而被其他访问者查看;此外,某些浏览器对于URL的长度是有限制的,服务器一般也对URL长度有某些限制(超过会返回414错误,关于状态码马上就会讲到),因此在需要向服务器传递大量数据的时候一般使用POST方法
在工作中,GET方法可以应用在数据分页,跳转重定向等地方,而POST方法主要应用在账户登录,编辑信息提交等方面。 POST与GET的另外一个区别在于:GET方式请求的资源可以被缓存,而POST请求无法被缓存。缓存这个问题十分重要,咱们后面再详细了解。
响应状态
状态码是一个三位数,第一位描述状态的一般类别(成功,失败...),后两位描述状态的详细信息,其中:
- 1,表示信息提示
- 2,表示请求成功,常见的状态码是
200
,对应的原因短语是OK
。 - 3,表示重定向,要么告知客户端使用替代位置来访问他们感兴趣的资源,要么是服务器提供一个替代的响应而不是请求资源的内容。这在缓存中十分常见,常见的状态码是
304 Not Modified
,表示资源未修改,可直接使用缓存(缓存这个问题对于前端十分重要,后面会花很多时间来学习的) - 4,表示客户端错误,指浏览器发送了服务器无法处理的内容,比如最常见的
404 Not Found
表示服务器上不存在该资源 - 5,表示服务端错误,有时候请求是有效的,服务端却出现错误,比如某段PHP漏了一个分号啥的,常见的是
502 Bad Gateway
表示无法连接
书中详细讲解了五类响应状态的完整状态码,就不搬过来了,这里是维基百科的链接,遇见不熟悉的状态码再回来查吧。
首部行
起始行提供了整个报文的一个概览,在某些只需要了解报文的基本信息而不需要具体的资源信息(比如判断一个资源是否存在),我们可以使用HEAD
方法发送请求,这个方法就只会返回报文的首部行。 因为起始行能够包含的信息太少了,在使用HEAD请求的时候会非常便捷。但是,在更多的时候,客户端和服务端都需要为报文提供更详细的信息。
首部行提供报文的额外描述信息,用来准确描述正在获取的资源、服务器或者客户端的行为。报文首部行由一组不区分大小写的属性名后跟一个冒号,再紧跟它的值(不必换行)的键值对组成,值前面的空格会被忽略掉。
有些首部信息是请求报文或响应报文专用的,有些首部则更通用一些。由于首部行的数量也比较多,因此下面只列举了一些经常遇见的首部行,这里是HTTP首部行字段的MDN文档。后面在学习HTTP连接,HTTP识别和认证,缓存等知识时,也会回过头来重新了解相关的首部行。
通用首部
表示服务器和浏览器都可以使用的首部,又可以分为
- 普通首部,提供与报文相关的最基本的信息,如
Date
,用来说明构建报文的时间和日期 - 缓存首部,将资源缓存到本地副本,如
Cache-Control
, 特别指定缓存策略
请求首部
请求报文独有的,为服务器提供关于请求数据的额外信息,又可以分为
- Accept首部,将客户端的资源喜好和处理能力告知服务器,如
Accept
, 表示浏览器所希望接收的数据类型 - 条件请求首部,为请求加上某些限制,如
If-Modified-Since
, 只有资源在指定事件后改变才发送该资源 - 安全请求首部,允许客户端在请求资源之前先对自身进行认证,如
Cookie
, 用来帮助服务器识别客户端的身份 - 代理请求首部,协助因特网代理更好地工作
响应首部
响应报文独有的,向浏览器提供服务器的额外信息,又可以分为
- 协商首部,为服务端和客户端对资源进行协商的能力,如
Accept-Ranges
,表示服务端对该资源可以接受的类型 - 安全响应首部,是HTTP的质询/响应认证机制的响应侧,如
Set-Cookie
用于在客户端设置一个Cookie
实体首部
可以用来说明实体主体及其内容部分的信息,又可以分为
- 内容首部,表示实体内容的类型,尺寸以及处理它所需的其他有用信息,如
Content-Length
,表明响应主体的内容长度 - 实体缓存首部,用于提供与被缓存实体有关的信息,如
Expires
, 用于指定了HTTP响应的过期时间
实体
HTTP协议负责传送资源(只要声明了正确的URL),而报文的实体部分就是用来保存资源内容的。此外,HTTP还负责确保它的报文被正确传送,识别提取和适当处理,具体来说,HTTP需要确保他传送的资源满足下面的条件:
- 可以被客户端正确识别(
Content-type
和Content-Language
来表明资源类型和语言)以及正确地解包(Content-Length和Content-Encoding
) - 是最新的(通过实体验证码和缓存过期限制),也是用户所需要的(通过内容协商)
- 可以被快速传输(通过范围传输,差异编码和其他数据压缩方法),且完整到达,未被篡改(通过校验)
HTTP主要就是用来传送资源,上面列举了与资源传送相关的各种技术,每一项技术都很难直接通过简单地学习就能理解,关于主体部分,针对前端工作,我觉得应该首先应该掌握的是__内容缓存__,接下来的就让我们来弄个明白缓存到底是个什么鬼。
你要请我喝一杯奶茶?
版权声明:自由转载-非商用-保持署名和原文链接。
本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。