Files
boost_beast/doc/6_4_server.qbk

145 lines
5.1 KiB
Plaintext
Raw Normal View History

2017-06-03 18:40:28 -07:00
[/
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:server Handshaking (Servers)]
A
[link beast.ref.websocket__stream `stream`]
automatically handles receiving and processing the HTTP response to the
handshake request. The call to handshake is successful if a HTTP response
is received with the 101 "Switching Protocols" status code. On failure,
an error is returned or an exception is thrown. Depending on the keep alive
setting, the connection may remain open for a subsequent handshake attempt.
Performing a handshake for an incoming websocket upgrade request operates
similarly. If the handshake fails, an error is returned or exception thrown:
```
...
ws.accept();
```
Successful WebSocket Upgrade responses generated by the implementation will
typically look like this:
[table Decorated WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: Beast/40
```
][
The Sec-WebSocket-Accept field value is generated from the
request in a fashion specified by the WebSocket protocol.
]]]
[heading Decorators]
If the caller wishes to add or modify fields, the member functions
[link beast.ref.websocket__stream.accept_ex `accept_ex`] and
[link beast.ref.websocket__stream.async_accept_ex `async_accept_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 the Server
field on the response:
```
ws.accept_ex(
[](websocket::response_type& res)
{
res.fields.insert("Server", "AcmeServer");
});
```
The HTTP Upgrade response produced by the previous call will look thusly:
[table Decorated WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: AcmeServer
```
][
When the Upgrade request fails, the implementation will still invoke
the decorator to modify the response. In this case, the response
object will have a status code other than 101.
Undefined behavior results when the upgrade request is successful
and the decorator modifies the fields specific to perform the
WebSocket Upgrade , such as the Upgrade and Connection fields.
]]]
[heading Passing HTTP Requests]
When implementing an HTTP server that also supports WebSocket, the
server usually reads the HTTP request from the client. To detect when
the incoming HTTP request is a WebSocket Upgrade request, the function
[link beast.ref.websocket__is_upgrade `is_upgrade`] may be used.
Once the caller determines that the HTTP request is a WebSocket Upgrade,
additional overloads of
[link beast.ref.websocket__stream.accept `accept`],
[link beast.ref.websocket__stream.accept_ex `accept_ex`],
[link beast.ref.websocket__stream.async_accept `async_accept`], and
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
are provided which receive the entire HTTP request header as an object
to perform the handshake. In this example, the request is first read
in using the HTTP algorithms, and then passed to a newly constructed
stream:
```
void handle_connection(boost::asio::ip::tcp::socket& sock)
{
flat_buffer buffer;
http::request<http::string_body> req;
http::read(sock, buffer, req);
if(websocket::is_upgrade(req))
{
websocket::stream<decltype(sock)> ws{std::move(sock)};
ws.accept(req);
}
}
```
[heading Buffered Handshakes]
Sometimes a server implementation wishes to read octets on the stream
in order to route the incoming request. For example, a server may read
the first 6 octets after accepting an incoming connection to determine
if a TLS protocol is being negotiated, and choose a suitable implementation
at run-time. In the case where the server wishes to accept the incoming
request as an HTTP WebSocket Upgrade request, additional overloads of
[link beast.ref.websocket__stream.accept `accept`],
[link beast.ref.websocket__stream.accept_ex `accept_ex`],
[link beast.ref.websocket__stream.async_accept `async_accept`], and
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
are provided which receive the additional buffered octects and consume
them as part of the handshake.
In this example, the server reads the initial HTTP message into the
specified dynamic buffer as an octet sequence in the buffer's output
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
```
void do_accept(boost::asio::ip::tcp::socket& sock)
{
boost::asio::streambuf sb;
boost::asio::read_until(sock, sb, "\r\n\r\n");
...
websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.accept(sb.data());
...
}
```
[endsect]