HTTP协议运行在TCP/IP基础上,依靠TCP/IP协议来实现数据的可靠传输。你在本地下载一个Tomcat并且启动,然后在Chrome浏览器的地址栏里输入http://localhost/ 一次简单的浏览器HTTP请求过程如下:
- 浏览器从地址栏的输入中获得服务器的IP地址和端口号
- 浏览器使用TCP的三次握手与服务器建立连接
- 浏览器向服务器发送拼好的报文
- 服务收到报文后处理请求,同样拼好报文再发给浏览器
- 浏览器解析报文,渲染输出页面
一、HTTP报文构成
HTTP协议请求和响应报文的结构基本相同,由三大部分组成:
- 起始行(start line):描述请求或响应的基本信息
- 头部字段集合(header):使用key-value形式更详细地说明
- 消息正文(entity):实际传输的数据,它不一定是纯文本,可以是图片,视频等二进制数据
HTTP协议规定报文必须有header,可以没有body,而且在header之后必须要有一个“空行”,如下图所示:
1.1 请求行
报文里面的起始行就是请求行,它简要描述了客户端想要如何操作服务器端的资源。请求行由三部分构成:
- 请求方法:如GET/POST,表示对资源的操作
- 请求目标:通常是一个URI,标记了请求方法要操作的资源
- 版本号:表示报文使用的HTTP协议版本 这三个部分通常使用空格来分隔,最后要用CRLF换行表示结束。
1.2 状态行
响应报文里的起始行,通常叫做状态行,表示服务器响应的状态,它同样也是由三部分构成:
- 版本号:表示报文使用的HTTP协议版本
- 状态码:一个三位数,用代码的形式表示处理的结果
- 原因:作为数字状态码补充,是更详细的解释文字 如下所示:
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
1.3 头部字段
请求行或状态行+头部字段+空行就构成了HTTP报文里完整的请求头或响应头。请求头和响应头的结构是基本一样的,唯一的区别是起始行。
HTTP协议规定了非常多的头部字段,但基本上可以分为四大类:
- 通用字段:在请求头和响应头里都可以
- 请求字段:仅能出现在请求头里,进一步说明请求信息
- 响应字段:仅能出现在响应头里
- 实体字段:属于通用字段,专门描述body的额外信息
- Host字段:请求字段在HTTP/1.1规范里要求必须出现的字段,告诉服务器这个请求由哪个主机来处理
- User-Agent字段:请求字段,用来描述发起HTTP请求的客户端
- Date字段:通用字段,表示HTTP报文创建的时间
- Server字段:响应字段,告诉客户端当前正在提供Web服务的软件名称和版本号
二、HTTP请求方法
- GET:获取资源,查询或者下载数据
- HEAD:获取资源的元信息,就是响应头部字段
- POST:向服务器资源提交数据,类似于写入或者上传数据
- PUT: 类似POST,POST是插入,PUT就是更新
- DELETE: 删除资源
- TRACE: 追踪请求-响应的传输路径
- OPTIONS: 列出可对资源操作的方法 安全:GET,HEAD方法是安全的,因为它们是只读操作;POST/PUT/DELETE操作会修改服务器上的资源,非安全。
幂等:GET,HEAD即安全也是幂等的,DELETE多次删除等同于一次删除是幂等,PUT多次更新等同于更新一次也是幂等,POST是插入操作非幂等。
三、HTTP响应状态码
目前RFC标准里规定的状态码是三位数,把状态码分成了如下五类:
- 1**:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;
- 2**:成功,报文已经收到并被正确处理;
- 3**:重定向,资源位置发生变动,需要客户端重新发送请求;
- 4**:客户端错误,请求报文有误,服务器无法处理;
- 5**:服务器错误,服务器在处理请求时内部发生了错误。
200:最常见的成功状态码,表示一切正常
204:另一个常见的成功状态码,含义与200基本相同,但是响应头后没有body数据
206:与200一样,也是服务器成功处理了请求,但是body里的数据不是资源的全部,而是其中的一部分
400:通用的错误码,表示请求报文有错误
403:实际上不是客户端的请求出错,而是表示服务器禁止访问资源
404:表示资源在服务器未找到,无法提供给客户端
500:与400一样,也是一个通用错误码,服务发生了什么错误不清楚
502:服务器作为网关或者代理时返回的错误码
503:服务器当前很忙,暂时无法响应服务
四、HTTP协议特点
- 简单灵活可扩展,可以任意添加头字段实现任意功能
- 是可靠传输协议,基于TCP/IP协议,尽量保证数据的送达
- 是应用层协议,比FTP,SSH等通用能力更强,能够传输任意数据
- 使用了请求-应答模式,客户端主动发起请求,服务器被动回复请求
- 是无状态的,每个请求都是相互独立,毫无关联