HTTP入门

资源和URI

引入:HTTP 请求的内容通称为“资源”。”资源”这一概念非常宽泛,它可以是一份文档,一张图片,或所有其他你能够想到的格式。每个资源都由一个 (URI) 来进行标识。

URI

URL(统一资源定位符)(Uniform Resource Locator)

URL又被称为Web地址,语法如下:

http://www.example.com:port/path/to/file/?key1=1&key2=2#somewhere

解析:

1.protocol(方案或协议)

常见的有http,https,具体如下表:

方案 描述
数据 数据 URI
文件 指定主机上文件的名称
FTP协议 文件传输协议
HTTP/HTTPS协议 超文本传输 协议/安全的超文本传输协议
mail至 电子邮件地址
SSH的 安全 shell
电话 电话
统一资源名称
查看源代码 资源的源代码
WS/WSS (加密的)WebSocket (en-US) 连接

2.主机

Domain Name(域名):www.example.com

www.example.com既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的 IP address 地址发起请求。但直接使用 IP 地址的场景并不常见。

3.端口(port)

port表示用于访问 Web 服务器上资源的技术“门”。如果访问的该 Web 服务器使用 HTTP 协议的标准端口(HTTP 为 80,HTTPS 为 443)授予对其资源的访问权限,则通常省略此部分。否则端口就是 URI 必须的部分。

4.路径(path)

/pah/to/file

/path/to/myfile.html是 Web 服务器上资源的路径。在 Web 的早期,类似这样的路径表示 Web 服务器上的物理文件位置。现在,它主要是由没有任何物理实体的 Web 服务器抽象处理而成的。

5.查询(参数)

?key1=1&key2=2

?key1=value1&key2=value2是提供给 Web 服务器的额外参数。这些参数是用 & 符号分隔的键/值对列表。Web 服务器可以在将资源返回给用户之前使用这些参数来执行额外的操作。每个 Web 服务器都有自己的参数规则,想知道特定 Web 服务器如何处理参数的唯一可靠方法是询问该 Web 服务器所有者。

6.片段

#somewhere

是资源本身的某一部分的一个锚点。锚点代表资源内的一种”书签”,它给予浏览器显示位于该”加书签”点的内容的指示。例如,在 HTML 文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是 # 号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。

举几个例子:

1
2
3
4
5
https://developer.mozilla.org/zh-CN/docs/Learn
tel:+1-816-555-1212
git@github.com:mdn/browser-compat-data.git
ftp://example.org/resource.txt
urn:isbn:9780141036144

URN

URN全称为Uniform Resource Name(统一资源名称),URN 是另一种形式的 URI,它通过特定命名空间中的唯一名称来标识资源。

1
2
urn:isbn:9780141036144
urn:ietf:rfc:7230

上面两个 URN 标识了下面的资源:

  • 乔治·奥威尔所著的《1984》
  • IETF 规范 7230,超文本传输 协议 (HTTP/1.1):Message Syntax and Routing.

Data URL

Ⅰ. 简介

Data URL,即前缀为 data: 协议的 URL,其允许内容创建者向文档中嵌入小文件。它们之前被称作“data URI”,直到这个名字被 WHATWG 弃用。

语法:data:[][;base64],

Data URL 由四个部分组成:前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 base64 标记、数据本身:

data:text/plain;base64,Hello World

Ⅱ.对数据base64编码

简介

Base64 是一组二进制到文本的编码方案,通过将其转换为 radix-64 表示形式,以 ASCII 字符串格式表示二进制数据。通过仅由 ASCII 字符组成,base64 字符串通常是 url 安全的,这就是为什么它们可用于在 Data URL 中编码数据。

作用:

Base64 编码方案通常用于需要对二进制数据进行编码的情况,这些数据需要通过设计用于处理 ASCII 的媒体进行存储和传输。这样是为了保证数据的完整并且不用在传输过程中修改这些数据。Base64 也被一些应用(包括使用 MIME 的电子邮件)和在 XML 中储存复杂数据时使用。

简单来说,信息从二进制方式变成文本方式

Base64 编码在网络上的一个常见应用是对二进制数据进行编码,以便将其纳入 data: URL 中。

