目录搜索
GuidesAccess control CORSAuthenticationBrowser detection using the user agentCachingCaching FAQCompressionConditional requestsConnection management in HTTP 1.xContent negotiationContent negotiation: List of default Accept valuesCookiesCSPMessagesOverviewProtocol upgrade mechanismProxy servers and tunnelingProxy servers and tunneling: Proxy Auto-Configuration (PAC) filePublic Key PinningRange requestsRedirectionsResources and specificationsResources and URIsResponse codesServer-Side Access ControlSessionGuides: BasicsBasics of HTTPChoosing between www and non-www URLsData URIsEvolution of HTTPIdentifying resources on the WebMIME TypesMIME types: Complete list of MIME typesCSPContent-Security-PolicyContent-Security-Policy-Report-OnlyCSP: base-uriCSP: block-all-mixed-contentCSP: child-srcCSP: connect-srcCSP: default-srcCSP: font-srcCSP: form-actionCSP: frame-ancestorsCSP: frame-srcCSP: img-srcCSP: manifest-srcCSP: media-srcCSP: object-srcCSP: plugin-typesCSP: referrerCSP: report-uriCSP: require-sri-forCSP: sandboxCSP: script-srcCSP: style-srcCSP: upgrade-insecure-requestsCSP: worker-srcHeadersAcceptAccept-CharsetAccept-EncodingAccept-LanguageAccept-RangesAccess-Control-Allow-CredentialsAccess-Control-Allow-HeadersAccess-Control-Allow-MethodsAccess-Control-Allow-OriginAccess-Control-Expose-HeadersAccess-Control-Max-AgeAccess-Control-Request-HeadersAccess-Control-Request-MethodAgeAllowAuthorizationCache-ControlConnectionContent-DispositionContent-EncodingContent-LanguageContent-LengthContent-LocationContent-RangeContent-TypeCookieCookie2DateDNTETagExpectExpiresForwardedFromHeadersHostIf-MatchIf-Modified-SinceIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveLarge-AllocationLast-ModifiedLocationOriginPragmaProxy-AuthenticateProxy-AuthorizationPublic-Key-PinsPublic-Key-Pins-Report-OnlyRangeRefererReferrer-PolicyRetry-AfterServerSet-CookieSet-Cookie2SourceMapStrict-Transport-SecurityTETkTrailerTransfer-EncodingUpgrade-Insecure-RequestsUser-AgentUser-Agent: FirefoxVaryViaWarningWWW-AuthenticateX-Content-Type-OptionsX-DNS-Prefetch-ControlX-Forwarded-ForX-Forwarded-HostX-Forwarded-ProtoX-Frame-OptionsX-XSS-ProtectionMethodsCONNECTDELETEGETHEADMethodsOPTIONSPATCHPOSTPUTStatus100 Continue101 Switching Protocols200 OK201 Created202 Accepted203 Non-Authoritative Information204 No Content205 Reset Content206 Partial Content300 Multiple Choices301 Moved Permanently302 Found303 See Other304 Not Modified307 Temporary Redirect308 Permanent Redirect400 Bad Request401 Unauthorized403 Forbidden404 Not Found405 Method Not Allowed406 Not Acceptable407 Proxy Authentication Required408 Request Timeout409 Conflict410 Gone411 Length Required412 Precondition Failed413 Payload Too Large414 URI Too Long415 Unsupported Media Type416 Range Not Satisfiable417 Expectation Failed426 Upgrade Required428 Precondition Required429 Too Many Requests431 Request Header Fields Too Large451 Unavailable For Legal Reasons500 Internal Server Error501 Not Implemented502 Bad Gateway503 Service Unavailable504 Gateway Timeout505 HTTP Version Not Supported511 Network Authentication RequiredStatus
文字

在HTTP协议提供了一个特殊机制,使已建立的连接升级到一个新的,不兼容,协议。本指南介绍了它的工作原理,并提供了其使用场景的示例。

此机制始终由客户端启动(有一个例外:服务器可能需要升级到TLS),并且服务器可能接受或拒绝切换到新协议。这使得使用常用协议(如HTTP / 1.1)启动连接成为可能,然后请求连接切换到HTTP / 2或甚至到WebSocket。

握手

协议升级总是由客户请求; 没有为服务器提供请求协议更改的机制。当客户机希望升级到新的协议,它通过发送任何类型的正常请求发送到服务器(这样做GETPOST等)。但是,该请求需要专门配置以包含升级请求。

特别是,请求需要这两个额外的头文件:

Connection: UpgradeConnection头被设置为"Upgrade"以表示的升级要求。Upgrade: protocols所述Upgrade标头指定的一个或多个以逗号分隔的协议名称,首选项的顺序。

根据请求的协议,可能需要其他头文件; 例如,WebSocket升级允许额外的头部配置关于WebSocket连接的细节,并在打开连接时提供一定程度的安全性。有关更多详细信息,请参阅升级到WebSocket连接。

