Mecanismo de actualización del protocolo

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

El protocolo HTTP posee un mecanismo especifico para permitir que una conexión de comunicación ya establecida, pueda actualizar su protocolo a un nuevo protocolo, incluso si es incompatible. Este documento muestra este mecanismo y presenta ejemplos de posibles escenarios en los que se puede usar. 

Este mecanismo, siempre es iniciado por el cliente (con la única excepción de que el servidor use: requerida actualización a TLS), y el servidor puede aceptar o rechazar el cambio al nuevo protocolo. Esto hace posible comenzar una conexión usando un protocolo de uso común, como puede ser HTTP/1.1, y posteriormente pedir un cambio de protocolo a HTTP/2.0 o incluso WebSockets.

Acuerdo de conexión (handshake)

Las actualizaciones del protocolo de comunicación son siempre iniciadas por el cliente; no hay un mecanismo establecido  para que el servidor pida un cambio de protocolo. Cuando el cliente desea una actualización a un nuevo protocolo, lo hace mandando una petición normal al servidor con cualquier método (GET, POST, etc.). La petición ha de configurarse de manera especial, para que incluya en ella, la petición de actualización del protocolo. 

En concreto, la petición ha de incluir las dos siguientes cabeceras:

Connection: Upgrade
La cabecera de conexión (Connection) ha de tener el valor "Upgrade" para señalar que se está pidiendo una actualización del protocolo.
Upgrade: protocols
La cabecera de actualización (Upgrade) indica los protocolos deseados, en orden de preferencia, separados por comas.

Puede que sean necesarias otras cabeceras, dependiendo del protocolo que se pida.; por ejemplo: las actualizaciones a WebSocket necesitan cabeceras adicionales para definir la configuración de la conexión, así como para detalles de la seguridad. Para más detalles, lea la sección: Upgrading to a WebSocket connection.

El servidor, puede negarse a la actualización en este caso, este simplemente ignora la cabecera de actualización ("Upgrade") y responde con un estado normal, ( "200 OK" si todo es correcto, o un  código 30x de estado si quiere hacer una redirección, o 40x ó 50x  si no puede responder con el recurso requerido) — o aceptar la actualización. En este caso, responde con un código "101 Switching Protocols"  con una cabecera Upgrade  que indica el protocolo elegido.

Right after sending the 101 status code, an eventual handshake for the new protocol happens, if the new protocol requires it, then the server sends the answer requested for the original request (the one that included the "Upgrade" header), following the new protocol rules.

El código de estado 101

The 101 status code is sent as a response to an request including the "Upgrade" header to signal that the recipient of the request is willing to upgrade to one of the desired protocols. If the "101 Switching Protocols" status code is returned, the header must also include the Connection and Upgrade headers to describe the chosen protocol. See the examples in Common uses for this mechanism to learn more about how this works.

While you can use the protocol upgrade mechanism to upgrade an HTTP/1.1 connection to HTTP/2, you can't go the other way. In fact, the 101 status code is no longer supported at all in HTTP/2, since HTTP/2 doesn't have an upgrade mechanism.

Usos normales para este mecanismo

Here we look at the most common use cases for the Upgrade header.

Upgrading to an HTTP/2 connection

It's standard procedure to start a connection using HTTP/1.1, due to its broad support, then request an upgrade to HTTP/2. This way, you have a functioning connection still even if HTTP/2 isn't supported by the server. However, you can only upgrade to an insecure (cleartext) HTTP/2 connection. This is done using the target protocol name h2c, which stands for "HTTP/2 Cleartext". This also requires the specification of the HTTP2-Settings header field.

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

Here, base64EncodedSettings is an HTTP/2 "SETTINGS" frame's payload which has been base64url encoded and all trailing "=" (equals) characters removed in order to safely include it in this textual header format.

The base64url format is not the same as standard Base64 encoding. This is almost but not quite the same as standard Base64. The only difference: in order to ensure that the resulting string is safe for use in both URLs and filenames, the 62nd and 63rd characters in its alphabet are changed from "+" and "/" to "-" (minus) and "_" (underscore), respectively.

If the server is unable to switch to HTTP/2 for any reason, it will reply with a standard HTTP/1 reply after handling the request as normal. So if the request was to fetch a web page which does in fact exist, you would get a standard "HTTP/1.1 200 OK" response with the web page following the remainder of the header. If the server is able to switch to HTTP/2, an "HTTP/1.1 101 Switching Protocols" response is sent, which will look like this:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[standard HTTP/2 server connection preface, etc.]

After the HTTP/1.1 header and the blank line that indicates the end of the header, the server will immediately include the server connection preface, starting with a SETTINGS frame.

Upgrading to a WebSocket connection

By far, the most common use case for upgrading an HTTP connection is to use WebSockets, which are always implemented by upgrading an HTTP or HTTPS connection. Keep in mind that if you're opening a new connection using the WebSocket API, or any library that does WebSockets, most or all of this is done for you. For example, opening a WebSocket connection is as simple as:

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

The WebSocket() constructor does all the work of creating an initial HTTP/1.1 connection then handling the handshaking and upgrade process for you.

You can also use the "wss://" URL scheme to open a secure WebSocket connection.

If you need to create a WebSocket connection from scratch, you'll have to handle the handshaking process yourself. After creating the initial HTTP/1.1 session, you need to request the upgrade by adding to a standard request the Upgrade and Connection headers, as follows:

Connection: Upgrade
Upgrade: websocket

WebSocket-specific headers

The following headers are involved in the WebSocket upgrade process. Other than the Upgrade and Connection headers, the rest are generally optional or handled for you by the browser and server when they're talking to each other.

