HTTP协议基于TCP/IP协议,属于无状态协议

HTTP 0.9

样例:
GET 192.168.1.2/test.txt
GET开头,空格接着URL地址和查询字符串,CRLF换行结束,返回结果默认是HTML格式(如果不是服务器也没法通知),HTTP 0.9不支持一台服务器IP对应多个域名,属于已经过时的协议,但大部分浏览器仍然支持HTTP 0.9,这将导致一些安全问题

HTTP 1.0/1.1

请求样例:

1
2
3
4
5
6
7
8
9
10
GET /myweb/login.jsp HTTP/1.1
Cookie: JSESSIONID=77FC1A52E9C3BAD0536359386A96C0FB
x-requested-with: XMLHttpRequest
Accept-Language: zh-cn
Referer: https://192.168.0.0:8443//myweb/login.jsp
Accept: */*
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Host: 192.168.0.0:8443
Connection: Keep-Alive
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)

第一行包含具体的版本信息,紧接着数条“名称:值”键值对组成的数据行(头域 Headers),每行为一个头域。请求头部分以一个单独的空行结束,空行后面可以加上需要发送给服务器的数据,这些数据长度必须在请求头Content-Length里明确标出。HTTP协议对后面部分数据的格式没有明确要求。
返回样例:

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Server: openresty
Date: Tue, 08 Mar 2016 08:24:48 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive

Hello world

第一行包含协议版本和状态码以及状态信息描述(可选),随后若干响应数据行,以一个单独空行结束,再后面是返回的正文内容。实际情况里,状态码很不可靠,如果客户端请求里Accept-Encoding没有规定能接受的压缩方式,服务器端可以在gzip、compress、deflate三种压缩方式里任选一种传输。

HTTP 1.0与1.1的差异

  • HTTP 1.1 加入了OPTIONS、PUT、DELETE、TRACE、CONNECT请求方法 (原有GET、POST、HEAD)
  • HTTP 1.1 增加数个头域
    • 增加了HOST域,以应对同一IP的多个虚拟主机
    • 增加了Upgrade头域,用来告诉服务端,客户端能够支持的其它备用通信协议;
    • 增加了Via头域,用来记录消息转发的路径,它记录了整个路径上所有发送方使用的版本号;
    • 增加了Cache-Control头域(请求消息和响应消息都可使用),用来控制缓存;
    • 增加Content-Range,用于节约优化。
  • HTTP 1.1 增加了100、305等24个新状态码
  • HTTP 1.0中需要建立长连接头域必须有Connection: Keep-Alive,HTTP 1.1 默认打开长连接,而且HTTP 1.0的Proxy不支持Connection头域,协议规定所有出现在Connection头域中的头域名都将被忽略。
  • HTTP 1.1允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容
  • HTTP 1.1 支持Transfer-Encoding:chunked 发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。这个差别有可能导致内容解析问题。
  • HTTP/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。
  • date/timestamp (日期时间戳)有细微差别。

关于RESTful

中间插一句,最近很流行的一个概念RESTful,REST全称是Representational State Transfer,不过这个全称看着也很懵逼。提出这个概念的Roy Thomas Fielding是HTTP协议的主要设计者,以我的理解,REST其实是让我们回归HTTP方法本身的语义。

HTTP 1.1 是1999年发表的,HTTP 2都发布了,但开发者几乎还在用HTTP 1.0的特性,请求方法平时几乎只用到GET和POST,大量的GET方法都不是幂等的。这显然有悖于HTTP 1.1的设计思想。

REST作为一种标准或者约定,主要定义了以下几点:

  • URL定位资源,URL都指向Resource,都应该是名词,不涉及任何操作语义
  • 操作语义交给HTTP请求方法,GET和PUT应当幂等:

    • GET 获取资源,
    • POST 新建资源
    • PUT 更新资源,
    • DELETE 删除资源
    • UPDATE 更新资源

    如上,其实HTTP协议的请求方法已经能覆盖所有对资源的操作了。

  • HTTP传递资源(无论Json、XML还是二进制数据,都是资源的不同形式)
  • 使用正确的HTTP状态码。HTTP 1.1就有三十多个状态码了。但我们平时用到的极少,很多网站都只有404、500、200这三个状态码。
  • 用/嵌套的url来标示子资源,比如:/tickets/12/messages
  • 用?来过滤资源

以上这些约定,仔细看不难发现,都是在重复和强调HTTP本身的语义。

安全问题