Introduction to HTTP

超文本传输协议(HTTP)是用于分布式, 协作, 超媒体系统的应用层协议. 设计HTTP的初衷是解决HTML页面的发布和接收问题, HTTP是万维网数据通信的基础. HTTP的全称为HyperText Transfer Protocol.HTTP遵循经典的客户端-服务端模型, 客户端打开一个连接以发出请求, 然后等待它收到服务器端响应. HTTP是一种无状态协议, 意味着服务器不会再两个请求之间保留任何数据(状态). 虽然HTTP是基于TCP/IP层之上的, 但可以在任何可靠的传输层上使用.

1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法, 并称之为超文本, 这也成为HTTP超文本传输协议标准架构的发展根基. HTTP的开发由Tim Berners-Lee于1989年在欧洲核子研究中心(CERN)发起, HTTP标准的开发由互联网工程任务小组(IETF)和万维网联盟(W3C)协调, 最终发布了一系列标准.

HTTP的版本

1
2
3
4
5
6
7
8
--------------------------------------------------------
年份 | HTTP版本
--------------------------------------------------------
1991年 | 0.9
1996年 | 1.0
1997年 | 1.1
2015年 | 2.0
--------------------------------------------------------

HTTP的特点

  • 简单快速: 客户端向服务器请求服务时, 只需传送请求方法和路径. 请求方法常见的有GET, HEAD, PUT, DELETE, POST. 每种方法规定了客户与服务器联系的类型不同, 由于HTTP协议简单, 使得HTTP服务器的程序规模小, 因此通信速度很快.

  • 灵活: HTTP允许传输任意类型的数据对象.

  • 无连接: 限制每次连接只处理一个请求. 服务器处理完客户的请求, 并收到客户的应答后, 断开连接, 采用这种方式可以节省传输时间.

  • 无状态: HTTP协议自身不对请求和相应之间的通信状态进行保存. 任何两次请求之间都没有依赖关系, 每个请求都是独立的, 与前面的请求和后面的请求都是没有直接联系. 协议本身不保存之前一切的请求报文或相应报文的信息. 这是为了更快的处理大量事务, 确保协议的可伸缩性.

HTTP消息格式

客户端和服务器通过发送纯文本消息进行通信. 客户端向服务器发送请求, 服务器发送相应.

请求消息包含如下内容:

  • 请求行
  • 请求头
  • 空行
  • 请求体

响应消息包含如下内容:

  • 状态行
  • 响应头
  • 空行
  • 响应体

HTTP持久连接

在HTTP/0.9和1.0中, 连接在单个请求/相应之后关闭的, 在HTTP/1.1中引入了keep-alive-mechanism, 其中连接可以被重用于多个请求. 这种持久连接可以明显地减少请求延迟, 因为客户端在发送了第一个请求之后不需要重新协商TCP 3-Way-Handshake连接. 由于TCP的慢启动机制, 连接随着时间的推移变得更快.

该协议的1.1版还对HTTP/1.0进行了带宽优化改进. HTTP1.1引入了分块传输编码, 以允许流传输持久连接上的内容而不是缓冲. HTTP流水线操作进一步缩短了延迟时间, 允许客户端在等待每个响应之前发送多个请求. 协议的另一个附加功能是字节服务, 其中服务器仅传输客户端明确请求的资源部分.

HTTP请求方法

HTTP请求方法是指要对所识别的资源执行的期望动作.

  • GET: 请求指定的内容信息, 返回响应主体.
  • HEAD: 与GET类似, 但没有响应主体. 这对于检索在响应头中编写的元信息非常有用, 而无需传输整个内容.
  • POST: 向指定资源提交数据进行处理请求, 数据包含在请求体中.
  • PUT: 将所包含的实体存储在指定的URI下. 如果URI引用已存在资源, 则将其修改; 如果URI未指定现有资源, 则在给URI下创建资源.
  • DELETE: 删除指定的资源.
  • TRACE: 回应收到的请求, 以便客户端可以查看中间服务器所做的更改和添加.
  • OPTIONS: 返回服务器支持指定的URL的HTTP方法, 这可以通过请求而不是特定资源来检查Web服务器的功能.
  • CONNECT: 将请求连接转换为透明的TCP/IP隧道, 通常是为了通过为加密的HTTP代理促进SSL加密通信(HTTPS).
  • PATCH: 对资源应用部分修改.

所用通用HTTP服务器都需要至少实现GET和POST方法, 并且规范认为所有的其它方法都是可选的.

GET与POST的区别

  • 浏览器刷新/后退: GET没有任何影响, POST会把数据重新提交
  • 书签: GET可收藏为书签, POST不可收藏为书签
  • 缓存: GET能被缓存, POST不能被缓存
  • 编码类型: GET采用application/x-www-form-urlencoded编码, POST采用application/x-www-form-urlencoded或者multipart/form-data编码, 为二进制数据使用多重编码
  • 浏览器保存历史: GET参数保留在浏览器历史中, POST参数不会保存在浏览器历史中
  • 数据长度限制: GET的URL最大长度为2048个字符, POST无长度限制
  • 数据类型限制: GET只允许ASCII字符, POST无限制, 也可以使用二进制数据
  • 安全性: GET安全性较差, 敏感数据最好不要使用, POST参数不会保存在浏览器历史或Web服务器的日志中, 比GET安全
  • 可见性: GET数据在URL中所有人可见, POST不会显示在URL中

