【HTTP 2】启用 HTTP 2(Starting HTTP/2)

前情提要

在上一篇文章《【HTTP
2】HTTP/2 协议概述(HTTP/2 Protocol Overview)
》中,简单介绍了 HTTP 2 规范的文档结构以及约定和术语。

本文变对 HTTP 2 规范的第一部分进行介绍,来说明如何发起一个 HTTP 2 连接。

启用 HTTP/2(Starting HTTP/2)

HTTP 2 连接是一个运行在 TCP 连接之上的应用层协议。客户端是
TCP 连接的发起者。

HTTP 2 保持了 HTTP 1.1 的风格,同样使用“http”和“https”作为 URI 的开始。并且共享相同的默认端口号:“http”使用 80 端口,“https”使用 443 端口。这意味着,相关实现要处理针对目标资源的请求,比如 http://example.org/foo 或者 https://example.com/bar,需要先知道上游服务器(该客户端当前希望建立的连接)是否支持 HTTP 2。

“http”和“https”支持 HTTP 2 的手段有所不同。“http”支持 HTTP 2 的方法在 3.2
详述,而“https”支持 HTTP 2 的方法在 3.3
详述。

HTTP/2 版本标识(HTTP/2 Version Identification)

本文档中所定义的协议有两个标识符。

字符串“h2”标识了使用传输安全层(TLS)的协议。该标识符用于
TLS 应用层协议协商(ALPN)扩展(TLS-ALPN)字段,在任何 TLS 之上的 HTTP 2 都会被该标识符标记。

“h2”字符串在 ALPN 协议标识中被序列化成两个八进制序列:0x68, 0x32。

字符串“h2c”标识了 HTTP 2 运行在明文 TCP 中。该标识符用于 HTTP 1.1 Upgrade 报文头中,在任何 TCP 之上的 HTTP 2 都会被该标识符标记。

选择“h2”或“h2c”意味着将会导致不同的传输、安全性、帧构成,以及在本文档中所描述的消息语法。

“http”中启用 HTTP/2(Starting HTTP/2 for “http” URIs)

一个客户端使用“http”发起请求,并不知道下一站是否支持 HTTP 升级机制。客户端通过发送 HTTP 1.1 请求,并包括 Upgrade 报文头,以“h2c”标识。这样的 HTTP 1.1 请求必须(MUST)有且仅有一个 HTTP2-Settings 报文头字段。

例如:

1
2
3
4
5
GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

在客户端发送 HTTP 2 帧之前,包含 Payload 的请求必须(MUST)被完整的发送。这意味着一个较大的请求将会阻塞连接,直到它被完全发送完毕。

如果初始请求与后续请求的并发非常重要,OPTIONS 请求可以用于升级至 HTTP 2 ,不过需要额外增加一次通信的成本。

不支持 HTTP 2 的服务器可以视 Upgrade 报文头不存在,进行如下响应:

1
2
3
4
5
HTTP/1.1
200
OK
Content-Length:
243
Content-Type:
text/html
 
...

服务器必须(MUST)忽略 Upgrade 报文头中的“h2”标识。“h2”标识意味着基于 TLS 的 HTTP/2,应该参考 3.3
进行协商。

支持 HTTP 2 的服务器接受了升级请求,并以状态码 101(转换协议)进行响应。在 101 响应的空行后,服务器可以开始发送 HTTP 2 帧。这些帧必须(MUST)包括升级请求对应的响应。

例如:

1
2
3
4
5
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
 