服务器可拒绝升级-在这种情况下,它仅仅是忽略了"Upgrade"头并发送回一个普通的响应("200 OK"如果它可以提供所请求的资源时,30x如果它要执行重定向,状态码40x50x一个如果不能提供请求的资源) - 或接受升级。在这种情况下,它会发送一个"101 Switching Protocols"带有升级标头的指定所选协议的标头。

在发送101状态码之后,如果新协议要求它发生新的协议的最终握手,则服务器"Upgrade"按照新的协议规则发送原始请求(包括标头的请求)所请求的答案。

101状态码

101状态代码被发送作为对包括一个请求的响应"Upgrade"报头以信号通知请求的接收方愿意升级到所期望的协议之一。如果"101 Switching Protocols"状态码被返回,则标题还必须包含描述所选协议的标题ConnectionUpgrade标题。请参阅此机制的常见用法中的示例,以了解有关这种机制的更多信息。

虽然您可以使用协议升级机制将HTTP / 1.1连接升级到HTTP / 2,但您不能以其他方式。实际上,HTTP / 2不再支持101状态码,因为HTTP / 2没有升级机制。

这种机制的共同用途

这里我们看一下Upgrade头部最常见的用例。

升级到HTTP/2连接

由于其广泛的支持,使用HTTP / 1.1启动连接的标准过程是,然后请求升级到HTTP / 2。这样,即使服务器不支持HTTP / 2,仍然可以正常工作。但是,只能升级到不安全(明文)HTTP / 2连接。这是通过使用目标协议名称来完成的h2c,该名称代表“HTTP / 2 Cleartext”。这也需要指定HTTP2-Settings标题字段。

GET / HTTP/1.1Host: destination.server.ext
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: base64EncodedSettings

这里base64EncodedSettings是一个HTTP / 2 "SETTINGS"帧的有效载荷,它已经被base64url编码,所有的尾随"="(等于)字符被删除,以便将其安全地包含在这个文本标题格式中。

所述base64url格式是不一样的标准Base64编码。这与标准的Base64差不多,但不完全相同。唯一的区别:为了确保所得到的字符串是在URL和文件名使用安全的字母表中的第62和第63个字符从改变"+""/""-"(负)和"_"(下划线),分别。

如果服务器由于某种原因无法切换到HTTP / 2,那么在正常处理请求后,它将回复标准的HTTP / 1回复。因此,如果请求是获取事实上存在的网页,那么您将"HTTP/1.1 200 OK"在网页的其余部分之后获得标准响应。如果服务器能够切换到HTTP / 2,HTTP/1.1 101 Switching Protocols"则会发送一个“ 响应” ,如下所示:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c[standard HTTP/2 server connection preface, etc.]

在HTTP / 1.1头部和指示头部结尾的空白行之后,服务器将立即包含服务器连接前言,从一个SETTINGS帧开始。

升级到WebSocket连接

到目前为止,升级HTTP连接最常见的用例是使用WebSocket,它通常通过升级HTTP或HTTPS连接来实现。请记住,如果您使用WebSocket API或任何执行WebSocket的库打开新连接,则大部分或所有这些都是为您完成的。例如,打开WebSocket连接非常简单:

webSocket = new WebSocket("ws://destination.server.ext", "optionalProtocol");

WebSocket()构造函数创建一个初始的HTTP / 1.1连接,然后处理握手和升级过程中的所有工作。

您也可以使用"wss://"URL方案打开安全的WebSocket连接。

如果您需要从头开始创建WebSocket连接,则必须自己处理握手过程。在创建初始HTTP / 1.1会话之后,您需要通过添加标准请求UpgradeConnection头部来请求升级,如下所示:

Connection: Upgrade
Upgrade: websocket

WebSocket-特定的头文件

WebSocket升级过程涉及以下头文件。除了头文件UpgradeConnection头文件,其余的文件通常都是可选的,或者在浏览器和服务器互相通话时为您处理。

Sec-WebSocket-Extensions

指定要求服务器使用的一个或多个协议级WebSocket扩展。Sec-WebSocket-Extension允许在请求中使用多个头部; 结果与您在一个这样的标题中包含所有列出的扩展名相同。

Sec-WebSocket-Extensions: extensions

extensions用逗号分隔的请求(或同意支持)的扩展名列表。这些应该从IANA WebSocket扩展名注册表中选择。带参数的扩展使用分号描述。

例如:

Sec-WebSocket-Extensions: superspeed, colormode; depth=16

Sec-WebSocket-Key

向服务器提供信息,以确认客户端有权请求升级到WebSocket。当不安全(HTTP)客户希望升级时,可以使用此头文件,以提供一定程度的防范滥用保护。使用WebSocket规范中定义的算法计算密钥的值,因此不提供安全性。相反,它有助于防止非WebSocket客户端无意中或通过滥用请求WebSocket连接。从本质上说,这个关键只是确认“是的,我真的打算打开一个WebSocket连接。”

这个标题是由选择使用它的客户端自动添加的; 它不能使用该XMLHttpRequest.setRequestHeader()方法添加。

Sec-WebSocket-Key: key