Sec-WebSocket-Extensions

Specifies one or more protocol-level WebSocket extensions to ask the server to use. Using more than one Sec-WebSocket-Extension header in a request is permitted; the result is the same as if you included all of the listed extensions in one such header.

Sec-WebSocket-Extensions: extensions
extensions
A comma-separated list of extensions to request (or agree to support). These should be selected from the IANA WebSocket Extension Name Registry. Extensions which take parameters do so using semicolon delineation.

For example:

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

Sec-WebSocket-Key

Provides information to the server which is needed in order to confirm that the client is entitled to request an upgrade to WebSocket. This header can be used when insecure (HTTP) clients wish to upgrade, in order to offer some degree of protection against abuse. The value of the key is computed using an algorithm defined in the WebSocket specification, so this does not provide security. Instead, it helps to prevent non-WebSocket clients from inadvertently, or through misuse, requesting a WebSocket connection. In essence, then, this key simply confirms that "Yes, I really mean to open a WebSocket connection."

This header is automatically added by clients that choose to use it; it cannot be added using the XMLHttpRequest.setRequestHeader() method.

Sec-WebSocket-Key: key
key
The key for this request to upgrade. The client adds this if it wishes to do so, and the server will include in the response a key of its own, which the client will validate before delivering the upgrade reponse to you.

The server's response's Sec-WebSocket-Accept header will have a value computed based upon the specified key.

Sec-WebSocket-Protocol

The Sec-WebSocket-Protocol header specifies one or more WebSocket protocols that you wish to use, in order of preference. The first one that is supported by the server will be selected and returned by the server in a Sec-WebSocket-Protocol header included in the response. You can use this more than once in the header, as well; the result is the same as if you used a comma-delineated list of subprotocol identifiers in a single header.

Sec-WebSocket-Protocol: subprotocols
subprotocols
A comma-separated list of subprotocol names, in the order of preference. The subprotocols may be selected from the IANA WebSocket Subprotocol Name Registry or may be a custom name jointly understood by the client and the server.

Sec-WebSocket-Version

Request header

Specifies the WebSocket protocol version the client wishes to use, so the server can confirm whether or not that version is supported on its end.

Sec-WebSocket-Version: version
version
The WebSocket protocol version the client wishes to use when communicating with the server. This number should be the most recent version possible listed in the IANA WebSocket Version Number Registry. The most recent final version of the WebSocket protocol is version 13.
Response header

If the server can't communicate using the specified version of the WebSocket protocol, it will respond with an error (such as 426 Upgrade Required) that includes in its headers a Sec-WebSocket-Version header with a comma-separated list of the supported protocol versions. If the server does support the requested protocol version, no Sec-WebSocket-Version header is included in the response.

Sec-WebSocket-Version: supportedVersions
supportedVersions
A comma-delineated list of the WebSocket protocol versions supported by the server.

Response-only headers

The response from the server may include these.

Sec-WebSocket-Accept

Included in the response message from the server during the opening handshake process when the server is willing to initiate a WebSocket connection. It will appear no more than once in the repsonse headers.

Sec-WebSocket-Accept: hash
hash
If a Sec-WebSocket-Key header was provided, the value of this header is computed by taking the value of the key, concatenating the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" to it, taking the SHA-1 hash of that concatenated string, resulting in a 20-byte value. That value is then base64 encoded to obtain the value of this property.

Client-initiated upgrade to HTTP over TLS

You can also upgrade an HTTP/1.1 connection to TLS/1.0. The main advantages to this are that you can avoid using URL redirection from "http://" to "https://" on the server and you can easily use TLS on virtual hosts. This may, however, introduce problems with proxy servers.

Upgrading an HTTP connection to use TLS uses the Upgrade header with the token "TLS/1.0". If the switch is made successfully, the original request (which included Upgrade) is completed as normal, but on the TLS connection.

The request to TLS can be made either optionally or mandatorily.

Optional upgrade

To upgrade to TLS optionally (that is, allowing the connection to continue in cleartext if the upgrade to TLS fails), you simply use the Upgrade and Connection headers as expected. For example, given the original request:

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

If the server does not support TLS upgrade, or is unable to upgrade to TLS at the time, it responds with a standard HTTP/1.1 response, such as:

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-8
Content-Length: 31374

<html>
  ...
</html>

If the server does support TLS upgrade and wishes to permit the upgrade, it responds with the "101 Switching Protocols" response code, like this:

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

Once the TLS handshake is complete, the original request will be responded to as normal.

Mandatory upgrade

To request a mandatory upgrade to TLS—that is, to upgrade and fail the connection if the upgrade is not successful—your first request must be an OPTIONS request, like this:

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

If the upgrade to TLS succeeds, the server will respond with "101 Switching Protocols" as described in the previous section. If the upgrade fails, the HTTP/1.1 connection will fail.

Server-initiated upgrade to TLS

This works roughly the same way as a client-initiated upgrade; an optional upgrade is requested by adding the Upgrade header to any message. A mandatory upgrade, though, works slightly differently, in that it requests the upgrade by replying to a message it receives with the 426 status code, like this:

HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.1, HTTP/1.1
Connection: Upgrade

<html>
... Human-readable HTML page describing why the upgrade is required
    and what to do if this text is seen ...
</html>

If the client receiving the "426 Upgrade Required" response is willing and able to upgrade to TLS, it should then start the same process covered above under Client-initiated upgrade to TLS.

References

Etiquetas y colaboradores del documento

 Colaboradores en esta página: Sergio_Gonzalez_Collado
 Última actualización por: Sergio_Gonzalez_Collado,