1[/ 2 Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 Official repository: https://github.com/boostorg/beast 8] 9 10[section Handshaking] 11 12[/-----------------------------------------------------------------------------] 13 14[heading Client Role] 15 16A WebSocket session begins when a client sends the HTTP/1.1 17[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade] 18request for 19[@https://tools.ietf.org/html/rfc6455#section-1.3 WebSocket] 20on an established connection, and the server sends an appropriate response 21indicating that the request was accepted and that the connection has been 22upgraded. The Upgrade request must include the 23[@https://tools.ietf.org/html/rfc7230#section-5.4 Host] 24field, and the 25[@https://tools.ietf.org/html/rfc7230#section-5.3 target] 26of the resource to request. 27A typical HTTP Upgrade request created and sent by the implementation 28will look like this: 29 30[table WebSocket HTTP Upgrade Request 31[[Wire Format][Description]] 32[[ 33``` 34 GET / HTTP/1.1 35 Host: www.example.com 36 Upgrade: websocket 37 Connection: upgrade 38 Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA== 39 Sec-WebSocket-Version: 13 40 User-Agent: Boost.Beast/216 41``` 42][ 43 The host and target parameters become part of the Host field 44 and request-target in the resulting HTTP request. The key is 45 generated by the implementation. Callers who wish to add, 46 modify, or inspect fields may set the ['decorator] option 47 on the stream (described later). 48]]] 49 50The 51[link beast.ref.boost__beast__websocket__stream `websocket::stream`] 52member functions 53[link beast.ref.boost__beast__websocket__stream.handshake `handshake`] and 54[link beast.ref.boost__beast__websocket__stream.async_handshake `async_handshake`] 55are used to send the request with the required host and target strings. This 56code connects to the IP address returned from a hostname lookup, then performs 57the WebSocket handshake in the client role. 58 59[code_websocket_2_1] 60 61When a client receives an HTTP Upgrade response from the server indicating 62a successful upgrade, the caller may wish to perform additional validation 63on the received HTTP response message. For example, to check that the 64response to a basic authentication challenge is valid. To achieve this, 65overloads of the handshake member function allow the caller to store the 66received HTTP message in an output reference argument of type 67[link beast.ref.boost__beast__websocket__response_type `response_type`] 68as follows: 69 70[code_websocket_2_2] 71 72[/-----------------------------------------------------------------------------] 73 74[heading Server Role] 75 76For servers accepting incoming connections, the 77[link beast.ref.boost__beast__websocket__stream `websocket::stream`] 78can read the incoming upgrade request and automatically reply. If the handshake 79meets the requirements, the stream sends back the upgrade response with a 80[@https://tools.ietf.org/html/rfc6455#section-4.2.2 ['101 Switching Protocols]] 81status code. If the handshake does not meet the requirements, or falls outside 82the range of allowed parameters specified by stream options set previously by 83the caller, the stream sends back an HTTP response with a status code indicating 84an error. Depending on the keep alive setting, the connection may remain open 85for a subsequent handshake attempt. A typical HTTP Upgrade response created and 86sent by the implementation upon receiving an upgrade request handshake will 87look like this: 88 89[table WebSocket Upgrade HTTP Response 90[[Wire Format][Description]] 91[[ 92 ``` 93 HTTP/1.1 101 Switching Protocols 94 Upgrade: websocket 95 Connection: upgrade 96 Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 97 Server: Boost.Beast 98 ``` 99][ 100 The 101 [@https://tools.ietf.org/html/rfc6455#section-11.3.3 ['Sec-WebSocket-Accept]] 102 field value is generated from the request in a fashion specified by 103 the WebSocket protocol. 104]]] 105 106The 107[link beast.ref.boost__beast__websocket__stream `stream`] 108member functions 109[link beast.ref.boost__beast__websocket__stream.accept `accept`] and 110[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] 111are used to read the WebSocket HTTP Upgrade request handshake from a stream 112already connected to an incoming peer, and then send the WebSocket HTTP 113Upgrade response, as shown: 114 115[code_websocket_2_3] 116 117[heading Handshake Buffering] 118 119It is possible for servers to read data from the stream and decide later 120that the buffered bytes should be interpreted as a WebSocket upgrade 121request. To address this usage, overloads of 122[link beast.ref.boost__beast__websocket__stream.accept `accept`] and 123[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] 124which accept an additional buffer sequence parameter are provided. 125 126In this example, the server reads the initial HTTP request header into a 127dynamic buffer, then later uses the buffered data to attempt a websocket 128upgrade. 129 130[code_websocket_2_4] 131 132[heading Inspecting HTTP Requests] 133 134When implementing an HTTP server that also supports WebSocket, the 135server usually reads the HTTP request from the client. To detect when 136the incoming HTTP request is a WebSocket Upgrade request, the function 137[link beast.ref.boost__beast__websocket__is_upgrade `is_upgrade`] may be used. 138 139Once the caller determines that the HTTP request is a WebSocket Upgrade, 140additional overloads of 141[link beast.ref.boost__beast__websocket__stream.accept `accept`] and 142[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] 143are provided which receive the entire HTTP request header as an object 144to perform the handshake. By reading the request manually, the program 145can handle normal HTTP requests as well as upgrades. The program may 146also enforce policies based on the HTTP fields, such as Basic 147Authentication. In this example, the request is first read in 148using the HTTP algorithms, and then passed to a newly constructed 149stream: 150 151[code_websocket_2_5] 152 153[heading Subprotocols] 154 155The WebSocket protocol understands the concept of subprotocols. If the client 156is requesting one of a set of subprotocols it will set the header 157[@https://tools.ietf.org/html/rfc6455#section-11.3.4 Sec-WebSocket-Protocol] 158in the initial WebSocket Upgrade HTTP request. It is up to the server to 159parse the header and select one of the protocols to accept. The server 160indicates the selected protocol by setting the 161[@https://tools.ietf.org/html/rfc6455#section-11.3.4 Sec-WebSocket-Protocol] 162header in the accept header. 163 164This is accomplished with a 165[link beast.ref.boost__beast__websocket__stream_base__decorator `decorator`]. 166 167The code that follows demonstrates how a server reads an HTTP request, identifies it 168as a WebSocket Upgrade, and then checks for a preferred matching subprotocol before 169performing the WebSocket handshake: 170 171[code_websocket_2_6] 172 173 174[/-----------------------------------------------------------------------------] 175 176[endsect] 177