愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

HTTP学习系列(一)HTTP协议基础

一、http协议

http协议用于客户端服务端之间的通信,通过请求响应的交换来达成通信。一次http请求,是从客户端发送请求报文开始,到服务端返回响应报文结束的。以下是一次HTTP请求报文的示例:
请求报文

GET /index.html HTTP/1.1
Host: ruphi.cn

响应报文

HTTP/1.1 200 OK
Date: Tues, 10 Oct 2017 11:04:17 GMT
Content-Length: 999
Content-Type: text/html
....

所以,一个完整的请求报文,其格式为:

请求方法 URI 协议版本
可选的头部

内容实体

而一个完整的响应报文,其格式为:

协议版本 状态码 原因短语
响应头部

内容实体


二、http是无状态的

http是一种无状态的协议,协议本身不保留之前一切的请求或响应报文的信息。如此设计,主要是因为:为了快速处理大量事务,确保协议的可伸缩性
而现代随着web技术的快速发展,记录用户状态越来越重要,所以为了解决这个问题,引入了cookie技术


三、请求资源与HTTP请求方法

HTTP协议使用URI定位互联网上的资源,指定URI的方式有:
1)URI为完整的URI,如:

GET http://ruphi.cn/index.html HTTP/1.1

2)在头部使用Host字段,如:

GET /index.html HTTP/1.1
Host: ruphi.cn

如果不是访问特定的资源,而是 对服务器本身发起请求 的话,那么可以使用*来代替请求URI,如:

OPTIONS * HTTP/1.1

在http请求中,有多种请求方法,如:GET、POST、PUT、HEAD、DELETE、OPTIONS、TRACE、CONNECT,下面对这些请求方法进行介绍:

1、GET

GET方法主要是用来 获取服务器资源,服务器会识别请求报文中指定的URI,然后返回经过解析的响应内容(如请求的是纯文本,就会原样返回纯文本,请求的是PHP文件,就会返回执行对应的PHP脚本后得到的内容)
例子如:

GET /index.html HTTP/1.1
Host: ruphi.cn

响应则返回 index.htm 页面的内容

2、POST

POST方法主要是用来 客户端向服务端传输实体主体,虽然GET也可以传输实体主体,但是一般不这么做,POST的主要目的在于让客户端可以给服务器发送实体数据
例子如:

POST /login.php HTTP/1.1
Host: u.ruphi.cn
Content-Length: 2000

username=admin&password=123456

响应则返回login.php接受数据的处理结果

3、PUT

PUT方法用于传输文件,在请求报文的内容实体中包含文件内容,然后保存到请求URI中指定的位置。但是HTTP/1.1协议对PUT方法自身不做验证,任何人都可以上传文件,所以存在安全问题,所以右边情况下不用这个方法。不过若配合Web程序的验证机制,或者是RESTful架构的,那么就可能采用PUT方法,例子如:
请求

PUT /example.html HTTP/1.1
Host: ruphi.cn
Content-Type: text/html
Content-Length: 1560
...

响应

HTTP/1.1 204 No Content
...

表明该html已存在于服务器上

4、HEAD

该方法和GET方法类似,只是它不返回报文的主体部分,只返回头部部分。所以HEAD方法的作用为:获得报文首部,用来确认URI的有效性及资源更新的日期时间等

5、DELETE

类似于PUT,只不过是PUT的反操作,用以删除文件。HTTP/1.1也不对该方法做验证,应该在具有验证机制的Web程序、或者在RESTful架构的程序里使用

6、OPTIONS

用来查询针对请求URI,所能支持的方法,如:
请求

OPTIONS * HTTP/1.1
Host: ruphi.cn

响应

HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS

7、TRACE

该方法的作用是让web服务器将之前的请求通信返回给客户端。在发送请求时,会在Max-Forwards首部字段中填入数值,每经过一个服务器,该数值-1,当数值为0时,就停止继续传输,最后接收到请求的服务器端返回状态码200 OK的响应。
客户端可以通过TRACE方法,知道发送出去的请求是怎样被加工、修改和篡改的,如:

客户端 --TRACE--> 代理服务器 --TRACE--> 代理服务器 --TRACE--> 服务器
Max-Forwards: 2 1 0

请求

TRACE / HTTP/1.1
Host: ruphi.cn
Max-Fowards: 2
...

响应

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 1024

TRACE / HTTP/1.1
Host: ruphi.cn
Max-Fowards: 2

(即返回的响应主体包含请求的内容)

8、CONNECT

CONNECT方法要求在于代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL和TLS协议把通信内容加密后经网络隧道传输,其格式如:

CONNECT 代理服务器名:端口号 HTTP版本

例子如:
请求报文

CONNECT proxy.example.com:8080 HTTP/1.1
Host: proxy.example.com

响应报文

HTTP/1.1 200 OK

之后便进入网络隧道
需要注意的是,HTTP的请求方法区分大小写,所以方法名称都应该是 大写


四、持久连接

1、Connection: keep-alive

在HTTP早期版本中,每进行一次HTTP通信就要断开一次TCP连接,如:

这种方式在当年互联网早期的通信中,不会带来太多问题,因为早期都是一些小文本的传输。但随着web技术的发展,浏览器浏览包含有大量图片、资源的页面的时候,这种方案就会造成通信量的巨大开销,同时也很浪费。所以在HTTP/1.1中,默认使用的是持久连接,即若没有一端明确提出断开连接,就保持TCP的连接状态,如:

持久连接的好处在于:减少了TCP连接重复建立与断开所造成的额外开销,减轻了服务器的负载。同时,因为减少了断开TCP连接的那部分时间,所以HTTP的请求和响应能够更快结束,从而使得页面的响应速度变得更快

2、管线化

持久连接使得多数请求以管线化方式发送成为可能,在之前,发送请求后需要等待并收到响应,才能发送下一个请求。而管线化技术,则能够不用等待也可以直接发送下一个请求。这么做的好处是能够做到并行发送多个请求,无需一个一个地等待响应,请求从而能够更快地结束(请求越多,这种方案带来的时间上的缩短就越明显)


五、Cookie

由于http是一种无状态的协议,不必保存状态使得http能够减少服务器的CPU及内存资源的消耗。但是随着web的发展,又需要跟踪客户端状态,所以cookie技术便被引入来解决这个问题。相关过程描述如:
1)客户端向服务端发送请求,在没有cookie信息的状态下,服务端会生成一个cookie,然后在响应报文中添加cookie(通过Set-Cookie头部字段指定)
2)客户端收到服务端的响应报文后,在本地保存Set-Cookie字段中所指定的cookie值
3)在下一次客户端向服务端请求的时候,客户端的请求报文的头部会带上Cookie字段,服务端拿到这个值后,会检查是哪一个客户端发送过来的请求,从而实现状态的记录
示例如:

GET / HTTP/1.1
Host: ruphi.cn

此时头部中没有cookie信息,于是服务器生成了一个cookie,并在响应报文中返回:

HTTP/1.1 200 OK
Set-Cookie: id=123; path=/; expire=Tues, 10 Oct 2017 18:04:17 GMT
...

那么,在下次客户端请求服务端的时候,头部也会带上cookie,如:

GET / HTTP/1.1
Host: ruphi.cn
Cookie: id=123