附:Unicode: Unicode 是一个字符集,为世界上几乎所有的字符提供了唯一的标识符(Code Point)。

​ UTF-8:UTF-8(Unicode Transformation Format - 8-bit)是一种编码方案,用于在计算机系统中以字节的形式表示 Unicode 中的字符。

关系:
Unicode 和 UTF-8 是两个相关但不同的概念,它们在字符编码领域有着密切的关系。

  1. Unicode:
    • 定义: Unicode 是一个字符集,为世界上几乎所有的字符提供了唯一的标识符(Code Point)。
    • 特点: Unicode 提供了一个标准化的方式来表示和处理不同语言和符号的字符,以实现统一的字符编码方案。
    • 表示方式: Unicode 中的每个字符都有一个唯一的编号,称为 Code Point,通常用 U+XXXX 的形式表示,其中 “XXXX” 是十六进制的数字。
  2. UTF-8:
    • 定义: UTF-8(Unicode Transformation Format - 8-bit)是一种编码方案,用于在计算机系统中以字节的形式表示 Unicode 中的字符。
    • 特点: UTF-8 是一种可变长度的编码方案,能够表示 Unicode 中的所有字符,但对于 ASCII 字符,它只需要一个字节,这使得它在存储和传输时更为高效。
    • 编码规则: UTF-8 的编码规则是根据字符的 Unicode Code Point 来确定不同长度的字节序列。

关系:

  • Unicode 定义了字符集和每个字符的唯一标识(Code Point)。
  • UTF-8 是 Unicode 的一种实现方式,是一种将 Unicode 字符编码为字节序列的方法,可以在计算机系统中存储和传输文本数据。

MIME 类型(IANA 媒体类型)

简介

媒体类型(也通常称为多用途互联网邮件扩展MIME 类型)是一种标准,用来表示文档、文件或一组数据的性质和格式。它在 IETF 的 RFC 6838 中进行了定义和标准化。

附:IANA:互联网号码分配局,负责跟踪所有官方 MIME 类型。

MIME结构

1.MIME 类型通常仅包含两个部分:类型(type)和子类型(subtype),中间由斜杠 / 分割,中间没有空白字符:

结构:type/subtype

  • 类型(type):表示数据的大致分类,如videotext
  • **子类型(subtype)**:MIME 类型所代表的指定类型的确切数据类型。以 text 类型为例,它的子类型包括:plain(纯文本)、htmlHTML 源代码)、calender(iCalendar/.ics 文件)。

2.结构里允许参数

1
type/subtype;parameter=value

例如,对于主类型为 text 的任何 MIME 类型,可以添加可选的 charset 参数,以指定数据中的字符所使用的字符集。如果没有指定 charset,默认值为 ASCIIUS-ASCII),除非被用户代理的设置覆盖。要指定 UTF-8 文本文件,则使用 MIME 类型 text/plain;charset=UTF-8

附:UTF-8完美兼容ASCII字符

3.MIME类型有两类:独立的(discrete)和多部分的(multipart)。

独立类型(IANA目前已注册的)

  • application:不明确属于其他类型之一的任何二进制数据。
  • audio:音频或音乐数据。常见的示例如 audio/mpegaudio/vorbis
  • example:在演示如何使用 MIME 类型的示例中用作占位符的保留类型。也可以作为子类型。
  • font:字体/字型数据。常见的示例如 font/wofffont/ttffont/otf
  • image:图像或图形数据,常见的例子有 image/jpegimage/pngimage/svg+xml
  • model:三维物体或场景的模型数据。示例包含 model/3mfmodel/vrml
  • text:纯文本数据,示例包含:text/plaintext/csvtext/html
  • video:视频数据或文件,例如 MP4 电影(video/mp4)。

多部分类型

多部分类型指的是一类可分成不同部分的文件,其各部分通常是不同的 MIME 类型;也可用于——尤其在电子邮件中——表示属于同一事务的多个独立文件。它们代表一个复合文档

有两种多部分类型(初学没有深入了解):

message