key此请求升级的关键。如果客户希望这样做,则客户端会添加该服务器,并且服务器会在响应中包含自己的密钥,客户端会在向您提供升级响应之前验证该密钥。

服务器的响应Sec-WebSocket-Accept头将有一个基于指定的值计算出来的值key

Sec-WebSocket-Protocol

Sec-WebSocket-Protocol头指定要使用,按优先顺序的一个或多个的WebSocket协议。服务器支持的第一个服务器将被选中,并由服务器在Sec-WebSocket-Protocol响应中包含的标题中返回。您也可以在标题中多次使用它,结果与在单个头中使用逗号分隔的子协议标识符列表相同。

Sec-WebSocket-Protocol: subprotocols

subprotocols按照优先顺序,按逗号分隔的子协议名称列表。子协议可以从IANA WebSocket子协议名称注册中选择,也可以是客户和服务器共同理解的定制名称。

Sec-WebSocket-Version

请求标题

指定客户端希望使用的WebSocket协议版本,以便服务器可以确认该版本是否受支持。

Sec-WebSocket-Version: version

version客户端希望在与服务器通信时使用的WebSocket协议版本。此号码应为IANA WebSocket版本号注册表中列出的最新版本。WebSocket协议的最新最终版本是版本13。

响应标题

如果服务器无法使用指定版本的WebSocket协议进行通信,它将响应一个错误(如需要升级426),在其标题中包含一个包含Sec-WebSocket-Version受支持协议版本的逗号分隔列表的标题。如果服务器确实支持所请求的协议版本,Sec-WebSocket-Version则响应中不会包含标题。

Sec-WebSocket-Version: supportedVersions

supportedVersions服务器支持的WebSocket协议版本的逗号分隔列表。

仅响应头文件

服务器的响应可能包括这些。

Sec-WebSocket-Accept

在服务器愿意启动WebSocket连接时,在打开握手过程期间包含在服务器的响应消息中。它在repsonse头文件中只会出现一次。

Sec-WebSocket-Accept: hash

hash如果Sec-WebSocket-Key提供了头文件,则通过获取该密钥的值来计算此头文件的值,并将字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”连接到该字符串,并取该连接字符串的SHA-1散列值,结果在一个20字节的值。然后该值被base64编码以获得该属性的值。

客户端的启动通过TLS升级到HTTP

您也可以将HTTP / 1.1连接升级到TLS / 1.0。这样做的主要优点是可以避免在服务器上使用从“http://”到“https://”的URL重定向,并且可以在虚拟主机上轻松使用TLS。但是,这可能会导致代理服务器出现问题。

升级HTTP连接以使用TLS将Upgrade标记与标记一起使用"TLS/1.0"。如果交换机成功完成,原始请求(包括其中Upgrade)将按照正常完成,但在TLS连接上完成。

对TLS的请求可以选择性地或强制性地进行。

可选升级

要升级到TLS(也就是说,如果升级到TLS失败,允许连接继续以明文方式),只需按预期方式使用UpgradeConnection标题。例如,给出原始请求:

GET http://destination.server.ext/secretpage.html HTTP/1.1Host: destination.server.ext
Upgrade: TLS/1.0Connection: Upgrade

如果服务器支持TLS升级,或者无法在当时升级到TLS,则它会使用标准的HTTP / 1.1响应进行响应,例如:

HTTP/1.1 200 OK
Date: Thu, 17 Aug 2017 21:07:44 GMT
Server: Apache
Last-Modified: Thu, 17 Aug 2017 08:30:15 GMT
Content-Type: text/html; charset=utf-8Content-Length: 31374<html>  ...</html>

如果服务器确实支持TLS升级并希望允许升级,它将使用"101 Switching Protocols"响应代码进行响应,如下所示:

HTTP/1.1 101 Switching Protocols
Upgrade: TLS/1.0, HTTP/1.1

一旦TLS握手完成,原始请求将被正常响应。

强制升级

要请求强制升级到TLS(即升级失败并在升级失败时连接失败),您的第一个请求必须是一个OPTIONS请求,如下所示:

OPTIONS * HTTP/1.1Host: destination.server.ext
Upgrade: TLS/1.0Connection: Upgrade

如果升级到TLS成功,服务器将"101 Switching Protocols"按照上一节所述进行响应。如果升级失败,HTTP / 1.1连接将失败。

服务器的启动升级到TLS

这与客户端启动的升级大致相同,通过将Upgrade头添加到任何消息来请求可选的升级。然而,强制升级的工作方式稍有不同,因为它会通过回复收到的带有426状态码的消息来请求升级,如下所示:

HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.1, HTTP/1.1Connection: Upgrade<html>... Human-readable HTML page describing why the upgrade is required
    and what to do if this text is seen ...</html>

如果接收到"426 Upgrade Required"响应的客户端愿意且能够升级到TLS,则应该启动上面在客户端启动的升级到TLS的过程中所述的相同过程。

参考

  • WebSocket API

  • HTTP

  • 规格和RFC:

    • RFC 2616

    • RFC 6455

    • RFC 2817

    • RFC 7540

在MDN上编辑此页面

上一篇:下一篇: