24 KiB
HTTP 基础
一:HTTP工作原理
1. 基本概念
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP协议工作于客户端-服务端(C/S;B/S)架构上;浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
Web服务器有:(Linux)Nginx,Apache服务器,(window-server)IIS服务器(Internet Information Services)等。
Web服务器根据接收到的请求后,向客户端发送响应信息。
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。
- HTTP协议默认端口号为80
- HTTPS协议默认端口号为443
2. HTTP协议特点
HTTP是无连接:
无连接的含义是限制每次连接只处理一个请求;服务器处理完客户的请求,并收到客户的应答后,即断开连接;采用这种方式可以节省传输时间。
HTTP是媒体独立的:
这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送;客户端以及服务器指定使用适合的MIME-TYPE内容类型(注意:mime类型是描述消息内容类型的因特网标准:多用途互联网邮件扩展)。
HTTP是无状态:
HTTP协议是无状态协议;无状态是指协议对于事务处理没有记忆能力;缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大;另一方面,在服务器不需要先前信息时它的应答就较快。
3. HTTP协议通信流程
- HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。
- 浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。一个HTTP"客户端"是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP请求的目的。
- Web服务器根据接收到的请求后,向客户端发送响应信息。一个HTTP"服务器"同样也是一个应用程序(通常是一个Web服务,如Apache Web服务器或IIS服务器等),通过接收客户端的请求并向客户端发送HTTP响应数据。
- HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。
通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。
4. HTTP交互原理
第一步:客户端/浏览器 发送给 服务端 一条Request请求报文,告诉服务器,我要浏览页面"www.example.com/index.html"。
第二步:服务器 返回给 客户端/浏览器 一条Response
应答报文,告诉客户端,好的!接收吧,这是你要的数据。
二:HTTP 消息结构
1. 客户端请求
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据。
2. 服务器响应
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
3. 实例
下面实例是一点典型的使用GET来传递数据的实例:
客户端请求:
# curl -v http://www.testpm.cn
Connected to www.testpm.cn (47.244.247.240) port 80 (#0)
> GET /hello.txt HTTP/1.1 # 请求方式与版本协议。
> User-Agent: curl/7.29.0 #用什么客户端访问
> Host: www.testpm.cn #主机名,域名。主机和端口号,
> Accept: */* #匹配什么文件类型,“*” 是通用匹配。匹配所有类型
服务端响应:
< HTTP/1.1 200 OK # 请求返回的状态码
< Server: nginx/1.16.0 # 请求的服务和版本号
< Date: Thu, 04 Jul 2019 08:19:40 GMT # 当前时间,北京时间为GMT+8小时
< Content-Type: text/plain # mime类型,test/plain:普通文本,比如image/png...、video
< Content-Length: 12 # 内容的长度
< Last-Modified: Thu, 04 Jul 2019 08:13:25 GMT #最后修改时间
< Connection: keep-alive #是否支持长连接
< ETag: "5d1db525-c" # 标识,每次访问如果与最开始的值一样返回304否则校验不一致返回200
< Accept-Ranges: bytes # 接受的范围单位
输出结果:
hello world
三:HTTP 其他特性
1. HTTP 中 Cache-Control
- 缓存控制:控制缓存的开关,用于标识请求或访问中是否开启了缓存,使用了哪种缓存方式。
- 缓存校验:如何校验缓存,比如怎么定义缓存的有效期,怎么确保缓存是最新的。
缓存控制:
在http中,控制缓存开关的字段有两个:Pragma 和 Cache-Control。
Pragma:
- Pragma有两个字段Pragma和Expires
- Pragma的值为no-cache时,表示禁用缓存
- Expires的值是一个GMT时间,表示该缓存的有效时间
注意:
- Pragma是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段。
- 如果一个报文中同时出现Pragma和Cache-Control时,以Pragma为准。
- 同时出现Cache-Control和Expires时,以Cache-Control为准。
- 优先级从高到低是 Pragma -> Cache-Control -> Expires
Cache-Control:
- 符合缓存策略时,服务器不会发送新的资源,但不是说客户端和服务器就没有会话了,客户端还是会发请求到服务器的
- Cache-Control除了在响应中使用,在请求中也可以使用
我们用调试器来模拟下请求时带上Cache-Control:勾选Disable cache,Request Headers中有个字段Cache-Control: no-cache
Cache-Control字段值:
在请求中使用Cache-Control 时,它可选的值有
字段名称 | 说明 |
---|---|
no-cache | 告知(代理)服务器不直接使用缓存,要求向原服务器发起请求 |
no-store | 所有内容都不会被保存到缓存或Inrernet临时文件 |
max-age=delta-seconds | 告知服务器客户端希望接受一个存在时间(Age)不大于delta-seconds秒的资源 |
max-stale [=delta-seconds] | 告知(代理)服务器客户端愿意接收一个超过缓存时间的资源,若有定义delta-seconds则为delta-seconds秒。若没有则为任意超出的时间 |
min-fresh=delta-seconds | 告知(代理)服务器客户端希望接收一个在小于delta-seconds秒内被更新的资源 |
no-transform | 告知(代理)代理服务器客户端希望获取实体数据没有被转换(比如压缩)过的资源 |
only-if-cached | 告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向原服务器发去请求 |
cache-extension | 自定义扩展值。若服务器不识别该值将被忽略掉 |
在响应中使用Cache-Control 时,它可选的值有
字段名称 | 说明 |
---|---|
public | 表明任何情况下都得缓存该资源(即使是需要HTTP认证的资源) |
Private[= "field-name"] | 表明返回报文中全部或部分(若指定了field-name则为field-name的字段数据)仅开放给某些用户(服务器指定的share-user,如代理服务器)做缓存使用,其他用户则不能缓存这些数据 |
no-cache | 不直接使用缓存,要求向服务器发起(新鲜度校验)请求 |
no-store | 所有内容都不会被保存到缓存或Inrernet临时文件 |
no-transform | 告知客户端缓存文件时不得对实体数据做任何改变 |
only-if-cached | 告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向原服务器发去请求 |
only-revalidate | 当前资源一定是向原服务器发去验证请求的,若请求失败会返回504(而非代理服务器上的缓存) |
proxy-revalidate | 与must-revalidate类似,但仅能应用于共享缓存(如代理) |
max-age=delta-seconds | 告知客户端该资源在delta-seconds秒内时新鲜的,无需向服务器发起请求 |
s-maxage=delta-seconds | 同max-age,但仅应用于共享缓存(如代理) |
cache-extension | 自定义扩展值。若服务器不识别该值将被忽略掉 |
缓存校验:
在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时并不需要重新发送。缓存校验就是用来解决这些问题的,在http 1.1 中,我们主要关注下Last-Modified 和 etag 这两个字段。
Last-Modified:
服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-Unmodified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不返回资源;如果不一致则返回200和修改后的资源,并带上新的时间。
注意:
- If-Modified-Since:告诉服务器如果时间一致,返回状态码304
- If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412(未满足前提条件)
etag:
单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理;etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。
注意:
- If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源
- If-Match:告诉服务器如果不一致,返回状态码412
2. HTTP 请求方法
根据HTTP标准,HTTP请求可以使用多种请求方法。
- HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
- HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
3. HTTP 状态码
当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码的英文为HTTP Status Code。
下面是常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL 永久重定向
- 302 - 临时重定向
- 304 - 缓存
- 403 - 访问被拒绝
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
HTTP状态码列表
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
100 | Continue | 继续。客户端应继续其请求 |
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
4. 关于URI
官方地址:标识互联网上的内容 - HTTP | MDN (mozilla.org)
HTTP 请求的内容通称为"资源"。"资源"这一概念非常宽泛,它可以是你能够想到的任何格式。每个资源都由一个 (URI) 来进行标识。
URI包含URL,URN
URL即统一资源定位符,它是 URI 的一种。可以是一份文档,一张图片,或所有其他。不仅标识了Web 资源,还指定了操作或者获取方式,同时指出了主要访问机制和网络位置。
URN是URI的一种,用特定命名空间的名字标识资源。使用URN可以在不知道其网络位置及访问方式的情况下讨论资源。
5. URL统一资源标识符语法
方案或协议
http://告诉浏览器使用何种协议。对于大部分 Web 资源,通常使用 HTTP 协议或其安全版本,HTTPS 协议。另外,浏览器也知道如何处理其他协议。例如, mailto: 协议指示浏览器打开邮件客户端;ftp:协议指示浏览器处理文件传输。常见方案见下表
方案 | 描述 |
---|---|
data | Data URIs |
file | 指定主机上文件的名称 |
ftp | 文件传输协议 |
http/https | 超文本传输协议/安全的超文本传输协议 |
mailto | 电子邮件地址 |
ssh | 安全 shell |
tel | 电话 |
urn | 统一资源名称 |
view-source | 资源的源代码 |
ws/wss | (加密的)WebSocket (en-US) 连接 |
主机
www.example.com既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的 IP address 地址发起请求。但直接使用 IP 地址的场景并不常见。
端口
:80 是端口。它表示用于访问 Web 服务器上资源的技术“门”。如果访问的该 Web 服务器使用 HTTP 协议的标准端口(HTTP 为 80,HTTPS 为 443)授予对其资源的访问权限,则通常省略此部分。否则端口就是 URI 必须的部分。
路径
/path/to/myfile.html 是 Web 服务器上资源的路径。在 Web 的早期,类似这样的路径表示 Web 服务器上的物理文件位置。现在,它主要是由没有任何物理实体的 Web 服务器抽象处理而成的。
查询
?key1=value1&key2=value2 是提供给 Web 服务器的额外参数。这些参数是用 & 符号分隔的键/值对列表。Web 服务器可以在将资源返回给用户之前使用这些参数来执行额外的操作。每个 Web 服务器都有自己的参数规则,想知道特定 Web 服务器如何处理参数的唯一可靠方法是询问该 Web 服务器所有者。
片段
#SomewhereInTheDocument 是资源本身的某一部分的一个锚点。锚点代表资源内的一种“书签”,它给予浏览器显示位于该“加书签”点的内容的指示。 例如,在 HTML 文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是 # 号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。