[ HTTP/2 connection ...

由服务器发送的第一个 HTTP 2 帧必须(MUST)是一个服务器连接序言(Connection Preface)(参考 3.5 章),并且包含一个 SETTINGS 帧(参考章节 6.5)。根据接收的 101 响应,客户端必须(MUST)发送一个同样包含 SETTINGS 帧的连接序言(Connection Preface)(参考章节 3.5)。

在升级之前所发送的 HTTP 1.1 请求,将被分配一个流标识符 “1”(参考章节 5.1.1),其优先级为默认级别(参考章节 5.3.5)。流 “1” 从 HTTP 1.1 请求完成后,是一个从客户端至服务器的隐性“半关闭”的流(参考章节 5.1)。在开始 HTTP 2 连接后,流 “1” 被用于响应。

HTTP2-Settings 报文头(HTTP2-Settings Header Field)

一个 HTTP 1.1 请求升级至 HTTP 2,必须(MUST)包含有且仅有一个 HTTP2-Settings 报文头。HTTP2-Settings 报文头是一个特定于连接的报头字段,其中的参数用于管理 HTTP 2 连接,在服务器接收升级请求时预先提供的。

1
HTTP2-Settings    =
token68

如果没有提供 HTTP2-Settings 报文头,或者提供了超过一个该报文头,服务器不可以(MUST NOT)升级该连接至 HTTP 2。服务器也不可以(MUST NOT)发送这个报文头。

HTTP2-Settings 报文头中的内容,是一个以 Base64 编码的 SETTINGS 帧的 Payload(即:URL 和安全文件名的 Base64 描述(RFC4648)的
5 章
,任何结尾的‘=’都将被忽略)。token68 的 ABNF(RFC5234)产物在 RFC7235 有所定义。

由于升级(Upgrade)只应用于直接连接,发送 HTTP2-Settings 的客户端必须(MUST)将 HTTP2-Settings 作为连接选项,包含在 Connection 报文头中,以防止它被转发(参考 RFC7230章节
6.1
)。

服务器解码并解释这些值,并将其看做其他 SETTINGS 帧。由于 101 响应作为了隐式确认,所以显式确认这些设置(参考章节 6.5.3)是没必要的。在升级请求中提供这些值,使得一个客户端有机会在接收服务器发 送的任何帧之前提供参数信息。

“https”中启用 HTTP/2(Starting HTTP/2 for “https” URIs)

一个发起“https”请求的客户端,需要用到 TLS(TLS1.2
和应用层协议协商(ALPN) 扩展(TLS-ALPN)。

TLS 之上的 HTTP 2 使用“h2”作为协议标识符。客户端一定不能(MUST NOT)发送“h2c”协议标识符,服务器也一定不能(MUST NOT)选择“h2c”标识符使用。“h2c”协议标识符描述了不适用 TLS 的协议。

一旦 TLS 协商完成,客户端和服务器都必须(MUST)发送一个连接序言(Connection preface)。

先验下启用 HTTP/2(Starting HTTP/2 with Prior Knowledge)

客户端可以通过其他方式判断服务器是否支持 HTTP 2。例如 ALT-SVC,它描述了一种机制使得 HTTP 具有广播能力。

客户端必须(MUST)发送连接序言(Connection preface,参考章节 3.5),然后可以(MAY)立即发送 HTTP 2 帧给服务器。服务端可以通过已存在的连接序言识别出这个连接。这只对基于明文 TCP 的 HTTP 2 连接建立有影响,TLS 之上的 HTTP 2 必须(MUST)使用 TLS 协议协商(TLS-ALPN)。

同样的,服务器必须(MUST) 发送连接序言(参考章节 3.5)。

如果没有其他信息,对 HTTP 2 之前的支持并不代表着指定服务器一定会在之后的连接中支持 HTTP 2。比如,服务器配置有可能改变,或者服务器集群中不同的实例配置有差异,亦或者网络状况的变化。

HTTP 2 连接序言(HTTP/2 Connection Preface)

在 HTTP 2 中,每个终端都需要发送一个连接序言作为协议的最终确认以及 HTTP 2 的连接初始设置。客户端和服务器均需要发送一个不同的连接序言。

客户端连接序言以 24 个字节序列开始,以十六进制表示为:

1
0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

也就是说,连接序言以字符串 PRI
* HTTP/2.0\r\n\r\nSM\r\n\r\n 
开头。这个序列后必须(MUST)跟着一个 SETTINGS 帧(参考章节 6.5),其可以(MAY)为空。客户端收到 101 (协议转换)响应后,立刻发送客户端连接序言。或者作为 TLS 连接的第一个应用数据字节。如果在语言验证服务器支持 HTTP 2 的情况下启用 HTTP 2 连接,客户端连接序言在连接建立后发送。

注意:客户端连接序言是用来让大部分 HTTP 1.1 或 HTTP 1.0 服务端及中介端不试图进一步处理帧。注意这并不能解决【TALKING】中提到的问题。

服务器连接序言包含一个可能是空的 SETTINGS 帧(参考章节 6.5),它必须在 HTTP 2 连接中首个发送。

从一个节点接收到的连接序言中所包含的 SETTINGS 帧必须在连接序言发送后被确认(参考章节 6.5.3)。

为了避免不必要的延迟,允许客户端在发送客户端连接序言之后立即发送其他额外的帧,不需要等待收到服务器端连接序言。不过,值得注意的是,服务端连接序言 SETTINGS 帧可能包含一些关于期望客户端如何与服务器端通信的必须修改的参数。在收到这些 SETTINGS 帧后,客户端应当遵守所有设置的参数。在有些配置中,服务器可能在客户端发送其他额外帧之前传输 SETTINGS,以提供一个避免这些问题的机会。

客户端和服务器必须(MUST)将一个非法的连接序言当做一个 PROTOCOL_ERROR 类型的连接错误(Connection error,参考章节 5.4.1)。在这个案例中,当一个节点不支持 HTTP 2 而出现非法序言时,GOAWAY 帧(参考章节 6.8)可以(MAY)被省略。


本文以 CC
BY-NC-SA 3.0 CN
 协议共享,转载、共享及二次创作时请保留原文出处及链接,请勿用于商业用途。

本文链接:http://litecodes.com/dev/http-2-spec-starting-http-2/

本系列文章将会在我的 GitBook:http2-spec-zh 同步更新,

下一篇文章将会翻译协议的第三部分:HTTP Frames(HTTP 帧),不要错过哟~

【HTTP 2】启用 HTTP 2(Starting HTTP/2)的更多相关文章

  1. 启用CentOS6.5 64位安装时自带的MySQL数据库服务器

    本人在虚拟机上又安装了一台linux机器,作为MySQL数据库服务器用,在安装时选择了系统自带的MySQL服务器端,以下是启用步骤. 首先开启mysqld服务 #service mysqld star ...

  2. springMVC注解启用及优化

    使用注解的原因 最方便的还是启用注解 注解方便,而且项目中很流行. 配置文件尽量减少,主要使用注解方式. Springmvc的注解是在2.5版本后有了注解,如何开启注解配置文件 Web.xml文件中不 ...

  3. CentOS 7.1 Bridge启用STP报错"Master connection not found or invalid"

    今天在公司测试Linux bridge搭建,为了使内部docker容器的网络能够不经过2层封装转发对外公布,顾试用一下bridge功能,结果碰到报错:"Bringing up interfa ...

  4. Nginx 启用 https

    在nginx.conf中增加新server配置 server { listen ; server_name www.some.com; ssl on; ssl_certificate sslkey/s ...

  5. 安装ESXi5.5遇到Relocating modules and starting up the kernel的处理

    在一些Dell较旧的服务器上安装ESXi 5.x时, 会遇到卡在Relocating modules and starting up the kernel过不去的问题. 比如我装的这台CS24VSS. ...

  6. [转]Hive:简单查询不启用Mapreduce job而启用Fetch task

    转自:http://www.iteblog.com/archives/831 如果你想查询某个表的某一列,Hive默认是会启用MapReduce Job来完成这个任务,如下: hive> SEL ...

  7. 启用VTX技术支持启动android的虚拟机 - 报错

    第一次启用VTX技术支持启动android的虚拟机,启动时提示如下错误: Starting emulator for AVD 'AVD_for_Android_TV_1080p_by_Google'e ...

  8. SpringMVC注释启用

    这篇文章是我学习的网络视频SpringMVC写的过程. 谢谢公布各位前辈的视频 以下评论SpringMVC几个关键步骤,注意事项启用: 首先需要加载配置文件(假设请使用自定义路径) <? xml ...

  9. ADS1.2和JlinkV8 erro starting external process,Process error code 87(0x57)参数错误

    ADS1.2和JlinkV8  erro starting external process,Process error code 87(0x57)参数错误 网上的大致说法是说这个跟W7有关 说是将I ...

随机推荐

  1. TMOUT

    设置TMOUT可以踢用户,直接从shell端. 实际上如果ssh或telnet也可以在其配置里面设定.

  2. 射频识别技术漫谈(11)——Mifare系列卡的共性

    Mifare是NXP公司生产的一系列遵守ISO14443A标准的射频卡,包Mifare S50.Mifare S70.Mifare UltraLight.Mifare Pro.Mifare Desfi ...

  3. php浮点数计算比较及取整不准确解决方法

    原文:php浮点数计算比较及取整不准确解决方法 php有意思的现象,应该是很多编程语言都会有这样的现象.这个是因为计算机的本身对浮点数识别的问题..... $f = 0.58; var_dump(in ...

  4. activemq在windows下启动报错,闪退问题

    查验了网上各种方法,都没搞定,最后楼主决定按照linux的解决套路来,把windows计算机名称改为纯英文字母,原计算机名:lee_pc,修改后为leepc,然后重启电脑,再重新运行activemq. ...

  5. perl lwp 超时问题

    lwp 超时问题: jrhmpt01:/root/async# cat a1.pl use LWP::UserAgent; use utf8; use DBI; use POSIX; use Data ...

  6. Create screenshots of a web page using Python and QtWebKit | Roland's Blog

    Create screenshots of a web page using Python and QtWebKit | Roland's Blog Create screenshots of a w ...

  7. Android开发中内置apk程序

    首先申明,这里的方法介绍是针对我司自己项目中的具体开发板而做的. Mg701内置APK有三种方式 一.         这种方法必须要自己编写Android.mk文件(关于Android.mk可以参考 ...

  8. MYSQL大小写(由于数据由windows迁移到Linux导致)

    今日从sqlserver上迁移了一个数据库到Linux的MySQL中,迁移成功了,但是应用却跑不通,查看日志发现,提示找不到表,我注意到,表名都是存在大小写的,而MySQL中的表名都是小写的.这提醒了 ...

  9. CSS——图片替换方法比较

    图片替换主要是指将文字替换成图片的技术,即在html语句中使用文字,浏览器显示时用对应的图片显示.其意义在于便于做网站优化(SEO),文字才是搜索引擎寻找的主要对象. 经典的替换方法: Fahrner ...

  10. PowerShell入门(序):为什么需要PowerShell?

    原文:http://www.cnblogs.com/ceachy/archive/2013/01/23/PowerShellPreface.html 曾几何时,微软的服务器操作系统因为缺乏一个强大的S ...