封装其他信息的信息。例如,这可以用来表示将转发信息作为其数据一部分的电子邮件,或将超大信息分块发送,就像发送多条信息一样。例如,message/rfc822(用于转发或回复信息的引用)和 message/partial(允许将大段信息自动拆分成小段,由收件人重新组装)是两个常见的例子。(查看 IANA 上 message 类型的注册表

multipart

由多个组件组成的数据,这些组件可能各自具有不同的 MIME 类型。例如,multipart/form-data(用于使用 FormData API 生成的数据)和 multipart/byteranges(定义于 RFC 7233, section 5.4.1,当获取到的数据仅为部分内容时——如使用 Range 标头传输的内容——与返回的 HTTP 响应 206 “Partial Content”组合使用)。(查看 IANA 上 multipart 类型的注册表

对Web开发者至关重要的MIME类型

application/octet-stream

这是二进制文件的默认值.。由于这意味着未知的二进制文件,浏览器一般不会自动执行或询问执行。

text/plain

这是文本文件的默认值。即使它其实意味着未知的文本文件,但浏览器认为是可以直接展示的。

text/css

在网页中要被解析为 CSS 的任何 CSS 文件必须指定 MIME 为 text/css。通常,如果服务器不识别 CSS 文件的 .css 后缀,则可能将它们以 MIME 为 text/plainapplication/octet-stream 来发送给浏览器:在这种情况下,大多数浏览器不将其识别为 CSS 文件而直接忽略。

text/html

所有的 HTML 内容都应该使用这种类型。

text/javascript

JavaScript 内容应始终使用 MIME 类型 text/javascript 提供。其他 MIME 类型对 JavaScript 无效,使用除 text/javascript 以外的任何 MIME 类型都可能导致脚本无法加载或运行。另外,。对于 JavaScript 内容来说,charset 参数无效,在大多数情况下会导致脚本加载失败。

以下是常用的图像类型,可在网页中安全使用:

multipart/form-data

multipart/form-data可用于HTML表单发送信息给服务器

multipart/byteranges

multipart/byteranges 用于把部分的响应报文发送回浏览器。

正确设置MIME类型

很多 web 服务器使用默认的 application/octet-stream 来发送未知类型。出于一些安全原因,对于这些资源浏览器不允许设置一些自定义默认操作,强制用户必须存储到本地以使用。

常见的导致服务器配置错误的文件类型如下所示:

  • RAR 压缩文件。在这种情况,理想状态是,设置真实的编码文件类型;但这通常不可能,因为 .RAR 文件可能包含多种不同类型的资源。这种情况,将所发送文件的 MIME 类型配置为 application/x-rar-compressed
  • 音频或视频文件。只有正确设置了 MIME 类型的文件才能被 ```` 元素识别和播放。请确保指定了正确的音频和视频的媒体类型
  • 专有文件类型。避免使用 application/octet-stream,对于这种一般的 MIME 类型浏览器不允许定义默认行为(比如“在 Word 中打开”)。像 application/vnd.mspowerpoint 这样的类型可以让用户选择自动在幻灯片软件中打开这样的文件。

MIME嗅探

在缺失 MIME 类型或客户端认为文件设置了错误的 MIME 类型时,浏览器可能会通过查看资源来进行 MIME 嗅探

简单来说即是通过其他方法得知数据类型。

由于某些 MIME 类型可能代表可执行内容,会存在一些安全问题。服务器可以通过发送 X-Content-Type-Options 标头来阻止 MIME 嗅探。

可知MIME嗅探并非是一件好事,比如xss攻击等等,一些安全专业人士主张禁用或限制 MIME 嗅探,并强调在服务器端正确设置 “Content-Type” 标头以提供准确的文件类型信息。此外,使用 X-Content-Type-Options 头来控制浏览器是否进行 MIME 嗅探也是一种辅助措施。

其他传送文件类型的方法

  • 有时会使用名称后缀,特别是在 Microsoft Windows 系统上。并非所有的操作系统都认为这些后缀是有意义的(特别是 Linux 和 Mac OS),并且像外部 MIME 类型一样,不能保证它们是正确的。
  • 魔数(magic number)。不同类型的文件的语法通过查看结构来允许文件类型推断。例如,每个 GIF 文件以 47 49 46 38 39 十六进制值(GIF89)开头,每个 PNG 文件以 89 50 4E 47.PNG)开头。并非所有类型的文件都有魔数,所以这也不是 100% 可靠的方式。

HTTP指南

HTTP概述

HTTP 是一种用作获取诸如 HTML 文档这类资源的协议。它是 Web 上进行任何数据交换的基础,同时,也是一种客户端—服务器(client-server)协议

客户端和服务器之间通过HTTP协议通过交换一个个独立的消息(而非数据流)进行通信。客户端发出的消息称为请求(request),服务端接收的应答消息称为响应(response)

基于HTTP的组件系统

客户端与服务器间的链条

客户端(Client):用户代理

用户代理是任何能够代表用户行为的工具。这类工具以浏览器为主,不过,它也可能是工程师和 Web 开发人员调试应用所使用的那些程序。

一般情况下总是浏览器发起请求而非是服务端,不过后来加入了一些机制,能够模拟由服务端发出的消息。

Web服务端(Server):

在上述通信过程的另一侧是服务端,它负责提供客户端所请求的文档。一个服务端可以假装表现为仅有一台机器,但实际上,它可以是共享负载的一组服务器集群(负载均衡)或是其他类型的软件(如缓存、数据库服务、电商服务等),按需完整或部分地生成文档。

此外,一个服务器可以不仅仅只有一台机器,而多个服务端软件实例也可部署在同一台机器上。

代理:

在浏览器和服务器之间,有许多计算机和设备参与传递了 HTTP 消息。依靠 Web 技术栈的层次化的结构,传递过程中的多数操作都位于传输层、网络层或物理层,它们对于 HTTP 应用层而言就是透明的,并默默地对网络性能产生着重要影响。还有一部分实体在应用层参与消息传递,一般被称为代理(Proxy)。代理可以是透明的,即转发它们收到的请求并不做任何修改,也可以表现得不透明,将它传递给服务端之前使用一些手段修改这个请求。代理可以发挥很多种作用:

  • 缓存(可以是公开的也可以是私有的,如浏览器的缓存)
  • 过滤(如反病毒扫描、家长控制…)
  • 负载均衡(让多个服务器服务不同的请求)
  • 认证(控制对不同资源的访问)
  • 日志(使得代理可以存储历史信息)

HTTP的基本性质

  • HTTP是简约的
  • HTTP是可扩展的:HTTP标头(header)
  • HTTP无状态,但并非无回会话
  • HTTP和网络连接

HTTP报文

HTTP/1.1 以及更早的 HTTP 协议报文都是语义可读的。在 HTTP/2 中,这些报文被嵌入到了一个新的二进制结构,帧。帧允许实现很多优化,比如报文标头的压缩以及多路复用。即使只有原始 HTTP 报文的一部分以 HTTP/2 发送出来,每条报文的语义依旧不变,客户端会重组原始 HTTP/1.1 请求。因此用 HTTP/1.1 格式来理解 HTTP/2 报文仍旧有效。

请求报文:一个基础的 HTTP 请求

  1. 一个HTTP方法,可以是GET,POST等等,以此定义客户端执行的操作
  2. 要获取的资源的路径
  3. HTTP协议版本号
  4. 请求头,又称为HTTP标头
  5. 请求体

响应报文:HTTP 响应的图片

  1. HTTP协议版本号
  2. 一个状态码,指明操作是否成功以及原因
  3. 一个状态信息,这个信息是一个不权威、简短的状态码描述
  4. 响应头,与请求头相似
  5. 可选项,一个包含了被获取资源的主体

附:API:API就像一家餐厅中的点餐窗口,提供了一个标准化的接口,使得应用程序能够与服务进行交互,请求执行特定的功能或获取数据。这种交互通过HTTP协议实现,就像服务员在点餐窗口和厨房之间传递顾客的需求和厨房的服务一样

附:HTTP/2与HTTP/1.1有几处基本的不同:

  • HTTP/2 是二进制协议而不是文本协议。不再可读,也不可无障碍的手动创建,改善的优化技术现在可被实施。
  • 这是一个多路复用协议。并行的请求能在同一个链接中处理,移除了 HTTP/1.x 中顺序和阻塞的约束。
  • 压缩了标头。因为标头在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本。
  • 其允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求。

HTTP标头(header)

推荐:https://juejin.cn/post/6844903745004765198

请求头

分类:
常用请求头:
1.Accept

Accept: type/subtype,浏览器可以接受服务器发来的数据类型

2.Accept-Encoding

浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(注意:这不是只字符编码)。

3.Accept-Language

浏览器申明自己接受的语言

4.Connecction
  • Connection: keep-alive :建立稳定的TCP链接,客户端下次访问此处时会继续使用该链接
  • Connection: close :当前Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
5.Host(必须的)

目标主机和端口号,通常在URL里提取

6.Referer

告诉服务器我从哪个页面来

7.User-Agent

告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本

8.Cache-Control

值:

  • private:默认值,应只能够作为私有的缓存,不能在用户间共享
  • public:响应会被缓存,并且在多用户间共享。
  • must-revalidate:响应在特定条件下会被重用,以满足接下来的请求,但是它必须到服务器端去验证它是不是仍然是最新的
  • no-cache:响应不会被缓存,而是实时向服务器端请求资源
  • max-age=num:设置缓存最大的有效时间,但是这个参数定义的是时间大小(比如:60)而不是确定的时间点。单位是[秒 seconds]。
  • no-store:任何条件下,响应都不会被缓存,并且不会被写入到客户端的磁盘里,这也是基于安全考虑的某些敏感的响应才会使用这个。

Cookie是用来存储一些用户信息以便让服务器辨别用户身份

10.Range(用于断点续传)

Range:bytes=0-5:指定第一个字节的位置和最后一个字节的位置。用于告诉服务器自己想取对象的哪部分。

11.X-Forwarded-For

该标头用来表示 HTTP 请求端真实 IP,可伪造

概览
  • Accept:指定客户端能够接收的内容类型。

  • Accept-Charset:浏览器可以接受的字符编码集。

  • Accept-Encoding:指定浏览器可以支持的web服务器返回内容压缩编码类型。

  • Accept-Language:浏览器可接受的语言。

  • Accept-Ranges:可以请求网页实体的一个或者多个子范围字段。

  • AuthorizationHTTP:授权的授权证书。

  • Cache-Control:指定请求和响应遵循的缓存机制。

  • Connection:表示是否需要持久连接。(HTTP 1.1默认进行持久连接)

  • CookieHTTP:请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。

  • Content-Length:请求的内容长度。

  • Content-Type:请求的与实体对应的MIME信息。

  • Date:请求发送的日期和时间。

  • Expect:请求的特定的服务器行为。

  • From:发出请求的用户的Email。

  • Host:指定请求的服务器的域名和端口号。

  • If-Match:只有请求内容与实体相匹配才有效。

  • If-Modified-Since:如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码。

  • If-None-Match:如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变。

  • If-Range:如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。

  • If-Unmodified-Since:只在实体在指定时间之后未被修改才请求成功。

  • Max-Forwards:限制信息通过代理和网关传送的时间。

  • Pragma:用来包含实现特定的指令。

  • Proxy-Authorization:连接到代理的授权证书。

  • Range:只请求实体的一部分,指定范围。

  • Referer:先前网页的地址,当前请求网页紧随其后,即来路。

  • TE:客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息。

  • Upgrade:向服务器指定某种传输协议以便服务器进行转换(如果支持。

  • User-AgentUser-Agent:的内容包含发出请求的用户信息。

  • Via:通知中间网关或代理服务器地址,通信协议。

  • Warning:关于消息实体的警告信息

响应头

分类:
常见响应头:
1.Cache-Control

(对应请求中的Cache-Control)

2..Content-Type

告诉客户端资源文件的类型以及相应的字符编码方式。(注意,这里是字符编码而不是传输编码)

3.Content-Encoding

告诉客户端二进制资源通过什么方式(比如gzip)对二进制资源实体进行压缩。

附:gzip 是一种压缩算法,用于将二进制数据流(包括文本和其他数据类型)进行压缩。gzip 并不是将文本编码成二进制数据流,而是对已有的二进制数据进行压缩,以减小数据的体积。

4.Date

Date: Tue, 03 Apr 2018 03:52:28 GMT 这个是服务端发送资源时的服务器时间,GMT是格林尼治所在地的标准时间。http协议中发送的时间都是GMT的,这主要是解决在互联网上,不同时区在相互请求资源的时候,时间混乱问题。

5.Server

表明服务器类型和对应的版本

6.Transfer-Encoding

Transfer-Encoding:chunked 这个响应头告诉客户端,服务器发送的资源的方式是分块发送的。一般分块发送的资源都是服务器动态生成的,在发送时还不知道发送资源的大小,所以采用分块发送,每一块都是独立的,独立的块都能标示自己的长度,最后一块是0长度的,当客户端读到这个0长度的块时,就可以确定资源已经传输完了。

7.Expires

Expires:Sun, 1 Jan 2000 01:00:00 GMT 这个响应头也是跟缓存有关的,告诉客户端在这个时间前,可以直接访问缓存副本,很显然这个值会存在问题,因为客户端和服务器的时间不一定会都是相同的,如果时间不同就会导致问题。所以这个响应头是没有Cache-Control:max-age=*这个响应头准确的,因为max-age=date中的date是个相对时间,不仅更好理解,也更准确。

8.Last-Modified

Last-Modified: Dec, 26 Dec 2015 17:30:00 GMT 所请求的对象的最后修改日期(按照 RFC 7231 中定义的“超文本传输协议日期”格式来表示)

9.Connection

Connection:keep-alive 回应客户端的Connection:keep-alive,告诉客户端服务器的tcp连接也是一个长连接,客户端可以继续使用这个tcp连接发送http请求。

10.Etag

ETag: “737060cd8c284d8af7ad3082f209582d” 就是一个对象(比如URL)的标志值,就一个对象而言,比如一个html文件,如果被修改了,其Etag也会别修改,所以,ETag的作用跟Last-Modified的作用差不多,主要供WEB服务器判断一个对象是否改变了。比如前一次请求某个html文件时,获得了其 ETag,当这次又请求这个文件时,浏览器就会把先前获得ETag值发送给WEB服务器,然后WEB服务器会把这个ETag跟该文件的当前ETag进行对比,然后就知道这个文件有没有改变了。

11.Refresh

Refresh: 5; url=http://baidu.com 用于重定向,或者当一个新的资源被创建时。默认会在5秒后刷新重定向。

12.Access-Control-Allow-Origin

Access-Control-Allow-Origin: * 号代表所有网站可以跨域资源共享,如果当前字段为那么Access-Control-Allow-Credentials就不能为true

Access-Control-Allow-Origin: www.baidu.com 指定哪些网站可以跨域资源共享

13.Access-Control-Allow-Methods

Access-Control-Allow-Methods:GET,POST,PUT,DELETE 允许哪些方法来访问

14.Access-Control-Allow-Credentials

Access-Control-Allow-Credentials: true 是否允许发送cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。如果access-control-allow-origin为*,当前字段就不能为true

15.Content-Range

Content-Range: bytes 0-5/7877 指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。

概览
  • Accept-Ranges:表明服务器是否支持指定范围请求及哪种类型的分段请求。

  • Age:从原始服务器到代理缓存形成的估算时间(以秒计,非负)。

  • Allow:对某网络资源的有效的请求行为,不允许则返回405。

  • Cache-Control:告诉所有的缓存机制是否可以缓存及哪种类型。

  • Content-Encodingweb:服务器支持的返回内容压缩编码类型。。

  • Content-Language:响应体的语言。

  • Content-Length:响应体的长度。

  • Content-Location:请求资源可替代的备用的另一地址。

  • Content-MD5:返回资源的MD5校验值。

  • Content-Range:在整个返回体中本部分的字节位置。

  • Content-Type:返回内容的MIME类型。

  • Date:原始服务器消息发出的时间。

  • ETag:请求变量的实体标签的当前值。

  • Expires:响应过期的日期和时间。

  • Last-Modified:请求资源的最后修改时间。

  • Location:用来重定向接收方到非请求URL的位置来完成请求或标识新的资源。

  • Pragma:包括实现特定的指令,它可应用到响应链上的任何接收方。

  • Proxy-Authenticate:它指出认证方案和可应用到代理的该URL上的参数。

  • refresh:应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)

  • Retry-After:如果实体暂时不可取,通知客户端在指定时间之后再次尝试。

  • Serverweb:服务器软件名称。

  • Set-Cookie:设置Http Cookie。

  • Trailer:指出头域在分块传输编码的尾部存在。

  • Transfer-Encoding:文件传输编码。

  • Vary:告诉下游代理是使用缓存响应还是从原始服务器请求。

  • Via:告知代理客户端响应是通过哪里发送的。

  • Warning:警告实体可能存在的问题。

  • WWW-Authenticate:表明客户端请求实体应该使用的授权方案。

HTTP会话过程

第一步:客户端建立一条 TCP 连接(如果传输层不是 TCP,也可以是其他适合的连接)。

第二步:客户端发送请求并等待应答。(Resquest)

第三步:服务器处理请求并送回应答,回应包括一个状态码和对应的数据。(Response)

从 HTTP/1.1 开始,连接在完成第三阶段后不再关闭,客户端可以再次发起新的请求。这意味着第二步和第三步可以连续进行数次。

HTTP/1.x 的连接管理

讨论四种方式:

Ⅰ.短连接

HTTP/1.0的默认方式,每次会话都要重新建立TCP连接

建立TCP 连接本身就是耗费时间的,可以保持更多的TCP热连接来适应负载。短连接破坏了 TCP 具备的能力,并且新的冷连接降低了其性能。

这是 HTTP/1.0 的默认模型(如果没有指定 Connection 协议头,或者是值被设置为 close)。而在 HTTP/1.1 中,只有当 Connection 被设置为 close 时才会用到这个模型。

Ⅱ.长连接

长连接又被称为keep-alive连接

长连接会在空闲一段时间后自动关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。

长连接缺点:长连接在空闲状态仍然会消耗服务器资源,而且在重负载时还有可能遭受 DoS 攻击。这种场景下可以使用非长连接,即尽快关闭那些空闲的连接,也能对性能有所提升。

注意:

HTTP/1.0 里默认并不使用长连接。把 Connection 设置成 close 以外的其他参数都可以让其保持长连接,通常会设置为 retry-after

在 HTTP/1.1 里,默认就是长连接的,不再需要标头(但我们还是会把它加上,万一某个时候因为某种原因要退回到 HTTP/1.0 呢)。

Ⅲ.流水线

流水线并发多个请求,在提高性能的同时对服务端的要求提高,并且也存在新的风险。

附:

HTTP 流水线在现代浏览器中并不是默认被启用的:

  • 有缺陷的代理服务器仍然很常见,这些会导致 Web 开发人员无法预见和轻松诊断的奇怪和不稳定行为。
  • 正确的实现流水线是复杂的:传输中的资源大小、多少有效的 RTT 会被用到以及有效带宽都会直接影响到流水线提供的改善。不知道这些的话,重要的消息可能被延迟到不重要的消息后面。这个重要性的概念甚至会演变为影响到页面布局!因此 HTTP 流水线在大多数情况下带来的改善并不明显。
  • 流水线受制于队头阻塞(HOL)问题。

由于这些原因,流水线已被 HTTP/2 中更好的算法——多路复用(multiplexing)所取代。

Ⅳ.域名分块

须知:

除非你有紧急而迫切的需求,不要使用这一过时的技术;而是升级到 HTTP/2。在 HTTP/2 里,做域名分片就没必要了:HTTP/2 的连接可以很好的处理并发的无优先级的请求。域名分片甚至会影响性能。大多数 HTTP/2 的实现还会使用一种称作连接聚合的技术去尝试合并被分片的域名。

简单来说,创建多个通向主域名的附域名,每个域名又有多个连接。如下图:

Without domain sharding, a client requests six images from a domain with a maximum of two requests taking place in parallel. With domain sharding, the images are available from two domains and the client can run four requests in parallel, downloading the images in less time.

HTTP协议升级

简单解释:

  1. 初始状态,较为低级
  2. 由客户端提出升级请求
  3. 协商升级(客户端发送一个请求头部包含 Upgrade: websocket,表示想要升级到 WebSocket 协议,服务端同意升级)
  4. 升级成功,切换到一个新的协议(如 WebSocket)

HTTP安全

内容安全策略(CSP)

概述

Content-Security-Policy,是一个额外的安全层,用于检测并削弱一些特定的攻击,如XSS(跨站脚本攻击),数据注入攻击等等。

为使 CSP 可用,需要配置网络服务器返回 Content-Security-Policy HTTP 标头(X-Content-Security-Policy` 标头是旧版本的,无须再如此指定)。

除此之外,元素也可以被用来配置该策略,例如

1
2
3
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';" />

可缓解的威胁

缓解跨站脚本攻击(XSS)

CSP 的主要目标是减少和报告 XSS 攻击。XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。

CSP制定了一个白名单域(制定白名单是一个好习惯),一个CSP兼容的浏览器仅会执行从白名单域获取到的脚本文件,其余的忽略。

缓解数据包嗅探攻击

除限制可以加载内容的域,服务器还可指明哪种协议允许使用;比如(从理想化的安全角度来说),服务器可指定所有内容必须通过 HTTPS 加载。一个完整的数据安全传输策略不仅强制使用 HTTPS 进行数据传输,也为所有的 cookie 标记 secure 标识,并且提供自动的重定向使得 HTTP 页面导向 HTTPS 版本。网站也可以使用 Strict-Transport-Security HTTP 标头确保连接它的浏览器只使用加密通道。

通过导向HTTPS进而避免数据包嗅探攻击。

使用CSP

制定策略:

使用 Content-Security-Policy HTTP 标头来指定策略,如下:

1
Content-Security-Policy: policy

策略(policy)参数是一个包含了各种描述你的 CSP 策略指令的字符串。

编写策略:

策略由一系列策略指令所组成,每个策略指令都描述了针对某个特定资源的类型以及策略生效的范围。策略应当包含一个default-src策略指令,在其他资源类型没有符合自己的策略时应用该策略。

对策略进行测试:

使用 Content-Security-Policy-Report-Only HTTP 标头来指定策略,如下:

1
Content-Security-Policy-Report-Only: policy

附:

如果 Content-Security-Policy-Report-Only 标头和 Content-Security-Policy 同时出现在一个响应中,两个策略均有效。在 Content-Security-Policy 标头中指定的策略有强制性,而 Content-Security-Policy-Report-Only 中的策略仅产生报告而不具有强制性。

启用报告:

默认情况下不发送报告,需要指定report-to策略指令,并提供至少一个URI地址以递交报告,如下:

1
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

然后需要设置服务器能够接收报告;使其能够以恰当的方式存储并处理这些报告。

违规报告的语法:
1.blocked-uri

被 CSP 阻止的资源 URI。如果被阻止的 URI 来自不同的源而非 document-uri,那么被阻止的资源 URI 会被删减,仅保留协议、主机和端口号。

2.disposition

根据 Content-Security-Policy-Report-OnlyContent-Security-Policy 标头使用情况的不同,值为 "enforce""report"

3.document-uri

发生违规文档的URI

4.effective-directive

导致违规行为发生的指令。一些浏览器可能提供不同的值,例如 Chrome 提供 style-src-elemstyle-src-attr,即使实际执行的指令是 style-src

5.original-policy

Content-Security-Policy HTTP 标头指定的原始策略值。

6.referer

违规发生的地址

7.script-sample

导致该违规的内联代码、事件处理器或样式的前 40 个字符。只适用于 script-src*style-src* 包含 'report-sample' 的情况。

8.status-code

全局对象被实例化的资源的 HTTP 状态代码。

9.violated-directive

导致违反策略的指令。violated-directiveeffective-directive 字段的历史名称,并包含相同的值。

违规报告的样本:

页面位于http://example.com/signup.html,假设有如下策略:

1
Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports

在样本HTML文档中:

1
<link rel="stylesheet" href="css/style.css" />

这里仅允许加载自 cdn.example.com 的样式表,然而该页面企图从自己的源(http://example.com)加载。当该文档被访问时,一个兼容 CSP 的浏览器将以 POST 请求的形式发送违规报告到 http://example.com/_/csp-reports,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"csp-report": {
"blocked-uri": "http://example.com/css/style.css",
"disposition": "report",
"document-uri": "http://example.com/signup.html",
"effective-directive": "style-src-elem",
"original-policy": "default-src 'none'; style-src cdn.example.com; report-to /_/csp-reports",
"referrer": "",
"status-code": 200,
"violated-directive": "style-src-elem"
}
}