1
0
mirror of https://github.com/actix/actix-website synced 2025-07-01 01:04:27 +02:00
Files
actix-website/static/api/actix-web/stable/src/actix_web/ws/mod.rs.html
2018-10-10 08:38:33 -07:00

955 lines
65 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source to the Rust file `src/ws/mod.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>mod.rs.html -- source</title><link rel="stylesheet" type="text/css" href="../../../normalize.css"><link rel="stylesheet" type="text/css" href="../../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../../dark.css"><link rel="stylesheet" type="text/css" href="../../../light.css" id="themeStyle"><script src="../../../storage.js"></script></head><body class="rustdoc source"><!--[if lte IE 8]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu">&#9776;</div></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!"><img src="../../../brush.svg" width="18" alt="Pick another theme!"></button><div id="theme-choices"></div></div><script src="../../../theme.js"></script><nav class="sub"><form class="search-form js-only"><div class="search-container"><input class="search-input" name="search" autocomplete="off" placeholder="Click or press S to search, ? for more options…" type="search"><a id="settings-menu" href="../../../settings.html"><img src="../../../wheel.svg" width="18" alt="Change settings"></a></div></form></nav><section id="main" class="content"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10"> 10</span>
<span id="11"> 11</span>
<span id="12"> 12</span>
<span id="13"> 13</span>
<span id="14"> 14</span>
<span id="15"> 15</span>
<span id="16"> 16</span>
<span id="17"> 17</span>
<span id="18"> 18</span>
<span id="19"> 19</span>
<span id="20"> 20</span>
<span id="21"> 21</span>
<span id="22"> 22</span>
<span id="23"> 23</span>
<span id="24"> 24</span>
<span id="25"> 25</span>
<span id="26"> 26</span>
<span id="27"> 27</span>
<span id="28"> 28</span>
<span id="29"> 29</span>
<span id="30"> 30</span>
<span id="31"> 31</span>
<span id="32"> 32</span>
<span id="33"> 33</span>
<span id="34"> 34</span>
<span id="35"> 35</span>
<span id="36"> 36</span>
<span id="37"> 37</span>
<span id="38"> 38</span>
<span id="39"> 39</span>
<span id="40"> 40</span>
<span id="41"> 41</span>
<span id="42"> 42</span>
<span id="43"> 43</span>
<span id="44"> 44</span>
<span id="45"> 45</span>
<span id="46"> 46</span>
<span id="47"> 47</span>
<span id="48"> 48</span>
<span id="49"> 49</span>
<span id="50"> 50</span>
<span id="51"> 51</span>
<span id="52"> 52</span>
<span id="53"> 53</span>
<span id="54"> 54</span>
<span id="55"> 55</span>
<span id="56"> 56</span>
<span id="57"> 57</span>
<span id="58"> 58</span>
<span id="59"> 59</span>
<span id="60"> 60</span>
<span id="61"> 61</span>
<span id="62"> 62</span>
<span id="63"> 63</span>
<span id="64"> 64</span>
<span id="65"> 65</span>
<span id="66"> 66</span>
<span id="67"> 67</span>
<span id="68"> 68</span>
<span id="69"> 69</span>
<span id="70"> 70</span>
<span id="71"> 71</span>
<span id="72"> 72</span>
<span id="73"> 73</span>
<span id="74"> 74</span>
<span id="75"> 75</span>
<span id="76"> 76</span>
<span id="77"> 77</span>
<span id="78"> 78</span>
<span id="79"> 79</span>
<span id="80"> 80</span>
<span id="81"> 81</span>
<span id="82"> 82</span>
<span id="83"> 83</span>
<span id="84"> 84</span>
<span id="85"> 85</span>
<span id="86"> 86</span>
<span id="87"> 87</span>
<span id="88"> 88</span>
<span id="89"> 89</span>
<span id="90"> 90</span>
<span id="91"> 91</span>
<span id="92"> 92</span>
<span id="93"> 93</span>
<span id="94"> 94</span>
<span id="95"> 95</span>
<span id="96"> 96</span>
<span id="97"> 97</span>
<span id="98"> 98</span>
<span id="99"> 99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
<span id="161">161</span>
<span id="162">162</span>
<span id="163">163</span>
<span id="164">164</span>
<span id="165">165</span>
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
<span id="170">170</span>
<span id="171">171</span>
<span id="172">172</span>
<span id="173">173</span>
<span id="174">174</span>
<span id="175">175</span>
<span id="176">176</span>
<span id="177">177</span>
<span id="178">178</span>
<span id="179">179</span>
<span id="180">180</span>
<span id="181">181</span>
<span id="182">182</span>
<span id="183">183</span>
<span id="184">184</span>
<span id="185">185</span>
<span id="186">186</span>
<span id="187">187</span>
<span id="188">188</span>
<span id="189">189</span>
<span id="190">190</span>
<span id="191">191</span>
<span id="192">192</span>
<span id="193">193</span>
<span id="194">194</span>
<span id="195">195</span>
<span id="196">196</span>
<span id="197">197</span>
<span id="198">198</span>
<span id="199">199</span>
<span id="200">200</span>
<span id="201">201</span>
<span id="202">202</span>
<span id="203">203</span>
<span id="204">204</span>
<span id="205">205</span>
<span id="206">206</span>
<span id="207">207</span>
<span id="208">208</span>
<span id="209">209</span>
<span id="210">210</span>
<span id="211">211</span>
<span id="212">212</span>
<span id="213">213</span>
<span id="214">214</span>
<span id="215">215</span>
<span id="216">216</span>
<span id="217">217</span>
<span id="218">218</span>
<span id="219">219</span>
<span id="220">220</span>
<span id="221">221</span>
<span id="222">222</span>
<span id="223">223</span>
<span id="224">224</span>
<span id="225">225</span>
<span id="226">226</span>
<span id="227">227</span>
<span id="228">228</span>
<span id="229">229</span>
<span id="230">230</span>
<span id="231">231</span>
<span id="232">232</span>
<span id="233">233</span>
<span id="234">234</span>
<span id="235">235</span>
<span id="236">236</span>
<span id="237">237</span>
<span id="238">238</span>
<span id="239">239</span>
<span id="240">240</span>
<span id="241">241</span>
<span id="242">242</span>
<span id="243">243</span>
<span id="244">244</span>
<span id="245">245</span>
<span id="246">246</span>
<span id="247">247</span>
<span id="248">248</span>
<span id="249">249</span>
<span id="250">250</span>
<span id="251">251</span>
<span id="252">252</span>
<span id="253">253</span>
<span id="254">254</span>
<span id="255">255</span>
<span id="256">256</span>
<span id="257">257</span>
<span id="258">258</span>
<span id="259">259</span>
<span id="260">260</span>
<span id="261">261</span>
<span id="262">262</span>
<span id="263">263</span>
<span id="264">264</span>
<span id="265">265</span>
<span id="266">266</span>
<span id="267">267</span>
<span id="268">268</span>
<span id="269">269</span>
<span id="270">270</span>
<span id="271">271</span>
<span id="272">272</span>
<span id="273">273</span>
<span id="274">274</span>
<span id="275">275</span>
<span id="276">276</span>
<span id="277">277</span>
<span id="278">278</span>
<span id="279">279</span>
<span id="280">280</span>
<span id="281">281</span>
<span id="282">282</span>
<span id="283">283</span>
<span id="284">284</span>
<span id="285">285</span>
<span id="286">286</span>
<span id="287">287</span>
<span id="288">288</span>
<span id="289">289</span>
<span id="290">290</span>
<span id="291">291</span>
<span id="292">292</span>
<span id="293">293</span>
<span id="294">294</span>
<span id="295">295</span>
<span id="296">296</span>
<span id="297">297</span>
<span id="298">298</span>
<span id="299">299</span>
<span id="300">300</span>
<span id="301">301</span>
<span id="302">302</span>
<span id="303">303</span>
<span id="304">304</span>
<span id="305">305</span>
<span id="306">306</span>
<span id="307">307</span>
<span id="308">308</span>
<span id="309">309</span>
<span id="310">310</span>
<span id="311">311</span>
<span id="312">312</span>
<span id="313">313</span>
<span id="314">314</span>
<span id="315">315</span>
<span id="316">316</span>
<span id="317">317</span>
<span id="318">318</span>
<span id="319">319</span>
<span id="320">320</span>
<span id="321">321</span>
<span id="322">322</span>
<span id="323">323</span>
<span id="324">324</span>
<span id="325">325</span>
<span id="326">326</span>
<span id="327">327</span>
<span id="328">328</span>
<span id="329">329</span>
<span id="330">330</span>
<span id="331">331</span>
<span id="332">332</span>
<span id="333">333</span>
<span id="334">334</span>
<span id="335">335</span>
<span id="336">336</span>
<span id="337">337</span>
<span id="338">338</span>
<span id="339">339</span>
<span id="340">340</span>
<span id="341">341</span>
<span id="342">342</span>
<span id="343">343</span>
<span id="344">344</span>
<span id="345">345</span>
<span id="346">346</span>
<span id="347">347</span>
<span id="348">348</span>
<span id="349">349</span>
<span id="350">350</span>
<span id="351">351</span>
<span id="352">352</span>
<span id="353">353</span>
<span id="354">354</span>
<span id="355">355</span>
<span id="356">356</span>
<span id="357">357</span>
<span id="358">358</span>
<span id="359">359</span>
<span id="360">360</span>
<span id="361">361</span>
<span id="362">362</span>
<span id="363">363</span>
<span id="364">364</span>
<span id="365">365</span>
<span id="366">366</span>
<span id="367">367</span>
<span id="368">368</span>
<span id="369">369</span>
<span id="370">370</span>
<span id="371">371</span>
<span id="372">372</span>
<span id="373">373</span>
<span id="374">374</span>
<span id="375">375</span>
<span id="376">376</span>
<span id="377">377</span>
<span id="378">378</span>
<span id="379">379</span>
<span id="380">380</span>
<span id="381">381</span>
<span id="382">382</span>
<span id="383">383</span>
<span id="384">384</span>
<span id="385">385</span>
<span id="386">386</span>
<span id="387">387</span>
<span id="388">388</span>
<span id="389">389</span>
<span id="390">390</span>
<span id="391">391</span>
<span id="392">392</span>
<span id="393">393</span>
<span id="394">394</span>
<span id="395">395</span>
<span id="396">396</span>
<span id="397">397</span>
<span id="398">398</span>
<span id="399">399</span>
<span id="400">400</span>
<span id="401">401</span>
<span id="402">402</span>
<span id="403">403</span>
<span id="404">404</span>
<span id="405">405</span>
<span id="406">406</span>
<span id="407">407</span>
<span id="408">408</span>
<span id="409">409</span>
<span id="410">410</span>
<span id="411">411</span>
<span id="412">412</span>
<span id="413">413</span>
<span id="414">414</span>
<span id="415">415</span>
<span id="416">416</span>
<span id="417">417</span>
<span id="418">418</span>
<span id="419">419</span>
<span id="420">420</span>
<span id="421">421</span>
<span id="422">422</span>
<span id="423">423</span>
<span id="424">424</span>
<span id="425">425</span>
<span id="426">426</span>
<span id="427">427</span>
<span id="428">428</span>
<span id="429">429</span>
<span id="430">430</span>
<span id="431">431</span>
<span id="432">432</span>
<span id="433">433</span>
<span id="434">434</span>
<span id="435">435</span>
<span id="436">436</span>
<span id="437">437</span>
<span id="438">438</span>
<span id="439">439</span>
<span id="440">440</span>
<span id="441">441</span>
<span id="442">442</span>
<span id="443">443</span>
<span id="444">444</span>
<span id="445">445</span>
<span id="446">446</span>
<span id="447">447</span>
<span id="448">448</span>
<span id="449">449</span>
<span id="450">450</span>
<span id="451">451</span>
<span id="452">452</span>
<span id="453">453</span>
<span id="454">454</span>
<span id="455">455</span>
<span id="456">456</span>
<span id="457">457</span>
<span id="458">458</span>
<span id="459">459</span>
<span id="460">460</span>
<span id="461">461</span>
<span id="462">462</span>
<span id="463">463</span>
<span id="464">464</span>
<span id="465">465</span>
<span id="466">466</span>
<span id="467">467</span>
<span id="468">468</span>
<span id="469">469</span>
<span id="470">470</span>
<span id="471">471</span>
<span id="472">472</span>
<span id="473">473</span>
<span id="474">474</span>
<span id="475">475</span>
<span id="476">476</span>
</pre><pre class="rust ">
<span class="doccomment">//! `WebSocket` support for Actix</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! To setup a `WebSocket`, first do web socket handshake then on success</span>
<span class="doccomment">//! convert `Payload` into a `WsStream` stream and then use `WsWriter` to</span>
<span class="doccomment">//! communicate with the peer.</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! ## Example</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! ```rust</span>
<span class="doccomment">//! # extern crate actix_web;</span>
<span class="doccomment">//! # use actix_web::actix::*;</span>
<span class="doccomment">//! # use actix_web::*;</span>
<span class="doccomment">//! use actix_web::{ws, HttpRequest, HttpResponse};</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! // do websocket handshake and start actor</span>
<span class="doccomment">//! fn ws_index(req: &amp;HttpRequest) -&gt; Result&lt;HttpResponse&gt; {</span>
<span class="doccomment">//! ws::start(req, Ws)</span>
<span class="doccomment">//! }</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! struct Ws;</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! impl Actor for Ws {</span>
<span class="doccomment">//! type Context = ws::WebsocketContext&lt;Self&gt;;</span>
<span class="doccomment">//! }</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! // Handler for ws::Message messages</span>
<span class="doccomment">//! impl StreamHandler&lt;ws::Message, ws::ProtocolError&gt; for Ws {</span>
<span class="doccomment">//! fn handle(&amp;mut self, msg: ws::Message, ctx: &amp;mut Self::Context) {</span>
<span class="doccomment">//! match msg {</span>
<span class="doccomment">//! ws::Message::Ping(msg) =&gt; ctx.pong(&amp;msg),</span>
<span class="doccomment">//! ws::Message::Text(text) =&gt; ctx.text(text),</span>
<span class="doccomment">//! ws::Message::Binary(bin) =&gt; ctx.binary(bin),</span>
<span class="doccomment">//! _ =&gt; (),</span>
<span class="doccomment">//! }</span>
<span class="doccomment">//! }</span>
<span class="doccomment">//! }</span>
<span class="doccomment">//! #</span>
<span class="doccomment">//! # fn main() {</span>
<span class="doccomment">//! # App::new()</span>
<span class="doccomment">//! # .resource(&quot;/ws/&quot;, |r| r.f(ws_index)) // &lt;- register websocket route</span>
<span class="doccomment">//! # .finish();</span>
<span class="doccomment">//! # }</span>
<span class="doccomment">//! ```</span>
<span class="kw">use</span> <span class="ident">bytes</span>::<span class="ident">Bytes</span>;
<span class="kw">use</span> <span class="ident">futures</span>::{<span class="ident">Async</span>, <span class="ident">Poll</span>, <span class="ident">Stream</span>};
<span class="kw">use</span> <span class="ident">http</span>::{<span class="ident">header</span>, <span class="ident">Method</span>, <span class="ident">StatusCode</span>};
<span class="kw">use</span> <span class="kw">super</span>::<span class="ident">actix</span>::{<span class="ident">Actor</span>, <span class="ident">StreamHandler</span>};
<span class="kw">use</span> <span class="ident">body</span>::<span class="ident">Binary</span>;
<span class="kw">use</span> <span class="ident">error</span>::{<span class="ident">Error</span>, <span class="ident">PayloadError</span>, <span class="ident">ResponseError</span>};
<span class="kw">use</span> <span class="ident">httpmessage</span>::<span class="ident">HttpMessage</span>;
<span class="kw">use</span> <span class="ident">httprequest</span>::<span class="ident">HttpRequest</span>;
<span class="kw">use</span> <span class="ident">httpresponse</span>::{<span class="ident">ConnectionType</span>, <span class="ident">HttpResponse</span>, <span class="ident">HttpResponseBuilder</span>};
<span class="kw">use</span> <span class="ident">payload</span>::<span class="ident">PayloadBuffer</span>;
<span class="kw">mod</span> <span class="ident">client</span>;
<span class="kw">mod</span> <span class="ident">context</span>;
<span class="kw">mod</span> <span class="ident">frame</span>;
<span class="kw">mod</span> <span class="ident">mask</span>;
<span class="kw">mod</span> <span class="ident">proto</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="self">self</span>::<span class="ident">client</span>::{
<span class="ident">Client</span>, <span class="ident">ClientError</span>, <span class="ident">ClientHandshake</span>, <span class="ident">ClientReader</span>, <span class="ident">ClientWriter</span>,
};
<span class="kw">pub</span> <span class="kw">use</span> <span class="self">self</span>::<span class="ident">context</span>::<span class="ident">WebsocketContext</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="self">self</span>::<span class="ident">frame</span>::{<span class="ident">Frame</span>, <span class="ident">FramedMessage</span>};
<span class="kw">pub</span> <span class="kw">use</span> <span class="self">self</span>::<span class="ident">proto</span>::{<span class="ident">CloseCode</span>, <span class="ident">CloseReason</span>, <span class="ident">OpCode</span>};
<span class="doccomment">/// Websocket protocol errors</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Fail</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">ProtocolError</span> {
<span class="doccomment">/// Received an unmasked frame from client</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Received an unmasked frame from client&quot;</span>)]</span>
<span class="ident">UnmaskedFrame</span>,
<span class="doccomment">/// Received a masked frame from server</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Received a masked frame from server&quot;</span>)]</span>
<span class="ident">MaskedFrame</span>,
<span class="doccomment">/// Encountered invalid opcode</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Invalid opcode: {}&quot;</span>, <span class="ident">_0</span>)]</span>
<span class="ident">InvalidOpcode</span>(<span class="ident">u8</span>),
<span class="doccomment">/// Invalid control frame length</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Invalid control frame length: {}&quot;</span>, <span class="ident">_0</span>)]</span>
<span class="ident">InvalidLength</span>(<span class="ident">usize</span>),
<span class="doccomment">/// Bad web socket op code</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Bad web socket op code&quot;</span>)]</span>
<span class="ident">BadOpCode</span>,
<span class="doccomment">/// A payload reached size limit.</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;A payload reached size limit.&quot;</span>)]</span>
<span class="ident">Overflow</span>,
<span class="doccomment">/// Continuation is not supported</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Continuation is not supported.&quot;</span>)]</span>
<span class="ident">NoContinuation</span>,
<span class="doccomment">/// Bad utf-8 encoding</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Bad utf-8 encoding.&quot;</span>)]</span>
<span class="ident">BadEncoding</span>,
<span class="doccomment">/// Payload error</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Payload error: {}&quot;</span>, <span class="ident">_0</span>)]</span>
<span class="ident">Payload</span>(<span class="attribute">#[<span class="ident">cause</span>]</span> <span class="ident">PayloadError</span>),
}
<span class="kw">impl</span> <span class="ident">ResponseError</span> <span class="kw">for</span> <span class="ident">ProtocolError</span> {}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">PayloadError</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">ProtocolError</span> {
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">err</span>: <span class="ident">PayloadError</span>) <span class="op">-&gt;</span> <span class="ident">ProtocolError</span> {
<span class="ident">ProtocolError</span>::<span class="ident">Payload</span>(<span class="ident">err</span>)
}
}
<span class="doccomment">/// Websocket handshake errors</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Fail</span>, <span class="ident">PartialEq</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">HandshakeError</span> {
<span class="doccomment">/// Only get method is allowed</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Method not allowed&quot;</span>)]</span>
<span class="ident">GetMethodRequired</span>,
<span class="doccomment">/// Upgrade header if not set to websocket</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Websocket upgrade is expected&quot;</span>)]</span>
<span class="ident">NoWebsocketUpgrade</span>,
<span class="doccomment">/// Connection header is not set to upgrade</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Connection upgrade is expected&quot;</span>)]</span>
<span class="ident">NoConnectionUpgrade</span>,
<span class="doccomment">/// Websocket version header is not set</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Websocket version header is required&quot;</span>)]</span>
<span class="ident">NoVersionHeader</span>,
<span class="doccomment">/// Unsupported websocket version</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Unsupported version&quot;</span>)]</span>
<span class="ident">UnsupportedVersion</span>,
<span class="doccomment">/// Websocket key is not set or wrong</span>
<span class="attribute">#[<span class="ident">fail</span>(<span class="ident">display</span> <span class="op">=</span> <span class="string">&quot;Unknown websocket key&quot;</span>)]</span>
<span class="ident">BadWebsocketKey</span>,
}
<span class="kw">impl</span> <span class="ident">ResponseError</span> <span class="kw">for</span> <span class="ident">HandshakeError</span> {
<span class="kw">fn</span> <span class="ident">error_response</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="ident">HttpResponse</span> {
<span class="kw">match</span> <span class="kw-2">*</span><span class="self">self</span> {
<span class="ident">HandshakeError</span>::<span class="ident">GetMethodRequired</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">MethodNotAllowed</span>()
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">ALLOW</span>, <span class="string">&quot;GET&quot;</span>)
.<span class="ident">finish</span>(),
<span class="ident">HandshakeError</span>::<span class="ident">NoWebsocketUpgrade</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">BadRequest</span>()
.<span class="ident">reason</span>(<span class="string">&quot;No WebSocket UPGRADE header found&quot;</span>)
.<span class="ident">finish</span>(),
<span class="ident">HandshakeError</span>::<span class="ident">NoConnectionUpgrade</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">BadRequest</span>()
.<span class="ident">reason</span>(<span class="string">&quot;No CONNECTION upgrade&quot;</span>)
.<span class="ident">finish</span>(),
<span class="ident">HandshakeError</span>::<span class="ident">NoVersionHeader</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">BadRequest</span>()
.<span class="ident">reason</span>(<span class="string">&quot;Websocket version header is required&quot;</span>)
.<span class="ident">finish</span>(),
<span class="ident">HandshakeError</span>::<span class="ident">UnsupportedVersion</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">BadRequest</span>()
.<span class="ident">reason</span>(<span class="string">&quot;Unsupported version&quot;</span>)
.<span class="ident">finish</span>(),
<span class="ident">HandshakeError</span>::<span class="ident">BadWebsocketKey</span> <span class="op">=&gt;</span> <span class="ident">HttpResponse</span>::<span class="ident">BadRequest</span>()
.<span class="ident">reason</span>(<span class="string">&quot;Handshake error&quot;</span>)
.<span class="ident">finish</span>(),
}
}
}
<span class="doccomment">/// `WebSocket` Message</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">PartialEq</span>, <span class="ident">Message</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">Message</span> {
<span class="doccomment">/// Text message</span>
<span class="ident">Text</span>(<span class="ident">String</span>),
<span class="doccomment">/// Binary message</span>
<span class="ident">Binary</span>(<span class="ident">Binary</span>),
<span class="doccomment">/// Ping message</span>
<span class="ident">Ping</span>(<span class="ident">String</span>),
<span class="doccomment">/// Pong message</span>
<span class="ident">Pong</span>(<span class="ident">String</span>),
<span class="doccomment">/// Close message with optional reason</span>
<span class="ident">Close</span>(<span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">CloseReason</span><span class="op">&gt;</span>),
}
<span class="doccomment">/// Do websocket handshake and start actor</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">start</span><span class="op">&lt;</span><span class="ident">A</span>, <span class="ident">S</span><span class="op">&gt;</span>(<span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>, <span class="ident">actor</span>: <span class="ident">A</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponse</span>, <span class="ident">Error</span><span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">A</span>: <span class="ident">Actor</span><span class="op">&lt;</span><span class="ident">Context</span> <span class="op">=</span> <span class="ident">WebsocketContext</span><span class="op">&lt;</span><span class="ident">A</span>, <span class="ident">S</span><span class="op">&gt;&gt;</span> <span class="op">+</span> <span class="ident">StreamHandler</span><span class="op">&lt;</span><span class="ident">Message</span>, <span class="ident">ProtocolError</span><span class="op">&gt;</span>,
<span class="ident">S</span>: <span class="lifetime">&#39;static</span>,
{
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">handshake</span>(<span class="ident">req</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">stream</span> <span class="op">=</span> <span class="ident">WsStream</span>::<span class="ident">new</span>(<span class="ident">req</span>.<span class="ident">payload</span>());
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">WebsocketContext</span>::<span class="ident">create</span>(<span class="ident">req</span>.<span class="ident">clone</span>(), <span class="ident">actor</span>, <span class="ident">stream</span>);
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">body</span>(<span class="ident">body</span>))
}
<span class="doccomment">/// Prepare `WebSocket` handshake response.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function returns handshake `HttpResponse`, ready to send to peer.</span>
<span class="doccomment">/// It does not perform any IO.</span>
<span class="doccomment">///</span>
<span class="comment">// /// `protocols` is a sequence of known protocols. On successful handshake,</span>
<span class="comment">// /// the returned response headers contain the first protocol in this list</span>
<span class="comment">// /// which the server also knows.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">handshake</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>(
<span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponseBuilder</span>, <span class="ident">HandshakeError</span><span class="op">&gt;</span> {
<span class="comment">// WebSocket accepts only GET</span>
<span class="kw">if</span> <span class="kw-2">*</span><span class="ident">req</span>.<span class="ident">method</span>() <span class="op">!=</span> <span class="ident">Method</span>::<span class="ident">GET</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">GetMethodRequired</span>);
}
<span class="comment">// Check for &quot;UPGRADE&quot; to websocket header</span>
<span class="kw">let</span> <span class="ident">has_hdr</span> <span class="op">=</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">hdr</span>) <span class="op">=</span> <span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">UPGRADE</span>) {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">s</span>) <span class="op">=</span> <span class="ident">hdr</span>.<span class="ident">to_str</span>() {
<span class="ident">s</span>.<span class="ident">to_lowercase</span>().<span class="ident">contains</span>(<span class="string">&quot;websocket&quot;</span>)
} <span class="kw">else</span> {
<span class="bool-val">false</span>
}
} <span class="kw">else</span> {
<span class="bool-val">false</span>
};
<span class="kw">if</span> <span class="op">!</span><span class="ident">has_hdr</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">NoWebsocketUpgrade</span>);
}
<span class="comment">// Upgrade connection</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">req</span>.<span class="ident">upgrade</span>() {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">NoConnectionUpgrade</span>);
}
<span class="comment">// check supported version</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">contains_key</span>(<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_VERSION</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">NoVersionHeader</span>);
}
<span class="kw">let</span> <span class="ident">supported_ver</span> <span class="op">=</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">hdr</span>) <span class="op">=</span> <span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_VERSION</span>) {
<span class="ident">hdr</span> <span class="op">==</span> <span class="string">&quot;13&quot;</span> <span class="op">||</span> <span class="ident">hdr</span> <span class="op">==</span> <span class="string">&quot;8&quot;</span> <span class="op">||</span> <span class="ident">hdr</span> <span class="op">==</span> <span class="string">&quot;7&quot;</span>
} <span class="kw">else</span> {
<span class="bool-val">false</span>
}
};
<span class="kw">if</span> <span class="op">!</span><span class="ident">supported_ver</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">UnsupportedVersion</span>);
}
<span class="comment">// check client handshake for validity</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">contains_key</span>(<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_KEY</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">HandshakeError</span>::<span class="ident">BadWebsocketKey</span>);
}
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> {
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_KEY</span>).<span class="ident">unwrap</span>();
<span class="ident">proto</span>::<span class="ident">hash_key</span>(<span class="ident">key</span>.<span class="ident">as_ref</span>())
};
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse</span>::<span class="ident">build</span>(<span class="ident">StatusCode</span>::<span class="ident">SWITCHING_PROTOCOLS</span>)
.<span class="ident">connection_type</span>(<span class="ident">ConnectionType</span>::<span class="ident">Upgrade</span>)
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">UPGRADE</span>, <span class="string">&quot;websocket&quot;</span>)
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">TRANSFER_ENCODING</span>, <span class="string">&quot;chunked&quot;</span>)
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_ACCEPT</span>, <span class="ident">key</span>.<span class="ident">as_str</span>())
.<span class="ident">take</span>())
}
<span class="doccomment">/// Maps `Payload` stream into stream of `ws::Message` items</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">WsStream</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> {
<span class="ident">rx</span>: <span class="ident">PayloadBuffer</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>,
<span class="ident">closed</span>: <span class="ident">bool</span>,
<span class="ident">max_size</span>: <span class="ident">usize</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> <span class="ident">WsStream</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">S</span>: <span class="ident">Stream</span><span class="op">&lt;</span><span class="ident">Item</span> <span class="op">=</span> <span class="ident">Bytes</span>, <span class="ident">Error</span> <span class="op">=</span> <span class="ident">PayloadError</span><span class="op">&gt;</span>,
{
<span class="doccomment">/// Create new websocket frames stream</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">stream</span>: <span class="ident">S</span>) <span class="op">-&gt;</span> <span class="ident">WsStream</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> {
<span class="ident">WsStream</span> {
<span class="ident">rx</span>: <span class="ident">PayloadBuffer</span>::<span class="ident">new</span>(<span class="ident">stream</span>),
<span class="ident">closed</span>: <span class="bool-val">false</span>,
<span class="ident">max_size</span>: <span class="number">65_536</span>,
}
}
<span class="doccomment">/// Set max frame size</span>
<span class="doccomment">///</span>
<span class="doccomment">/// By default max size is set to 64kb</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">max_size</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">size</span>: <span class="ident">usize</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">max_size</span> <span class="op">=</span> <span class="ident">size</span>;
<span class="self">self</span>
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> <span class="ident">Stream</span> <span class="kw">for</span> <span class="ident">WsStream</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">S</span>: <span class="ident">Stream</span><span class="op">&lt;</span><span class="ident">Item</span> <span class="op">=</span> <span class="ident">Bytes</span>, <span class="ident">Error</span> <span class="op">=</span> <span class="ident">PayloadError</span><span class="op">&gt;</span>,
{
<span class="kw">type</span> <span class="ident">Item</span> <span class="op">=</span> <span class="ident">Message</span>;
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">ProtocolError</span>;
<span class="kw">fn</span> <span class="ident">poll</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-&gt;</span> <span class="ident">Poll</span><span class="op">&lt;</span><span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="self">Self</span>::<span class="ident">Item</span><span class="op">&gt;</span>, <span class="self">Self</span>::<span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">closed</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">None</span>));
}
<span class="kw">match</span> <span class="ident">Frame</span>::<span class="ident">parse</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>.<span class="ident">rx</span>, <span class="bool-val">true</span>, <span class="self">self</span>.<span class="ident">max_size</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">frame</span>))) <span class="op">=&gt;</span> {
<span class="kw">let</span> (<span class="ident">finished</span>, <span class="ident">opcode</span>, <span class="ident">payload</span>) <span class="op">=</span> <span class="ident">frame</span>.<span class="ident">unpack</span>();
<span class="comment">// continuation is not supported</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">finished</span> {
<span class="self">self</span>.<span class="ident">closed</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ProtocolError</span>::<span class="ident">NoContinuation</span>);
}
<span class="kw">match</span> <span class="ident">opcode</span> {
<span class="ident">OpCode</span>::<span class="ident">Continue</span> <span class="op">=&gt;</span> <span class="prelude-val">Err</span>(<span class="ident">ProtocolError</span>::<span class="ident">NoContinuation</span>),
<span class="ident">OpCode</span>::<span class="ident">Bad</span> <span class="op">=&gt;</span> {
<span class="self">self</span>.<span class="ident">closed</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="prelude-val">Err</span>(<span class="ident">ProtocolError</span>::<span class="ident">BadOpCode</span>)
}
<span class="ident">OpCode</span>::<span class="ident">Close</span> <span class="op">=&gt;</span> {
<span class="self">self</span>.<span class="ident">closed</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="kw">let</span> <span class="ident">close_reason</span> <span class="op">=</span> <span class="ident">Frame</span>::<span class="ident">parse_close_payload</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>);
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">Message</span>::<span class="ident">Close</span>(<span class="ident">close_reason</span>))))
}
<span class="ident">OpCode</span>::<span class="ident">Ping</span> <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">Message</span>::<span class="ident">Ping</span>(
<span class="ident">String</span>::<span class="ident">from_utf8_lossy</span>(<span class="ident">payload</span>.<span class="ident">as_ref</span>()).<span class="ident">into</span>(),
)))),
<span class="ident">OpCode</span>::<span class="ident">Pong</span> <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">Message</span>::<span class="ident">Pong</span>(
<span class="ident">String</span>::<span class="ident">from_utf8_lossy</span>(<span class="ident">payload</span>.<span class="ident">as_ref</span>()).<span class="ident">into</span>(),
)))),
<span class="ident">OpCode</span>::<span class="ident">Binary</span> <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">Message</span>::<span class="ident">Binary</span>(<span class="ident">payload</span>)))),
<span class="ident">OpCode</span>::<span class="ident">Text</span> <span class="op">=&gt;</span> {
<span class="kw">let</span> <span class="ident">tmp</span> <span class="op">=</span> <span class="ident">Vec</span>::<span class="ident">from</span>(<span class="ident">payload</span>.<span class="ident">as_ref</span>());
<span class="kw">match</span> <span class="ident">String</span>::<span class="ident">from_utf8</span>(<span class="ident">tmp</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">s</span>) <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">Message</span>::<span class="ident">Text</span>(<span class="ident">s</span>)))),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=&gt;</span> {
<span class="self">self</span>.<span class="ident">closed</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="prelude-val">Err</span>(<span class="ident">ProtocolError</span>::<span class="ident">BadEncoding</span>)
}
}
}
}
}
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">None</span>)) <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">None</span>)),
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">NotReady</span>) <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">NotReady</span>),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=&gt;</span> {
<span class="self">self</span>.<span class="ident">closed</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="prelude-val">Err</span>(<span class="ident">e</span>)
}
}
}
}
<span class="doccomment">/// Common writing methods for a websocket.</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">WsWriter</span> {
<span class="doccomment">/// Send a text</span>
<span class="kw">fn</span> <span class="ident">send_text</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">Binary</span><span class="op">&gt;&gt;</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">text</span>: <span class="ident">T</span>);
<span class="doccomment">/// Send a binary</span>
<span class="kw">fn</span> <span class="ident">send_binary</span><span class="op">&lt;</span><span class="ident">B</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">Binary</span><span class="op">&gt;&gt;</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">data</span>: <span class="ident">B</span>);
<span class="doccomment">/// Send a ping message</span>
<span class="kw">fn</span> <span class="ident">send_ping</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">message</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>);
<span class="doccomment">/// Send a pong message</span>
<span class="kw">fn</span> <span class="ident">send_pong</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">message</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>);
<span class="doccomment">/// Close the connection</span>
<span class="kw">fn</span> <span class="ident">send_close</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">reason</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">CloseReason</span><span class="op">&gt;</span>);
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">http</span>::{<span class="ident">header</span>, <span class="ident">Method</span>};
<span class="kw">use</span> <span class="ident">test</span>::<span class="ident">TestRequest</span>;
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_handshake</span>() {
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">POST</span>).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">GetMethodRequired</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">NoWebsocketUpgrade</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">UPGRADE</span>, <span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;test&quot;</span>))
.<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">NoWebsocketUpgrade</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">UPGRADE</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;websocket&quot;</span>),
).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">NoConnectionUpgrade</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">UPGRADE</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;websocket&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONNECTION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;upgrade&quot;</span>),
).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">NoVersionHeader</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">UPGRADE</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;websocket&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONNECTION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;upgrade&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_VERSION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;5&quot;</span>),
).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">UnsupportedVersion</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">UPGRADE</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;websocket&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONNECTION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;upgrade&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_VERSION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;13&quot;</span>),
).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">HandshakeError</span>::<span class="ident">BadWebsocketKey</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">err</span>().<span class="ident">unwrap</span>()
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>()
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">UPGRADE</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;websocket&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONNECTION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;upgrade&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_VERSION</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;13&quot;</span>),
).<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">SEC_WEBSOCKET_KEY</span>,
<span class="ident">header</span>::<span class="ident">HeaderValue</span>::<span class="ident">from_static</span>(<span class="string">&quot;13&quot;</span>),
).<span class="ident">finish</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">StatusCode</span>::<span class="ident">SWITCHING_PROTOCOLS</span>,
<span class="ident">handshake</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>().<span class="ident">finish</span>().<span class="ident">status</span>()
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_wserror_http_response</span>() {
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">GetMethodRequired</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">METHOD_NOT_ALLOWED</span>);
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">NoWebsocketUpgrade</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>);
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">NoConnectionUpgrade</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>);
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">NoVersionHeader</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>);
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">UnsupportedVersion</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>);
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">HttpResponse</span> <span class="op">=</span> <span class="ident">HandshakeError</span>::<span class="ident">BadWebsocketKey</span>.<span class="ident">error_response</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>);
}
}
</pre>
</section><section id="search" class="content hidden"></section><section class="footer"></section><aside id="help" class="hidden"><div><h1 class="hidden">Help</h1><div class="shortcuts"><h2>Keyboard Shortcuts</h2><dl><dt><kbd>?</kbd></dt><dd>Show this help dialog</dd><dt><kbd>S</kbd></dt><dd>Focus the search field</dd><dt><kbd></kbd></dt><dd>Move up in search results</dd><dt><kbd></kbd></dt><dd>Move down in search results</dd><dt><kbd></kbd></dt><dd>Switch tab</dd><dt><kbd>&#9166;</kbd></dt><dd>Go to active search result</dd><dt><kbd>+</kbd></dt><dd>Expand all sections</dd><dt><kbd>-</kbd></dt><dd>Collapse all sections</dd></dl></div><div class="infos"><h2>Search Tricks</h2><p>Prefix searches with a type followed by a colon (e.g. <code>fn:</code>) to restrict the search to a given type.</p><p>Accepted types are: <code>fn</code>, <code>mod</code>, <code>struct</code>, <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, and <code>const</code>.</p><p>Search functions by type signature (e.g. <code>vec -> usize</code> or <code>* -> vec</code>)</p><p>Search multiple things at once by splitting your query with comma (e.g. <code>str,u8</code> or <code>String,struct:Vec,test</code>)</p></div></div></aside><script>window.rootPath = "../../../";window.currentCrate = "actix_web";</script><script src="../../../aliases.js"></script><script src="../../../main.js"></script><script defer src="../../../search-index.js"></script></body></html>