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"><</span><span class="identifier">tcp_stream</span><span class="special">></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"><</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">></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"><</span><span class="identifier">tcp_stream</span><span class="special">></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">-></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"><</span><span class="identifier">string_view</span><span class="special">,</span> <span class="number">3</span><span class="special">></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"><</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">></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"><</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">></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"><</span><span class="identifier">tcp_stream</span><span class="special">></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"><></span> <span class="special">&</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