HTTP 全名是超文本传输协议
,它是一个标准,定义了 Web 客户端如何请求服务器以及服务器如何响应客户端的请求并且将数据如何传回到客户端,它可以用来传输一切可以用字节表示的东西。
HTTP 是 Web 客户端(一般是指浏览器)和 Web 服务器之间通信的标准协议。它定义了所有客户端和服务器之间的通信,例如客户端如何和服务器进行连接、客户端如何从服务器获取数据、服务器如何响应客户端的请求、完成传输之后如何关闭连接等等。
HTTP 连接使用 TCP/IP 协议来传输数据,对于客户端到服务器的每一个请求,都有四个步骤:
默认情况下,客户端在80端口打开与服务器的一个 TCP 连接,也可以在请求中指定其他端口。
客户端向服务器发送请求,请求指定路径上的资源。
服务器向客户端发送响应。
服务器关闭连接。
这是基本 HTTP1.0 的过程,在 HTTP1.0 以后的版本中,可以通过一个 TCP 连接连续发送多个请求和响应,也就是说可以重复第二步和第三步。
每个请求和响应都有同样的基本形式:
上图是使用 Fiddler 抓包得到的请求和响应。
HTTP 请求就是客户端向服务器发送信息的过程,一个标准的请求信息由请求行
、HTTP 头
和请求内容
组成。
请求行的写法是固定的,由请求方法
、请求地址
和HTTP 版本
组成
在上面的图中,请求行就是:
GET http://cn.bing.com/search?q=HTTP&qs=n&form=QBLH&sp=-1&pq=http&sc=8-4&sk=&cvid=334F3AB2A8544E68BB984FBD0B9ECF58 HTTP/1.1
可以看到,请求方法是:GET
、请求地址是:http://cn.bing.com/search?q=HTTP&qs=n&form=QBLH&sp=-1&pq=http&sc=8-4&sk=&cvid=334F3AB2A8544E68BB984FBD0B9ECF58
、HTTP 版本是:HTTP/1.1
。
请求方法包括一下几种:
OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用*
来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
HEAD:与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
GET:向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
PUT:向指定资源位置上传其最新内容。
DELETE:请求服务器删除Request-URI所标识的资源。
TRACE:回显服务器收到的请求,主要用于测试或诊断。
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。
HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。当然,所有的方法支持的实现都应当匹配下述的方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。例如:
请求头由key/value
键值对组成,每行一对,key 和 value 之间用:
分割。
HTTP 请求头包括:
Header | 解释 | 示例 |
---|---|---|
Accept | 指定客户端能够接收的内容类型 | Accept: text/plain, text/html |
Accept-Charset | 浏览器可以接受的字符编码集。 | Accept-Charset: iso-8859-5 |
Accept-Encoding | 指定浏览器可以支持的web服务器返回内容压缩编码类型。 | Accept-Encoding: compress, gzip |
Accept-Language | 浏览器可接受的语言 | Accept-Language: en,zh |
Accept-Ranges | 可以请求网页实体的一个或者多个子范围字段 | Accept-Ranges: bytes |
Authorization | HTTP授权的授权证书 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control: no-cache |
Connection | 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) | Connection: close |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 | Cookie: $Version=1; Skin=new; |
Content-Length | 请求的内容长度 | Content-Length: 348 |
Content-Type | 请求的与实体对应的MIME信息 | Content-Type: application/x-www-form-urlencoded |
Date | 请求发送的日期和时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
Expect | 请求的特定的服务器行为 | Expect: 100-continue |
From | 发出请求的用户的Email | From: user@email.com |
Host | 指定请求的服务器的域名和端口号 | Host: www.zcmhi.com |
If-Match | 只有请求内容与实体相匹配才有效 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since | 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 | If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
If-None-Match | 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range | 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag | If-Range: “737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since | 只在实体在指定时间之后未被修改才请求成功 | If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
Max-Forwards | 限制信息通过代理和网关传送的时间 | Max-Forwards: 10 |
Pragma | 用来包含实现特定的指令 | Pragma: no-cache |
Proxy-Authorization | 连接到代理的授权证书 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 只请求实体的一部分,指定范围 | Range: bytes=500-999 |
Referer | 先前网页的地址,当前请求网页紧随其后,即来路 | Referer: http://www.zcmhi.com/archives/71.html |
TE | 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 | TE: trailers,deflate;q=0.5 |
Upgrade | 向服务器指定某种传输协议以便服务器进行转换(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent | User-Agent的内容包含发出请求的用户信息 | User-Agent: Mozilla/5.0 (Linux; X11) |
Via | 通知中间网关或代理服务器地址,通信协议 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 关于消息实体的警告信息 | Warn: 199 Miscellaneous warning |
请求内容值在 POST 请求中存在。
例如我们登录新浪微博时候,HTTP 请求内容如下:
POST http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18) HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://weibo.com/
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Content-Length: 620
DNT: 1
Host: login.sina.com.cn
Pragma: no-cache
Cookie: xxxxxxxx
entry=weibo&gg&servertime=1487856413&nonce=KYUWEL&pwencode=rsa2&rsakv=这里就是请求内容0876529ace35e8265859d3afa839e297db36b82465c57&sr=1920t.sinaSSOController.feedBackUrlCallBack&returntype=META
可以看到,这个请求方式是 POST,所以就会存在请求内容。
客户端向服务器发出请求之后,服务器会根据请求的信息做出响应,返回所请求的内容(有可能是一个网页,一张图片等等)。
HTTP 响应和 HTTP 请求一样,也是由三部分组成,它们是:状态行
、HTTP响应头
和响应内容
。
状态行的写法也是固定的,由HTTP版本
、响应码
和响应码描述
三个部分组成。
在一开始的图中,状态行就是:
HTTP/1.1 200 OK
关于状态响应码和响应描述大致可以分为以下几类:
100-199 指示信息--表示请求已接收,继续处理。
200-299 成功--表示请求已被成功接收、理解、接受。
300-399 重定向--要完成请求必须进行更进一步的操作。
400-499 客户端错误--请求有语法错误或请求无法实现。
500-599 服务器端错误--服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。
200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常。
更加详细的状态码解释可以自行搜索。
响应头也是由key/value键值对组成,每行一对,key 和 value 之间用:分割。
HTTP 响应头包括:
Header | 解释 | 示例 |
---|---|---|
Accept-Ranges | 表明服务器是否支持指定范围请求及哪种类型的分段请求 | Accept-Ranges: bytes |
Age | 从原始服务器到代理缓存形成的估算时间(以秒计,非负) | Age: 12 |
Allow | 对某网络资源的有效的请求行为,不允许则返回405 | Allow: GET, HEAD |
Cache-Control | 告诉所有的缓存机制是否可以缓存及哪种类型 | Cache-Control: no-cache |
Content-Encoding | web服务器支持的返回内容压缩编码类型。 | Content-Encoding: gzip |
Content-Language | 响应体的语言 | Content-Language: en,zh |
Content-Length | 响应体的长度 | Content-Length: 348 |
Content-Location | 请求资源可替代的备用的另一地址 | Content-Location: /index.htm |
Content-MD5 | 返回资源的MD5校验值 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Range | 在整个返回体中本部分的字节位置 | Content-Range: bytes 21010-47021/47022 |
Content-Type | 返回内容的MIME类型 | Content-Type: text/html; charset=utf-8 |
Date | 原始服务器消息发出的时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
ETag | 请求变量的实体标签的当前值 | ETag: “737060cd8c284d8af7ad3082f209582d” |
Expires | 响应过期的日期和时间 | Expires: Thu, 01 Dec 2010 16:00:00 GMT |
Last-Modified | 请求资源的最后修改时间 | Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT |
Location | 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 | Location: http://www.zcmhi.com/archives/94.html |
Pragma | 包括实现特定的指令,它可应用到响应链上的任何接收方 | Pragma: no-cache |
Proxy-Authenticate | 它指出认证方案和可应用到代理的该URL上的参数 | Proxy-Authenticate: Basic |
refresh | 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) | Refresh: 5; url=http://www.atool.org/httptest.php |
Retry-After | 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 | Retry-After: 120 |
Server | web服务器软件名称 | Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) |
Set-Cookie | 设置Http Cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
Trailer | 指出头域在分块传输编码的尾部存在 | Trailer: Max-Forwards |
Transfer-Encoding | 文件传输编码 | Transfer-Encoding:chunked |
Vary | 告诉下游代理是使用缓存响应还是从原始服务器请求 | Vary: * |
Via | 告知代理客户端响应是通过哪里发送的 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 警告实体可能存在的问题 | Warning: 199 Miscellaneous warning |
WWW-Authenticate | 表明客户端请求实体应该使用的授权方案 | WWW-Authenticate: Basic |
响应内容就是服务器返回的之前 HTTP 请求的内容,这个内容可以是一张图片,或者是一段 HTML 代码。
一开始的图片响应内容就是一个页面,也就是一段 HTML 代码。
HTTP 协议是无状态的,什么意思呢?无状态的意思就是服务器会接收大量的客户端请求,但是服务器是无法分辨该请求是来自于哪个客户端的,为了解决这个问题,HTTP 协议通过 cookies 来保持状态。
客户端想服务器发送请求,服务器会通过 setCookie 来为这个连接设置一个 cookie,当客户端下一次再向服务器发出请求的时候,会携带这个 cookie 来证明自己的身份。
cookie 是保存在本地的,所以很容易会被伪造。