HTTP状态代码

在HTTP/1.0中, HTTP响应的第一行称为状态行, 包括数字状态代码(例如:404)和文本原因短语(例如: Not Found). 用户代理处理响应的方式主要取决于代码, 其次取决于其它响应头字段. 可以使用自定义状态代码, 因为如果用户代理遇到它无法识别的代码, 它可以使用代码的第一个数字来确定响应的一般类.

HTTP状态代码主要分为五组, 以便更好地解释客户端和服务器之间的请求和响应.

  • 1xx: 信息性状态码, 接收的请求正在处理
  • 2xx: 成功状态码, 请求正常处理完毕
  • 3xx: 重定向状态码, 需要进行附加操作以完成请求
  • 4xx: 客户端错误状态码, 服务器无法处理请求
  • 5xx: 服务器错误状态码, 服务器处理请求出错

常见状态码

200 OK
请求成功. 成功的含义取决于HTTP方法:

  • GET: 资源已被提取并在消息正文中传输
  • HEAD: 实体标头位于消息正文中
  • POST: 描述动作结果的资源在消息体中传输
  • TRACE: 消息正文包含服务器收到的请求消息

204 No Content
服务器成功处理了请求, 但不需要返回任何实体内容, 并且希望返回更新了的元信息. 响应可能通过实体头部的形式, 返回新的或更新的元信息. 如果存在这些头部信息, 则应当与所请求的变量相呼应. 如果客户端是浏览器的话, 那么用户浏览器应保留发送了该请求的页面, 而不产生任何文档视图上的变化. 即使按照规范新的或更新后的元信息应当被应用到用户浏览器活动视图中的文档. 由于204响应被禁止包含任何消息体, 因此它始终以消息头后的第一个空行结尾.

206 Partial Content
服务器已经成功处理了部分GET请求. 类似于FlashGet或者迅雷这类的HTTP下载工具都是使用此类响应实现断点续传或者建一个大文档分解为多个下载段同时下载. 该请求必须包含Range头信息来指示客户端希望得到的内容范围, 并且可能包含if-Range来作为请求条件.

301 Moved Permanently
被请求的资源已永久移动到新位置, 并且将来任何对此资源的引用都应该使用本响应返回的若干个URL之一. 如果可能, 拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址. 除非额外指定, 否则这个响应也是可缓存的.

302 Found
请求的资源现在临时从不同的URI响应请求. 由于这样的重定向是临时的客户端应当继续向原有地址发送以后的请求, 只有在Cache-Control或在Expires中进行了指定的情况下, 这个响应才是可缓存的.

303 See Other
对应当前请求的响应可以在另一个URI上被找到, 而且客户端应当采用GET的方式访问那个资源. 这个方法的存在主要是为了允许由脚本激活的POST请求输出重定向到一个新的资源.

304 Not Modified
如果客户端发送了一个带条件的GET请求且该请求已被允许, 而文档的内容(自上次访问以来或者根据请求的条件)并没有改变, 则服务器应当返回这个状态码. 304响应禁止包含消息体, 因此始终以消息头后的第一个空行结尾.

307 Temporary Redirect
请求的资源现在临时从不同的URI响应请求. 由于这样的重定向是临时的, 客户端应当继续向原有地址发送以后的请求. 只有在Cache-Control或Expires中进行了指定的情况下, 这个响应才是可缓存的.

400 Bad Request

  1. 语义有误, 当前请求无法被服务器理解. 除非进行修改, 否则客户端不应该重复提交这个请求.
  2. 请求参数有误

401 Unauthorized
当前请求需要用户验证. 该响应必须包含一个适用于被请求资源的WWW-Authenticate信息头用以询问用户信息. 客户端可以重复提交一个包含恰当的Authorization头信息的请求. 如果当前请求已经包含了Authorization证书, 那么401响应代表着服务器验证已经拒绝了那些证书. 如果401响应包含了与前一个响应相同的身份验证询问, 且浏览器已经至少尝试了一次验证, 那么浏览器应当向用户展示响应中包含的实体信息, 因为这个实体信息中可能包含了相关诊断信息.

403 Forbidden
服务器已经理解请求, 但是拒绝执行它. 与401响应不同的是, 身份验证并不能提供任何帮助, 而且这个请求也不应该被重复提交. 如果这不是一个HEAD请求, 而且服务器希望能够讲清楚为何请求不能被执行, 那么就应该在实体内描述拒绝的原因. 当然服务器也可以返回一个404响应, 假如它不希望让客户端获得任何信息.

404 Not Found
请求失败, 请求所希望得到的资源未被在服务器上发现. 没有信息能够告诉用户这个状态码到底是暂时的还是永久的.

500 Internal Server Error
服务器遇到了不知道如何处理的情况.

503 Service Unavailable
服务器没有准备好处理请求. 常见原因是服务器因维护或重载而停机.