0. 前言
该笔记记录了HTTP相关的基本知识,包括:
1. 定义
超文本传输协议 HyperText Transfer Protocol,简称HTTP。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求,Web服务器根据接收到的请求后,向客户端发送响应信息。HTTP协议定义这个过程中Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。目前广泛使用的是HTTP/1.1版本,HTTP/2标准于2015年5月以RFC 7540正式发表,但尚未普及。
2. 特点
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
- 支持B/S及C/S模式。
关于无连接可参考我的笔记 如何理解HTTP的无连接、短连接、长连接
3. 工作过程
- 客户端连接到Web服务器, 一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://kanarien.cn。
- 发送HTTP请求, 通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
- 服务器接受请求并返回HTTP响应, Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
- 释放连接TCP连接若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
- 客户端浏览器解析HTML内容客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
4. 统一资源定位符 URL
统一资源定位符 Uniform Resource Locator,简称URL,是互联网上用来标识某一处资源的地址。以下面这个URL为例,介绍下普通URL的各部分组成:
http://kanarien.cn:80/2018/07/22/Nginx搭配Tomcat作Web服务器/index.html?page=1
- 协议部分:该URL的协议部分为
http:
,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在”HTTP”后面的“//”为分隔符; - 域名部分:该URL的域名部分为
kanarien.cn
,是一级域名,常见的如www.baidu.com
是二级域名。另外,域名不区分大小写。一个URL中,也可以使用IP地址作为域名使用; - 端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口。HTTP协议的默认端口为80,HTTPS协议默认端口为443;
- 虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分,而且URL中的中文会被转码成类似“%EF”的形式。本例中的虚拟目录是
/2018/07/22/Nginx搭配Tomcat作Web服务器/
; - 文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是
index.html
。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名; - 参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为
?page=1
。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符; - 锚部分:从“#”开始到最后,都是锚部分。本例中没有,比如用作文本目录的定位。URL按定义是没有锚部分的,但是URI有,具体往下看。
4.1 统一资源标识符 URI
“A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource. “ ——RFC 3986
Uniform Resource Identifier,统一资源标识符,简称URI,用来在万维网中唯一的标识一个资源。
4.2 统一资源命名 URN
“Uniform Resource Names (URNs) are intended to serve as persistent,location-independent, resource identifiers.” ——RFC 2141
Uniform Resource Name,统一资源命名,简称URN,是通过名字来标识持久化的资源。
4.3 URI、URL、URN
URN确定了一个资源的名字,URL确定了一个资源的位置,而URN、URL是URI的子集。URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
举个例子,与上述的URL类似的URI(多了锚部分)http://kanarien.cn:80/2018/07/22/Nginx搭配Tomcat作Web服务器/index.html#0-前言
其中http://
表示访问方式
而kanarien.cn:80/2018/07/22/Nginx搭配Tomcat作Web服务器/index.html
,定位了资源的地址
最后的#0-前言
,标识了资源名称
因此,这一整个URI中:http://kanarien.cn:80/2018/07/22/Nginx搭配Tomcat作Web服务器/index.html
是一个URLkanarien.cn:80/2018/07/22/Nginx搭配Tomcat作Web服务器/index.html#0-前言
是一个URN
5. 请求 HTTP Request
请求消息,由请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。如图:
Post请求例子1
2
3
4
5
6
7
8
9POST https://cosapi4.cloud.tencent.com/api.php?Action=DeleteResource HTTP/1.1
Host cosapi4.cloud.tencent.com
User-Agent Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept application/json, text/javascript, */*; q=0.01
Referer https://console.cloud.tencent.com/cos/bucket
Accept-Encoding gzip, deflate, sdch
Accept-Language zh-CN,zh;q=0.8
appid=12345678&bucketName=kanarien
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本.
POST说明请求类型为GET,https://cosapi4.cloud.tencent.com/api.php?Action=DeleteResource
为要访问的资源,该行的最后一部分说明使用的是HTTP1.1版本。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
从第二行起为请求头部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等
第三部分:空行,请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行。
第四部分:请求数据也叫主体,可以添加任意的其他数据。appid=12345678&bucketName=kanarien
是Post请求的携带的数据。Get方法是没有请求体的,数据可通过URL传递。
5.1 请求方法 Request Method
请求方法 | 描述 |
---|---|
OPTIONS | 返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的赢球来测试服务器的功能性 |
HEAD | 向服务器索与与GET请求相一致的响应,只不过响应体不会被返回。可以获取包含在响应小消息头中的元消息 |
GET | 请求获取服务器上的资源,详细见5.2 |
POST | 请求更新服务器上的资源,详细见5.2 |
PUT | 向指定资源位置上传其最新内容 |
DELETE | 请求服务器删除Request-URL所标识的资源。 |
TRACE | 回显服务器收到的请求,主要用于测试和诊断 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器,如使用SSL |
5.2 GET和POST的区别
- 根据Http规范,get是用于获取信息,是幂等(多个请求返回相同结果)的。post是用于更新信息。
- get会把参数显示在URL上,如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。post把参数放在HTTP包的包体中,用户无法看到。
- get的参数大小直接受到URL长度的限制,不同浏览器具体限制不同,IE对URL长度的限制是2083字节(2K+35)。另外,HTTP规范并没有对URL长度做出限制。post的参数大小受到服务器处理数据能力的限制。理论上没有大小限制,但出于安全考虑,IIS规范对其做出了限制。
- get的安全性较post低,因为参数会显示在URL上,且post的数据不会保存到浏览器历史或web服务日志中。而效率上get高于post。
- 刷新/后退页面,post数据会被重新提交,而get则不会。
5.3 forward和redirect的区别
- 从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL. - 从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据. - 从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等. - 从效率来说
forward:高.
redirect:低.
6. 响应 HTTP Response
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
一个响应的例子,如下:1
2
3
4
5
6
7
8
9
10
11
12HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: https://console.cloud.tencent.com
Connection: close
Content-Type: application/json
Date: Mon, 30 Jul 2018 11:39:23 GMT
Server: nginx
Transfer-Encoding: chunked
{"code":0,"message":"success","request_id":"NWI1ZWY4ZWJf"}
第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)
第二部分:消息报头,用来说明客户端要使用的一些附加信息
第二行和第三行为消息报头,
Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。
响应的数据对应Content-Type: application/json
是json字符串
6.1 状态码 Status Code
状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
- 1xx:指示信息–表示临时性信息,请求已接收,继续处理
- 2xx:成功–表示请求已被成功接收、理解、接受
- 3xx:重定向–要完成请求必须进行更进一步的操作
- 4xx:客户端错误–请求有语法错误或请求无法实现
- 5xx:服务器端错误–服务器未能实现合法的请求
常见的状态码如下:
状态代码 | 状态描述 | 说明 |
---|---|---|
100 | Continue | 继续 |
101 | Switching Protocols | 切换协议 |
200 | OK | 客户端请求成功 |
201 | Created | 服务器已经创建了文档,Location头给出了它的URL |
202 | Accepted | 已经接受请求,但处理尚未完成 |
203 | Non-Authoritative Information | 非权威信息,表明请求已成功,但封装的有效负载已由源服务器的200(OK)响应由变换代理修改。 |
204 | No Content | 没有新文档,浏览器应该继续显示原来的文档。操作已经执行成功,但是没有返回数据 |
300 | Multiple Choices | 客户端请求了实际指向多个资源的URL。这个代码是和一个选项列表一起返回的,然后用户就可以选择他希望的选项了 |
301 | Moved Permanently | 请求的网页已永久移动到新的位置,Response中应该包含一个Location URL, 说明资源现在所处的位置 |
302 | Found | 请求的网页临时移动到新的位置,Found是HTTP1.1的标准,Temporarily Moved是HTTP1.0的标准,使用redirect会产生302 |
304 | Not Modified | 未修改,服务器告诉客户,原来缓冲的文档还可以继续使用 |
305 | Use Proxy | 必须通过代理访问资源, 代理的地址在Response 的Location中 |
400 | Bad Request | 客户端请求语法有问题,或者是参数错误 |
401 | Unauthorized | 请求未经授权,客户端可以重复提交一个包含恰当的 Authorization 头信息的请求 |
403 | Forbidden | 服务器已经接收到请求,但拒绝提供服务,服务器通常会在响应正文中给出不能提供服务的原因 |
404 | Not Found | 请求的资源不存在 |
405 | Method Not Allowed | 客户端请求中的方法被禁止,常见如,由于DELETE、PUT请求对资源进行写操作,故大部分浏览器都不支持或者在默认配置下不允许DELETE、PUT请求 |
406 | Not Acceptable | 无法使用请求的内容特性响应请求的网页,和Accept字段有关 |
407 | Proxy Authentication Required | Web 服务器认为客户端发送的 HTTP 数据流是正确的,但访问该网址资源需要事先经过一个代理服务器,而该代理服务器所需的身份验证尚未提供。 这通常意味着您必须首先登录代理服务器。 |
408 | Request Timeout | 如果客户端完成请求时花费的时间太长, 服务器可以回送这个状态码并关闭连接 |
409 | Conflict | 响应状态码指示与服务器当前状态的请求冲突,如,在上传比服务器上已存在的文件更早的文件 |
410 | Gone | 服务器上的某个资源被永久性的删除 |
413 | Request Entity Too Large | 请求实体过大,如上传文件过大 |
414 | Request URI Too Long | 请求URI过长 |
500 | Internal Server Error | 服务器内部错误,无法完成请求,如服务器运行出现异常 |
501 | Not Implemented | 服务器不支持实现请求所需要的功能 |
502 | Bad Gateway | 代理使用的服务器遇到了上游的无效响应,常见如使用Nginx时,后端处理不过来,可能是内存或缓存使用方面出问题 |
503 | Service Unavailable | 服务不可用,暂时性的,可表示服务器正在维护 |
504 | Gateway Timeout | 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答 |
505 | HTTP Version Not Supported | HTTP版本不受支持 |
7. 总结
该笔记参考了以下文章:
Copyright © 2018, GDUT CSCW back-end Kanarien, All Rights Reserved