• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Handshaking</title>
5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Beast">
8<link rel="up" href="../using_websocket.html" title="WebSocket">
9<link rel="prev" href="establishing_connections.html" title="Connecting">
10<link rel="next" href="decorator.html" title="Decorator">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15<td align="center"><a href="../../../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="establishing_connections.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_websocket.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="decorator.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h3 class="title">
27<a name="beast.using_websocket.handshaking"></a><a class="link" href="handshaking.html" title="Handshaking">Handshaking</a>
28</h3></div></div></div>
29<h5>
30<a name="beast.using_websocket.handshaking.h0"></a>
31        <span class="phrase"><a name="beast.using_websocket.handshaking.client_role"></a></span><a class="link" href="handshaking.html#beast.using_websocket.handshaking.client_role">Client
32        Role</a>
33      </h5>
34<p>
35        A WebSocket session begins when a client sends the HTTP/1.1 <a href="https://tools.ietf.org/html/rfc7230#section-6.7" target="_top">Upgrade</a>
36        request for <a href="https://tools.ietf.org/html/rfc6455#section-1.3" target="_top">WebSocket</a>
37        on an established connection, and the server sends an appropriate response
38        indicating that the request was accepted and that the connection has been
39        upgraded. The Upgrade request must include the <a href="https://tools.ietf.org/html/rfc7230#section-5.4" target="_top">Host</a>
40        field, and the <a href="https://tools.ietf.org/html/rfc7230#section-5.3" target="_top">target</a>
41        of the resource to request. A typical HTTP Upgrade request created and sent
42        by the implementation will look like this:
43      </p>
44<div class="table">
45<a name="beast.using_websocket.handshaking.websocket_http_upgrade_request"></a><p class="title"><b>Table 1.30. WebSocket HTTP Upgrade Request</b></p>
46<div class="table-contents"><table class="table" summary="WebSocket HTTP Upgrade Request">
47<colgroup>
48<col>
49<col>
50</colgroup>
51<thead><tr>
52<th>
53                <p>
54                  Wire Format
55                </p>
56              </th>
57<th>
58                <p>
59                  Description
60                </p>
61              </th>
62</tr></thead>
63<tbody><tr>
64<td>
65<pre class="programlisting"><span class="identifier">GET</span> <span class="special">/</span> <span class="identifier">HTTP</span><span class="special">/</span><span class="number">1.1</span>
66<span class="identifier">Host</span><span class="special">:</span> <span class="identifier">www</span><span class="special">.</span><span class="identifier">example</span><span class="special">.</span><span class="identifier">com</span>
67<span class="identifier">Upgrade</span><span class="special">:</span> <span class="identifier">websocket</span>
68<span class="identifier">Connection</span><span class="special">:</span> <span class="identifier">upgrade</span>
69<span class="identifier">Sec</span><span class="special">-</span><span class="identifier">WebSocket</span><span class="special">-</span><span class="identifier">Key</span><span class="special">:</span> <span class="number">2</span><span class="identifier">pGeTR0DsE4dfZs2pH</span><span class="special">+</span><span class="number">8</span><span class="identifier">MA</span><span class="special">==</span>
70<span class="identifier">Sec</span><span class="special">-</span><span class="identifier">WebSocket</span><span class="special">-</span><span class="identifier">Version</span><span class="special">:</span> <span class="number">13</span>
71<span class="identifier">User</span><span class="special">-</span><span class="identifier">Agent</span><span class="special">:</span> <span class="identifier">Boost</span><span class="special">.</span><span class="identifier">Beast</span><span class="special">/</span><span class="number">216</span>
72</pre>
73              </td>
74<td>
75                <p>
76                  The host and target parameters become part of the Host field and
77                  request-target in the resulting HTTP request. The key is generated
78                  by the implementation. Callers who wish to add, modify, or inspect
79                  fields may set the <span class="emphasis"><em>decorator</em></span> option on the
80                  stream (described later).
81                </p>
82              </td>
83</tr></tbody>
84</table></div>
85</div>
86<br class="table-break"><p>
87        The <a class="link" href="../ref/boost__beast__websocket__stream.html" title="websocket::stream"><code class="computeroutput"><span class="identifier">websocket</span><span class="special">::</span><span class="identifier">stream</span></code></a> member functions <a class="link" href="../ref/boost__beast__websocket__stream/handshake.html" title="websocket::stream::handshake"><code class="computeroutput"><span class="identifier">handshake</span></code></a> and <a class="link" href="../ref/boost__beast__websocket__stream/async_handshake.html" title="websocket::stream::async_handshake"><code class="computeroutput"><span class="identifier">async_handshake</span></code></a> are used to send
88        the request with the required host and target strings. This code connects
89        to the IP address returned from a hostname lookup, then performs the WebSocket
90        handshake in the client role.
91      </p>
92<pre class="programlisting"><span class="identifier">stream</span><span class="special">&lt;</span><span class="identifier">tcp_stream</span><span class="special">&gt;</span> <span class="identifier">ws</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">);</span>
93<span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">resolver</span> <span class="identifier">resolver</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">);</span>
94<span class="identifier">get_lowest_layer</span><span class="special">(</span><span class="identifier">ws</span><span class="special">).</span><span class="identifier">connect</span><span class="special">(</span><span class="identifier">resolver</span><span class="special">.</span><span class="identifier">resolve</span><span class="special">(</span><span class="string">"www.example.com"</span><span class="special">,</span> <span class="string">"ws"</span><span class="special">));</span>
95
96<span class="comment">// Do the websocket handshake in the client role, on the connected stream.</span>
97<span class="comment">// The implementation only uses the Host parameter to set the HTTP "Host" field,</span>
98<span class="comment">// it does not perform any DNS lookup. That must be done first, as shown above.</span>
99
100<span class="identifier">ws</span><span class="special">.</span><span class="identifier">handshake</span><span class="special">(</span>
101    <span class="string">"www.example.com"</span><span class="special">,</span>  <span class="comment">// The Host field</span>
102    <span class="string">"/"</span>                 <span class="comment">// The request-target</span>
103<span class="special">);</span>
104</pre>
105<p>
106        When a client receives an HTTP Upgrade response from the server indicating
107        a successful upgrade, the caller may wish to perform additional validation
108        on the received HTTP response message. For example, to check that the response
109        to a basic authentication challenge is valid. To achieve this, overloads
110        of the handshake member function allow the caller to store the received HTTP
111        message in an output reference argument of type <a class="link" href="../ref/boost__beast__websocket__response_type.html" title="websocket::response_type"><code class="computeroutput"><span class="identifier">response_type</span></code></a> as follows:
112      </p>
113<pre class="programlisting"><span class="comment">// This variable will receive the HTTP response from the server</span>
114<span class="identifier">response_type</span> <span class="identifier">res</span><span class="special">;</span>
115
116<span class="comment">// Perform the websocket handshake in the client role.</span>
117<span class="comment">// On success, `res` will hold the complete HTTP response received.</span>
118
119<span class="identifier">ws</span><span class="special">.</span><span class="identifier">handshake</span><span class="special">(</span>
120    <span class="identifier">res</span><span class="special">,</span>                <span class="comment">// Receives the HTTP response</span>
121    <span class="string">"www.example.com"</span><span class="special">,</span>  <span class="comment">// The Host field</span>
122    <span class="string">"/"</span>                 <span class="comment">// The request-target</span>
123<span class="special">);</span>
124</pre>
125<h5>
126<a name="beast.using_websocket.handshaking.h1"></a>
127        <span class="phrase"><a name="beast.using_websocket.handshaking.server_role"></a></span><a class="link" href="handshaking.html#beast.using_websocket.handshaking.server_role">Server
128        Role</a>
129      </h5>
130<p>
131        For servers accepting incoming connections, the <a class="link" href="../ref/boost__beast__websocket__stream.html" title="websocket::stream"><code class="computeroutput"><span class="identifier">websocket</span><span class="special">::</span><span class="identifier">stream</span></code></a> can read the incoming upgrade
132        request and automatically reply. If the handshake meets the requirements,
133        the stream sends back the upgrade response with a <a href="https://tools.ietf.org/html/rfc6455#section-4.2.2" target="_top"><span class="emphasis"><em>101
134        Switching Protocols</em></span></a> status code. If the handshake does
135        not meet the requirements, or falls outside the range of allowed parameters
136        specified by stream options set previously by the caller, the stream sends
137        back an HTTP response with a status code indicating an error. Depending on
138        the keep alive setting, the connection may remain open for a subsequent handshake
139        attempt. A typical HTTP Upgrade response created and sent by the implementation
140        upon receiving an upgrade request handshake will look like this:
141      </p>
142<div class="table">
143<a name="beast.using_websocket.handshaking.websocket_upgrade_http_response"></a><p class="title"><b>Table 1.31. WebSocket Upgrade HTTP Response</b></p>
144<div class="table-contents"><table class="table" summary="WebSocket Upgrade HTTP Response">
145<colgroup>
146<col>
147<col>
148</colgroup>
149<thead><tr>
150<th>
151                <p>
152                  Wire Format
153                </p>
154              </th>
155<th>
156                <p>
157                  Description
158                </p>
159              </th>
160</tr></thead>
161<tbody><tr>
162<td>
163<pre class="programlisting"><span class="identifier">HTTP</span><span class="special">/</span><span class="number">1.1</span> <span class="number">101</span> <span class="identifier">Switching</span> <span class="identifier">Protocols</span>
164<span class="identifier">Upgrade</span><span class="special">:</span> <span class="identifier">websocket</span>
165<span class="identifier">Connection</span><span class="special">:</span> <span class="identifier">upgrade</span>
166<span class="identifier">Sec</span><span class="special">-</span><span class="identifier">WebSocket</span><span class="special">-</span><span class="identifier">Accept</span><span class="special">:</span> <span class="identifier">s3pPLMBiTxaQ9kYGzzhZRbK</span><span class="special">+</span><span class="identifier">xOo</span><span class="special">=</span>
167<span class="identifier">Server</span><span class="special">:</span> <span class="identifier">Boost</span><span class="special">.</span><span class="identifier">Beast</span>
168</pre>
169              </td>
170<td>
171                <p>
172                  The <a href="https://tools.ietf.org/html/rfc6455#section-11.3.3" target="_top"><span class="emphasis"><em>Sec-WebSocket-Accept</em></span></a>
173                  field value is generated from the request in a fashion specified
174                  by the WebSocket protocol.
175                </p>
176              </td>
177</tr></tbody>
178</table></div>
179</div>
180<br class="table-break"><p>
181        The <a class="link" href="../ref/boost__beast__websocket__stream.html" title="websocket::stream"><code class="computeroutput"><span class="identifier">stream</span></code></a> member functions <a class="link" href="../ref/boost__beast__websocket__stream/accept.html" title="websocket::stream::accept"><code class="computeroutput"><span class="identifier">accept</span></code></a> and <a class="link" href="../ref/boost__beast__websocket__stream/async_accept.html" title="websocket::stream::async_accept"><code class="computeroutput"><span class="identifier">async_accept</span></code></a> are used to read the
182        WebSocket HTTP Upgrade request handshake from a stream already connected
183        to an incoming peer, and then send the WebSocket HTTP Upgrade response, as
184        shown:
185      </p>
186<pre class="programlisting"><span class="comment">// Perform the websocket handshake in the server role.</span>
187<span class="comment">// The stream must already be connected to the peer.</span>
188
189<span class="identifier">ws</span><span class="special">.</span><span class="identifier">accept</span><span class="special">();</span>
190</pre>
191<h5>
192<a name="beast.using_websocket.handshaking.h2"></a>
193        <span class="phrase"><a name="beast.using_websocket.handshaking.handshake_buffering"></a></span><a class="link" href="handshaking.html#beast.using_websocket.handshaking.handshake_buffering">Handshake
194        Buffering</a>
195      </h5>
196<p>
197        It is possible for servers to read data from the stream and decide later
198        that the buffered bytes should be interpreted as a WebSocket upgrade request.
199        To address this usage, overloads of <a class="link" href="../ref/boost__beast__websocket__stream/accept.html" title="websocket::stream::accept"><code class="computeroutput"><span class="identifier">accept</span></code></a> and <a class="link" href="../ref/boost__beast__websocket__stream/async_accept.html" title="websocket::stream::async_accept"><code class="computeroutput"><span class="identifier">async_accept</span></code></a> which accept an additional
200        buffer sequence parameter are provided.
201      </p>
202<p>
203        In this example, the server reads the initial HTTP request header into a
204        dynamic buffer, then later uses the buffered data to attempt a websocket
205        upgrade.
206      </p>
207<pre class="programlisting"><span class="comment">// This buffer will hold the HTTP request as raw characters</span>
208<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s</span><span class="special">;</span>
209
210<span class="comment">// Read into our buffer until we reach the end of the HTTP request.</span>
211<span class="comment">// No parsing takes place here, we are just accumulating data.</span>
212
213<span class="identifier">net</span><span class="special">::</span><span class="identifier">read_until</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">dynamic_buffer</span><span class="special">(</span><span class="identifier">s</span><span class="special">),</span> <span class="string">"\r\n\r\n"</span><span class="special">);</span>
214
215<span class="comment">// Now accept the connection, using the buffered data.</span>
216<span class="identifier">ws</span><span class="special">.</span><span class="identifier">accept</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">s</span><span class="special">));</span>
217</pre>
218<h5>
219<a name="beast.using_websocket.handshaking.h3"></a>
220        <span class="phrase"><a name="beast.using_websocket.handshaking.inspecting_http_requests"></a></span><a class="link" href="handshaking.html#beast.using_websocket.handshaking.inspecting_http_requests">Inspecting
221        HTTP Requests</a>
222      </h5>
223<p>
224        When implementing an HTTP server that also supports WebSocket, the server
225        usually reads the HTTP request from the client. To detect when the incoming
226        HTTP request is a WebSocket Upgrade request, the function <a class="link" href="../ref/boost__beast__websocket__is_upgrade.html" title="websocket::is_upgrade"><code class="computeroutput"><span class="identifier">is_upgrade</span></code></a> may be used.
227      </p>
228<p>
229        Once the caller determines that the HTTP request is a WebSocket Upgrade,
230        additional overloads of <a class="link" href="../ref/boost__beast__websocket__stream/accept.html" title="websocket::stream::accept"><code class="computeroutput"><span class="identifier">accept</span></code></a> and <a class="link" href="../ref/boost__beast__websocket__stream/async_accept.html" title="websocket::stream::async_accept"><code class="computeroutput"><span class="identifier">async_accept</span></code></a> are provided which
231        receive the entire HTTP request header as an object to perform the handshake.
232        By reading the request manually, the program can handle normal HTTP requests
233        as well as upgrades. The program may also enforce policies based on the HTTP
234        fields, such as Basic Authentication. In this example, the request is first
235        read in using the HTTP algorithms, and then passed to a newly constructed
236        stream:
237      </p>
238<pre class="programlisting"><span class="comment">// This buffer is required for reading HTTP messages</span>
239<span class="identifier">flat_buffer</span> <span class="identifier">buffer</span><span class="special">;</span>
240
241<span class="comment">// Read the HTTP request ourselves</span>
242<span class="identifier">http</span><span class="special">::</span><span class="identifier">request</span><span class="special">&lt;</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">&gt;</span> <span class="identifier">req</span><span class="special">;</span>
243<span class="identifier">http</span><span class="special">::</span><span class="identifier">read</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">req</span><span class="special">);</span>
244
245<span class="comment">// See if its a WebSocket upgrade request</span>
246<span class="keyword">if</span><span class="special">(</span><span class="identifier">websocket</span><span class="special">::</span><span class="identifier">is_upgrade</span><span class="special">(</span><span class="identifier">req</span><span class="special">))</span>
247<span class="special">{</span>
248    <span class="comment">// Construct the stream, transferring ownership of the socket</span>
249    <span class="identifier">stream</span><span class="special">&lt;</span><span class="identifier">tcp_stream</span><span class="special">&gt;</span> <span class="identifier">ws</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">sock</span><span class="special">));</span>
250
251    <span class="comment">// Clients SHOULD NOT begin sending WebSocket</span>
252    <span class="comment">// frames until the server has provided a response.</span>
253    <span class="identifier">BOOST_ASSERT</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span>
254
255    <span class="comment">// Accept the upgrade request</span>
256    <span class="identifier">ws</span><span class="special">.</span><span class="identifier">accept</span><span class="special">(</span><span class="identifier">req</span><span class="special">);</span>
257<span class="special">}</span>
258<span class="keyword">else</span>
259<span class="special">{</span>
260    <span class="comment">// Its not a WebSocket upgrade, so</span>
261    <span class="comment">// handle it like a normal HTTP request.</span>
262<span class="special">}</span>
263</pre>
264<h5>
265<a name="beast.using_websocket.handshaking.h4"></a>
266        <span class="phrase"><a name="beast.using_websocket.handshaking.subprotocols"></a></span><a class="link" href="handshaking.html#beast.using_websocket.handshaking.subprotocols">Subprotocols</a>
267      </h5>
268<p>
269        The WebSocket protocol understands the concept of subprotocols. If the client
270        is requesting one of a set of subprotocols it will set the header <a href="https://tools.ietf.org/html/rfc6455#section-11.3.4" target="_top">Sec-WebSocket-Protocol</a>
271        in the initial WebSocket Upgrade HTTP request. It is up to the server to
272        parse the header and select one of the protocols to accept. The server indicates
273        the selected protocol by setting the <a href="https://tools.ietf.org/html/rfc6455#section-11.3.4" target="_top">Sec-WebSocket-Protocol</a>
274        header in the accept header.
275      </p>
276<p>
277        This is accomplished with a <a class="link" href="../ref/boost__beast__websocket__stream_base__decorator.html" title="websocket::stream_base::decorator"><code class="computeroutput"><span class="identifier">decorator</span></code></a>.
278      </p>
279<p>
280        The code that follows demonstrates how a server reads an HTTP request, identifies
281        it as a WebSocket Upgrade, and then checks for a preferred matching subprotocol
282        before performing the WebSocket handshake:
283      </p>
284<pre class="programlisting"><span class="comment">// a function to select the most preferred protocol from a comma-separated list</span>
285<span class="keyword">auto</span> <span class="identifier">select_protocol</span> <span class="special">=</span> <span class="special">[](</span><span class="identifier">string_view</span> <span class="identifier">offered_tokens</span><span class="special">)</span> <span class="special">-&gt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span>
286<span class="special">{</span>
287    <span class="comment">// tokenize the Sec-Websocket-Protocol header offered by the client</span>
288    <span class="identifier">http</span><span class="special">::</span><span class="identifier">token_list</span> <span class="identifier">offered</span><span class="special">(</span> <span class="identifier">offered_tokens</span> <span class="special">);</span>
289
290    <span class="comment">// an array of protocols supported by this server</span>
291    <span class="comment">// in descending order of preference</span>
292    <span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="identifier">string_view</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span>
293        <span class="identifier">supported</span> <span class="special">=</span> <span class="special">{</span>
294        <span class="string">"v3.my.chat"</span><span class="special">,</span>
295        <span class="string">"v2.my.chat"</span><span class="special">,</span>
296        <span class="string">"v1.my.chat"</span>
297    <span class="special">};</span>
298
299    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span><span class="special">;</span>
300
301    <span class="keyword">for</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">proto</span> <span class="special">:</span> <span class="identifier">supported</span><span class="special">)</span>
302    <span class="special">{</span>
303        <span class="keyword">auto</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">find</span><span class="special">(</span><span class="identifier">offered</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">offered</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">proto</span><span class="special">);</span>
304        <span class="keyword">if</span> <span class="special">(</span><span class="identifier">iter</span> <span class="special">!=</span> <span class="identifier">offered</span><span class="special">.</span><span class="identifier">end</span><span class="special">())</span>
305        <span class="special">{</span>
306            <span class="comment">// we found a supported protocol in the list offered by the client</span>
307            <span class="identifier">result</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">proto</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">proto</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
308            <span class="keyword">break</span><span class="special">;</span>
309        <span class="special">}</span>
310    <span class="special">}</span>
311
312    <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
313<span class="special">};</span>
314
315
316<span class="comment">// This buffer is required for reading HTTP messages</span>
317<span class="identifier">flat_buffer</span> <span class="identifier">buffer</span><span class="special">;</span>
318
319<span class="comment">// Read the HTTP request ourselves</span>
320<span class="identifier">http</span><span class="special">::</span><span class="identifier">request</span><span class="special">&lt;</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">&gt;</span> <span class="identifier">req</span><span class="special">;</span>
321<span class="identifier">http</span><span class="special">::</span><span class="identifier">read</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">req</span><span class="special">);</span>
322
323<span class="comment">// See if it's a WebSocket upgrade request</span>
324<span class="keyword">if</span><span class="special">(</span><span class="identifier">websocket</span><span class="special">::</span><span class="identifier">is_upgrade</span><span class="special">(</span><span class="identifier">req</span><span class="special">))</span>
325<span class="special">{</span>
326    <span class="comment">// we store the selected protocol in a std::string here because</span>
327    <span class="comment">// we intend to capture it in the decorator's lambda below</span>
328    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">protocol</span> <span class="special">=</span>
329        <span class="identifier">select_protocol</span><span class="special">(</span>
330            <span class="identifier">req</span><span class="special">[</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">sec_websocket_protocol</span><span class="special">]);</span>
331
332    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">protocol</span><span class="special">.</span><span class="identifier">empty</span><span class="special">())</span>
333    <span class="special">{</span>
334        <span class="comment">// none of our supported protocols were offered</span>
335        <span class="identifier">http</span><span class="special">::</span><span class="identifier">response</span><span class="special">&lt;</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">&gt;</span> <span class="identifier">res</span><span class="special">;</span>
336        <span class="identifier">res</span><span class="special">.</span><span class="identifier">result</span><span class="special">(</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">status</span><span class="special">::</span><span class="identifier">bad_request</span><span class="special">);</span>
337        <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">()</span> <span class="special">=</span> <span class="string">"No valid sub-protocol was offered."</span>
338                      <span class="string">" This server implements"</span>
339                      <span class="string">" v3.my.chat,"</span>
340                      <span class="string">" v2.my.chat"</span>
341                      <span class="string">" and v1.my.chat"</span><span class="special">;</span>
342        <span class="identifier">http</span><span class="special">::</span><span class="identifier">write</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">res</span><span class="special">);</span>
343    <span class="special">}</span>
344    <span class="keyword">else</span>
345    <span class="special">{</span>
346        <span class="comment">// Construct the stream, transferring ownership of the socket</span>
347        <span class="identifier">stream</span><span class="special">&lt;</span><span class="identifier">tcp_stream</span><span class="special">&gt;</span> <span class="identifier">ws</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">sock</span><span class="special">));</span>
348
349        <span class="identifier">ws</span><span class="special">.</span><span class="identifier">set_option</span><span class="special">(</span>
350            <span class="identifier">stream_base</span><span class="special">::</span><span class="identifier">decorator</span><span class="special">(</span>
351                <span class="special">[</span><span class="identifier">protocol</span><span class="special">](</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">response_header</span><span class="special">&lt;&gt;</span> <span class="special">&amp;</span><span class="identifier">hdr</span><span class="special">)</span> <span class="special">{</span>
352                    <span class="identifier">hdr</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span>
353                        <span class="identifier">http</span><span class="special">::</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">sec_websocket_protocol</span><span class="special">,</span>
354                        <span class="identifier">protocol</span><span class="special">);</span>
355                <span class="special">}));</span>
356
357        <span class="comment">// Accept the upgrade request</span>
358        <span class="identifier">ws</span><span class="special">.</span><span class="identifier">accept</span><span class="special">(</span><span class="identifier">req</span><span class="special">);</span>
359    <span class="special">}</span>
360<span class="special">}</span>
361<span class="keyword">else</span>
362<span class="special">{</span>
363    <span class="comment">// Its not a WebSocket upgrade, so</span>
364    <span class="comment">// handle it like a normal HTTP request.</span>
365<span class="special">}</span>
366</pre>
367</div>
368<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
369<td align="left"></td>
370<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie
371      Falco<p>
372        Distributed under the Boost Software License, Version 1.0. (See accompanying
373        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
374      </p>
375</div></td>
376</tr></table>
377<hr>
378<div class="spirit-nav">
379<a accesskey="p" href="establishing_connections.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_websocket.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="decorator.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
380</div>
381</body>
382</html>
383