forked from boostorg/beast
110 lines
3.6 KiB
Plaintext
110 lines
3.6 KiB
Plaintext
|
|
[/
|
||
|
|
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||
|
|
|
||
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
|
]
|
||
|
|
|
||
|
|
[section:client Handshaking (Clients)]
|
||
|
|
|
||
|
|
A WebSocket session begins when a client sends the HTTP
|
||
|
|
[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade]
|
||
|
|
request for
|
||
|
|
[@https://tools.ietf.org/html/rfc6455#section-1.3 websocket],
|
||
|
|
and the server sends an appropriate HTTP response indicating that
|
||
|
|
the request was accepted and that the connection has been upgraded.
|
||
|
|
The HTTP Upgrade request must include the
|
||
|
|
[@https://tools.ietf.org/html/rfc7230#section-5.4 Host]
|
||
|
|
field, and the
|
||
|
|
[@https://tools.ietf.org/html/rfc7230#section-5.3 target]
|
||
|
|
of the resource to request. The stream member functions
|
||
|
|
[link beast.ref.websocket__stream.handshake.overload1 `handshake`] and
|
||
|
|
[link beast.ref.websocket__stream.async_handshake.overload1 `async_handshake`]
|
||
|
|
are used to send the request with the required host and target strings.
|
||
|
|
```
|
||
|
|
...
|
||
|
|
ws.set_option(websocket::keep_alive(true));
|
||
|
|
ws.handshake("localhost", "/");
|
||
|
|
```
|
||
|
|
|
||
|
|
The implementation will create and send an HTTP request that typically
|
||
|
|
looks like this:
|
||
|
|
|
||
|
|
[table WebSocket Upgrade HTTP Request
|
||
|
|
[[Serialized Octets][Description]]
|
||
|
|
[[
|
||
|
|
```
|
||
|
|
GET / HTTP/1.1
|
||
|
|
Host: localhost
|
||
|
|
Upgrade: websocket
|
||
|
|
Connection: upgrade
|
||
|
|
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
||
|
|
Sec-WebSocket-Version: 13
|
||
|
|
User-Agent: Beast
|
||
|
|
```
|
||
|
|
][
|
||
|
|
The host and target parameters become part of the Host field
|
||
|
|
and request-target in the resulting HTTP request. The key is
|
||
|
|
generated by the implementation. Callers may add fields or
|
||
|
|
modify fields by providing a ['decorator], described below.
|
||
|
|
]]]
|
||
|
|
|
||
|
|
[heading Decorators]
|
||
|
|
|
||
|
|
If the caller wishes to add or modify fields, the member functions
|
||
|
|
[link beast.ref.websocket__stream.handshake_ex `handshake_ex`] and
|
||
|
|
[link beast.ref.websocket__stream.async_handshake_ex `async_handshake_ex`]
|
||
|
|
are provided which allow an additional function object, called a
|
||
|
|
['decorator], to be passed. The decorator is invoked to modify
|
||
|
|
the HTTP Upgrade request as needed. This example sets a subprotocol
|
||
|
|
on the request:
|
||
|
|
```
|
||
|
|
void decorate(websocket::request_type& req)
|
||
|
|
{
|
||
|
|
req.fields.insert("Sec-WebSocket-Protocol", "xmpp;ws-chat");
|
||
|
|
}
|
||
|
|
...
|
||
|
|
ws.handshake_ex("localhost", "/", &decorate);
|
||
|
|
|
||
|
|
```
|
||
|
|
|
||
|
|
The HTTP Upgrade request produced by the previous call will look thusly:
|
||
|
|
|
||
|
|
[table Decorated WebSocket Upgrade HTTP Request
|
||
|
|
[[Serialized Octets][Description]]
|
||
|
|
[[
|
||
|
|
```
|
||
|
|
GET / HTTP/1.1
|
||
|
|
Host: localhost
|
||
|
|
Upgrade: websocket
|
||
|
|
Connection: upgrade
|
||
|
|
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
||
|
|
Sec-WebSocket-Version: 13
|
||
|
|
Sec-WebSocket-Protocol: xmpp;ws-chat
|
||
|
|
User-Agent: Beast
|
||
|
|
```
|
||
|
|
][
|
||
|
|
Undefined behavior results if the decorator modifies the fields
|
||
|
|
specific to perform the WebSocket Upgrade , such as the Upgrade
|
||
|
|
and Connection fields.
|
||
|
|
]]]
|
||
|
|
|
||
|
|
[heading Filtering]
|
||
|
|
|
||
|
|
When a client receives an HTTP Upgrade response from the server indicating
|
||
|
|
a successful upgrade, the caller may wish to perform additional validation
|
||
|
|
on the received HTTP response message. For example, to check that the
|
||
|
|
response to a basic authentication challenge is valid. To achieve this,
|
||
|
|
overloads of the handshake member function allow the caller to store the
|
||
|
|
received HTTP message in an output reference argument as
|
||
|
|
[link beast.ref.websocket__response_type `response_type`]
|
||
|
|
as follows:
|
||
|
|
```
|
||
|
|
websocket::response_type res;
|
||
|
|
ws.handshake(res, "localhost", "/");
|
||
|
|
if(! res.fields.exists("Sec-WebSocket-Protocol"))
|
||
|
|
throw std::invalid_argument("missing subprotocols");
|
||
|
|
```
|
||
|
|
|
||
|
|
[endsect]
|