1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-03-16 10:22:42 +01:00
actix-extras/src/actix_session/middleware.rs.html

937 lines
61 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 of the Rust file `actix-session/src/middleware.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>middleware.rs - source</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><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="../../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../../dark.css" disabled><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.js"></script><script defer src="../../main.js"></script><noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="icon" href="https://actix.rs/favicon.ico"></head><body class="rustdoc source"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../../actix_session/index.html"><div class="logo-container"><img src="https://actix.rs/img/logo.png" alt="logo"></div>
</a><h2 class="location"></h2>
</nav>
<nav class="sidebar"><a class="sidebar-logo" href="../../actix_session/index.html"><div class="logo-container">
<img src="https://actix.rs/img/logo.png" alt="logo"></div>
</a></nav><main><div class="width-limiter"><div class="sub-container"><a class="sub-logo-container" href="../../actix_session/index.html">
<img src="https://actix.rs/img/logo.png" alt="logo"></a><nav class="sub"><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><button type="button">?</button></div><div id="settings-menu" tabindex="-1">
<a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../wheel.svg"></a></div>
</div></form></nav></div><section id="main-content" class="content"><div class="example-wrap"><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>
</pre><pre class="rust"><code><span class="kw">use</span> <span class="ident">std</span>::{<span class="ident">collections::HashMap</span>, <span class="ident">convert::TryInto</span>, <span class="ident">fmt</span>, <span class="ident">future::Future</span>, <span class="ident">pin::Pin</span>, <span class="ident">rc::Rc</span>};
<span class="kw">use</span> <span class="ident">actix_utils::future</span>::{<span class="ident">ready</span>, <span class="ident">Ready</span>};
<span class="kw">use</span> <span class="ident">actix_web</span>::{
<span class="ident">body::MessageBody</span>,
<span class="ident">cookie</span>::{<span class="ident">Cookie</span>, <span class="ident">CookieJar</span>, <span class="ident">Key</span>},
<span class="ident">dev</span>::{<span class="ident">forward_ready</span>, <span class="ident">ResponseHead</span>, <span class="ident">Service</span>, <span class="ident">ServiceRequest</span>, <span class="ident">ServiceResponse</span>, <span class="ident">Transform</span>},
<span class="ident">http::header</span>::{<span class="ident">HeaderValue</span>, <span class="ident">SET_COOKIE</span>},
<span class="ident">HttpResponse</span>,
};
<span class="kw">use</span> <span class="ident">anyhow::Context</span>;
<span class="kw">use</span> <span class="kw">crate</span>::{
<span class="ident">config</span>::{
<span class="self">self</span>, <span class="ident">Configuration</span>, <span class="ident">CookieConfiguration</span>, <span class="ident">CookieContentSecurity</span>, <span class="ident">SessionMiddlewareBuilder</span>,
<span class="ident">TtlExtensionPolicy</span>,
},
<span class="ident">storage</span>::{<span class="ident">LoadError</span>, <span class="ident">SessionKey</span>, <span class="ident">SessionStore</span>},
<span class="ident">Session</span>, <span class="ident">SessionStatus</span>,
};
<span class="doccomment">/// A middleware for session management in Actix Web applications.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// [`SessionMiddleware`] takes care of a few jobs:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// - Instructs the session storage backend to create/update/delete/retrieve the state attached to</span>
<span class="doccomment">/// a session according to its status and the operations that have been performed against it;</span>
<span class="doccomment">/// - Set/remove a cookie, on the client side, to enable a user to be consistently associated with</span>
<span class="doccomment">/// the same session across multiple HTTP requests.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Use [`SessionMiddleware::new`] to initialize the session framework using the default parameters.</span>
<span class="doccomment">/// To create a new instance of [`SessionMiddleware`] you need to provide:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// - an instance of the session storage backend you wish to use (i.e. an implementation of</span>
<span class="doccomment">/// [`SessionStore`]);</span>
<span class="doccomment">/// - a secret key, to sign or encrypt the content of client-side session cookie.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```no_run</span>
<span class="doccomment">/// use actix_web::{web, App, HttpServer, HttpResponse, Error};</span>
<span class="doccomment">/// use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore};</span>
<span class="doccomment">/// use actix_web::cookie::Key;</span>
<span class="doccomment">///</span>
<span class="doccomment">/// // The secret key would usually be read from a configuration file/environment variables.</span>
<span class="doccomment">/// fn get_secret_key() -&gt; Key {</span>
<span class="doccomment">/// # todo!()</span>
<span class="doccomment">/// // [...]</span>
<span class="doccomment">/// }</span>
<span class="doccomment">///</span>
<span class="doccomment">/// #[actix_web::main]</span>
<span class="doccomment">/// async fn main() -&gt; std::io::Result&lt;()&gt; {</span>
<span class="doccomment">/// let secret_key = get_secret_key();</span>
<span class="doccomment">/// let redis_connection_string = &quot;127.0.0.1:6379&quot;;</span>
<span class="doccomment">/// HttpServer::new(move ||</span>
<span class="doccomment">/// App::new()</span>
<span class="doccomment">/// // Add session management to your application using Redis for session state storage</span>
<span class="doccomment">/// .wrap(</span>
<span class="doccomment">/// SessionMiddleware::new(</span>
<span class="doccomment">/// RedisActorSessionStore::new(redis_connection_string),</span>
<span class="doccomment">/// secret_key.clone()</span>
<span class="doccomment">/// )</span>
<span class="doccomment">/// )</span>
<span class="doccomment">/// .default_service(web::to(|| HttpResponse::Ok())))</span>
<span class="doccomment">/// .bind((&quot;127.0.0.1&quot;, 8080))?</span>
<span class="doccomment">/// .run()</span>
<span class="doccomment">/// .await</span>
<span class="doccomment">/// }</span>
<span class="doccomment">/// ```</span>
<span class="doccomment">///</span>
<span class="doccomment">/// If you want to customise use [`builder`](Self::builder) instead of [`new`](Self::new):</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```no_run</span>
<span class="doccomment">/// use actix_web::{App, cookie::{Key, time}, Error, HttpResponse, HttpServer, web};</span>
<span class="doccomment">/// use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore};</span>
<span class="doccomment">/// use actix_session::config::PersistentSession;</span>
<span class="doccomment">///</span>
<span class="doccomment">/// // The secret key would usually be read from a configuration file/environment variables.</span>
<span class="doccomment">/// fn get_secret_key() -&gt; Key {</span>
<span class="doccomment">/// # todo!()</span>
<span class="doccomment">/// // [...]</span>
<span class="doccomment">/// }</span>
<span class="doccomment">///</span>
<span class="doccomment">/// #[actix_web::main]</span>
<span class="doccomment">/// async fn main() -&gt; std::io::Result&lt;()&gt; {</span>
<span class="doccomment">/// let secret_key = get_secret_key();</span>
<span class="doccomment">/// let redis_connection_string = &quot;127.0.0.1:6379&quot;;</span>
<span class="doccomment">/// HttpServer::new(move ||</span>
<span class="doccomment">/// App::new()</span>
<span class="doccomment">/// // Customise session length!</span>
<span class="doccomment">/// .wrap(</span>
<span class="doccomment">/// SessionMiddleware::builder(</span>
<span class="doccomment">/// RedisActorSessionStore::new(redis_connection_string),</span>
<span class="doccomment">/// secret_key.clone()</span>
<span class="doccomment">/// )</span>
<span class="doccomment">/// .session_lifecycle(</span>
<span class="doccomment">/// PersistentSession::default()</span>
<span class="doccomment">/// .session_ttl(time::Duration::days(5))</span>
<span class="doccomment">/// )</span>
<span class="doccomment">/// .build(),</span>
<span class="doccomment">/// )</span>
<span class="doccomment">/// .default_service(web::to(|| HttpResponse::Ok())))</span>
<span class="doccomment">/// .bind((&quot;127.0.0.1&quot;, 8080))?</span>
<span class="doccomment">/// .run()</span>
<span class="doccomment">/// .await</span>
<span class="doccomment">/// }</span>
<span class="doccomment">/// ```</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ## How did we choose defaults?</span>
<span class="doccomment">///</span>
<span class="doccomment">/// You should not regret adding `actix-session` to your dependencies and going to production using</span>
<span class="doccomment">/// the default configuration. That is why, when in doubt, we opt to use the most secure option for</span>
<span class="doccomment">/// each configuration parameter.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// We expose knobs to change the default to suit your needs—i.e., if you know what you are doing,</span>
<span class="doccomment">/// we will not stop you. But being a subject-matter expert should not be a requirement to deploy</span>
<span class="doccomment">/// reasonably secure implementation of sessions.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">SessionMiddleware</span><span class="op">&lt;</span><span class="ident">Store</span>: <span class="ident">SessionStore</span><span class="op">&gt;</span> {
<span class="ident">storage_backend</span>: <span class="ident">Rc</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span>,
<span class="ident">configuration</span>: <span class="ident">Rc</span><span class="op">&lt;</span><span class="ident">Configuration</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">Store</span>: <span class="ident">SessionStore</span><span class="op">&gt;</span> <span class="ident">SessionMiddleware</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span> {
<span class="doccomment">/// Use [`SessionMiddleware::new`] to initialize the session framework using the default</span>
<span class="doccomment">/// parameters.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// To create a new instance of [`SessionMiddleware`] you need to provide:</span>
<span class="doccomment">/// - an instance of the session storage backend you wish to use (i.e. an implementation of</span>
<span class="doccomment">/// [`SessionStore]);</span>
<span class="doccomment">/// - a secret key, to sign or encrypt the content of client-side session cookie.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">store</span>: <span class="ident">Store</span>, <span class="ident">key</span>: <span class="ident">Key</span>) -&gt; <span class="self">Self</span> {
<span class="ident"><span class="self">Self</span>::builder</span>(<span class="ident">store</span>, <span class="ident">key</span>).<span class="ident">build</span>()
}
<span class="doccomment">/// A fluent API to configure [`SessionMiddleware`].</span>
<span class="doccomment">///</span>
<span class="doccomment">/// It takes as input the two required inputs to create a new instance of [`SessionMiddleware`]:</span>
<span class="doccomment">/// - an instance of the session storage backend you wish to use (i.e. an implementation of</span>
<span class="doccomment">/// [`SessionStore]);</span>
<span class="doccomment">/// - a secret key, to sign or encrypt the content of client-side session cookie.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">builder</span>(<span class="ident">store</span>: <span class="ident">Store</span>, <span class="ident">key</span>: <span class="ident">Key</span>) -&gt; <span class="ident">SessionMiddlewareBuilder</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span> {
<span class="ident">SessionMiddlewareBuilder::new</span>(<span class="ident">store</span>, <span class="ident">config::default_configuration</span>(<span class="ident">key</span>))
}
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">from_parts</span>(<span class="ident">store</span>: <span class="ident">Store</span>, <span class="ident">configuration</span>: <span class="ident">Configuration</span>) -&gt; <span class="self">Self</span> {
<span class="self">Self</span> {
<span class="ident">storage_backend</span>: <span class="ident">Rc::new</span>(<span class="ident">store</span>),
<span class="ident">configuration</span>: <span class="ident">Rc::new</span>(<span class="ident">configuration</span>),
}
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">B</span>, <span class="ident">Store</span><span class="op">&gt;</span> <span class="ident">Transform</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">ServiceRequest</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">SessionMiddleware</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">S</span>: <span class="ident">Service</span><span class="op">&lt;</span><span class="ident">ServiceRequest</span>, <span class="ident">Response</span> <span class="op">=</span> <span class="ident">ServiceResponse</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>, <span class="ident">Error</span> <span class="op">=</span> <span class="ident">actix_web::Error</span><span class="op">&gt;</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
<span class="ident">S::Future</span>: <span class="lifetime">&#39;static</span>,
<span class="ident">B</span>: <span class="ident">MessageBody</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
<span class="ident">Store</span>: <span class="ident">SessionStore</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
{
<span class="kw">type</span> <span class="ident">Response</span> <span class="op">=</span> <span class="ident">ServiceResponse</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>;
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">actix_web::Error</span>;
<span class="kw">type</span> <span class="ident">Transform</span> <span class="op">=</span> <span class="ident">InnerSessionMiddleware</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">Store</span><span class="op">&gt;</span>;
<span class="kw">type</span> <span class="ident">InitError</span> <span class="op">=</span> ();
<span class="kw">type</span> <span class="ident">Future</span> <span class="op">=</span> <span class="ident">Ready</span><span class="op">&lt;</span><span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident"><span class="self">Self</span>::Transform</span>, <span class="ident"><span class="self">Self</span>::InitError</span><span class="op">&gt;</span><span class="op">&gt;</span>;
<span class="kw">fn</span> <span class="ident">new_transform</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">service</span>: <span class="ident">S</span>) -&gt; <span class="ident"><span class="self">Self</span>::Future</span> {
<span class="ident">ready</span>(<span class="prelude-val">Ok</span>(<span class="ident">InnerSessionMiddleware</span> {
<span class="ident">service</span>: <span class="ident">Rc::new</span>(<span class="ident">service</span>),
<span class="ident">configuration</span>: <span class="ident">Rc::clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">configuration</span>),
<span class="ident">storage_backend</span>: <span class="ident">Rc::clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">storage_backend</span>),
}))
}
}
<span class="doccomment">/// Short-hand to create an `actix_web::Error` instance that will result in an `Internal Server</span>
<span class="doccomment">/// Error` response while preserving the error root cause (e.g. in logs).</span>
<span class="kw">fn</span> <span class="ident">e500</span><span class="op">&lt;</span><span class="ident">E</span>: <span class="ident">fmt::Debug</span> <span class="op">+</span> <span class="ident">fmt::Display</span> <span class="op">+</span> <span class="lifetime">&#39;static</span><span class="op">&gt;</span>(<span class="ident">err</span>: <span class="ident">E</span>) -&gt; <span class="ident">actix_web::Error</span> {
<span class="comment">// We do not use `actix_web::error::ErrorInternalServerError` because we do not want to</span>
<span class="comment">// leak internal implementation details to the caller.</span>
<span class="comment">//</span>
<span class="comment">// `actix_web::error::ErrorInternalServerError` includes the error Display representation</span>
<span class="comment">// as body of the error responses, leading to messages like &quot;There was an issue persisting</span>
<span class="comment">// the session state&quot; reaching API clients. We don&#39;t want that, we want opaque 500s.</span>
<span class="ident">actix_web::error::InternalError::from_response</span>(
<span class="ident">err</span>,
<span class="ident">HttpResponse::InternalServerError</span>().<span class="ident">finish</span>(),
)
.<span class="ident">into</span>()
}
<span class="attribute">#[<span class="ident">doc</span>(<span class="ident">hidden</span>)]</span>
<span class="attribute">#[<span class="ident">non_exhaustive</span>]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">InnerSessionMiddleware</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">Store</span>: <span class="ident">SessionStore</span> <span class="op">+</span> <span class="lifetime">&#39;static</span><span class="op">&gt;</span> {
<span class="ident">service</span>: <span class="ident">Rc</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>,
<span class="ident">configuration</span>: <span class="ident">Rc</span><span class="op">&lt;</span><span class="ident">Configuration</span><span class="op">&gt;</span>,
<span class="ident">storage_backend</span>: <span class="ident">Rc</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">B</span>, <span class="ident">Store</span><span class="op">&gt;</span> <span class="ident">Service</span><span class="op">&lt;</span><span class="ident">ServiceRequest</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">InnerSessionMiddleware</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">Store</span><span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">S</span>: <span class="ident">Service</span><span class="op">&lt;</span><span class="ident">ServiceRequest</span>, <span class="ident">Response</span> <span class="op">=</span> <span class="ident">ServiceResponse</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>, <span class="ident">Error</span> <span class="op">=</span> <span class="ident">actix_web::Error</span><span class="op">&gt;</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
<span class="ident">S::Future</span>: <span class="lifetime">&#39;static</span>,
<span class="ident">Store</span>: <span class="ident">SessionStore</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
{
<span class="kw">type</span> <span class="ident">Response</span> <span class="op">=</span> <span class="ident">ServiceResponse</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>;
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">actix_web::Error</span>;
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::type_complexity</span>)]</span>
<span class="kw">type</span> <span class="ident">Future</span> <span class="op">=</span> <span class="ident">Pin</span><span class="op">&lt;</span><span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Future</span><span class="op">&lt;</span><span class="ident">Output</span> <span class="op">=</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident"><span class="self">Self</span>::Response</span>, <span class="ident"><span class="self">Self</span>::Error</span><span class="op">&gt;</span><span class="op">&gt;</span><span class="op">&gt;</span><span class="op">&gt;</span>;
<span class="macro">forward_ready!</span>(<span class="ident">service</span>);
<span class="kw">fn</span> <span class="ident">call</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw-2">mut</span> <span class="ident">req</span>: <span class="ident">ServiceRequest</span>) -&gt; <span class="ident"><span class="self">Self</span>::Future</span> {
<span class="kw">let</span> <span class="ident">service</span> <span class="op">=</span> <span class="ident">Rc::clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">service</span>);
<span class="kw">let</span> <span class="ident">storage_backend</span> <span class="op">=</span> <span class="ident">Rc::clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">storage_backend</span>);
<span class="kw">let</span> <span class="ident">configuration</span> <span class="op">=</span> <span class="ident">Rc::clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">configuration</span>);
<span class="ident">Box::pin</span>(<span class="kw">async</span> <span class="kw">move</span> {
<span class="kw">let</span> <span class="ident">session_key</span> <span class="op">=</span> <span class="ident">extract_session_key</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>, <span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>);
<span class="kw">let</span> (<span class="ident">session_key</span>, <span class="ident">session_state</span>) <span class="op">=</span>
<span class="ident">load_session_state</span>(<span class="ident">session_key</span>, <span class="ident">storage_backend</span>.<span class="ident">as_ref</span>()).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">Session::set_session</span>(<span class="kw-2">&amp;mut</span> <span class="ident">req</span>, <span class="ident">session_state</span>);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">service</span>.<span class="ident">call</span>(<span class="ident">req</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> (<span class="ident">status</span>, <span class="ident">session_state</span>) <span class="op">=</span> <span class="ident">Session::get_changes</span>(<span class="kw-2">&amp;mut</span> <span class="ident">res</span>);
<span class="kw">match</span> <span class="ident">session_key</span> {
<span class="prelude-val">None</span> =&gt; {
<span class="comment">// we do not create an entry in the session store if there is no state attached</span>
<span class="comment">// to a fresh session</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">session_state</span>.<span class="ident">is_empty</span>() {
<span class="kw">let</span> <span class="ident">session_key</span> <span class="op">=</span> <span class="ident">storage_backend</span>
.<span class="ident">save</span>(<span class="ident">session_state</span>, <span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="ident">set_session_cookie</span>(
<span class="ident">res</span>.<span class="ident">response_mut</span>().<span class="ident">head_mut</span>(),
<span class="ident">session_key</span>,
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>,
)
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
}
}
<span class="prelude-val">Some</span>(<span class="ident">session_key</span>) =&gt; {
<span class="kw">match</span> <span class="ident">status</span> {
<span class="ident">SessionStatus::Changed</span> =&gt; {
<span class="kw">let</span> <span class="ident">session_key</span> <span class="op">=</span> <span class="ident">storage_backend</span>
.<span class="ident">update</span>(
<span class="ident">session_key</span>,
<span class="ident">session_state</span>,
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span>,
)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="ident">set_session_cookie</span>(
<span class="ident">res</span>.<span class="ident">response_mut</span>().<span class="ident">head_mut</span>(),
<span class="ident">session_key</span>,
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>,
)
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
}
<span class="ident">SessionStatus::Purged</span> =&gt; {
<span class="ident">storage_backend</span>.<span class="ident">delete</span>(<span class="kw-2">&amp;</span><span class="ident">session_key</span>).<span class="kw">await</span>.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="ident">delete_session_cookie</span>(
<span class="ident">res</span>.<span class="ident">response_mut</span>().<span class="ident">head_mut</span>(),
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>,
)
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
}
<span class="ident">SessionStatus::Renewed</span> =&gt; {
<span class="ident">storage_backend</span>.<span class="ident">delete</span>(<span class="kw-2">&amp;</span><span class="ident">session_key</span>).<span class="kw">await</span>.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">session_key</span> <span class="op">=</span> <span class="ident">storage_backend</span>
.<span class="ident">save</span>(<span class="ident">session_state</span>, <span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="ident">set_session_cookie</span>(
<span class="ident">res</span>.<span class="ident">response_mut</span>().<span class="ident">head_mut</span>(),
<span class="ident">session_key</span>,
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>,
)
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
}
<span class="ident">SessionStatus::Unchanged</span> =&gt; {
<span class="kw">if</span> <span class="macro">matches!</span>(
<span class="ident">configuration</span>.<span class="ident">ttl_extension_policy</span>,
<span class="ident">TtlExtensionPolicy::OnEveryRequest</span>
) {
<span class="ident">storage_backend</span>
.<span class="ident">update_ttl</span>(<span class="kw-2">&amp;</span><span class="ident">session_key</span>, <span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">max_age</span>.<span class="ident">is_some</span>() {
<span class="ident">set_session_cookie</span>(
<span class="ident">res</span>.<span class="ident">response_mut</span>().<span class="ident">head_mut</span>(),
<span class="ident">session_key</span>,
<span class="kw-2">&amp;</span><span class="ident">configuration</span>.<span class="ident">cookie</span>,
)
.<span class="ident">map_err</span>(<span class="ident">e500</span>)<span class="question-mark">?</span>;
}
}
}
};
}
}
<span class="prelude-val">Ok</span>(<span class="ident">res</span>)
})
}
}
<span class="doccomment">/// Examines the session cookie attached to the incoming request, if there is one, and tries</span>
<span class="doccomment">/// to extract the session key.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// It returns `None` if there is no session cookie or if the session cookie is considered invalid</span>
<span class="doccomment">/// (e.g., when failing a signature check).</span>
<span class="kw">fn</span> <span class="ident">extract_session_key</span>(<span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">ServiceRequest</span>, <span class="ident">config</span>: <span class="kw-2">&amp;</span><span class="ident">CookieConfiguration</span>) -&gt; <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">SessionKey</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="ident">req</span>.<span class="ident">cookies</span>().<span class="ident">ok</span>()<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">session_cookie</span> <span class="op">=</span> <span class="ident">cookies</span>
.<span class="ident">iter</span>()
.<span class="ident">find</span>(<span class="op">|</span><span class="kw-2">&amp;</span><span class="ident">cookie</span><span class="op">|</span> <span class="ident">cookie</span>.<span class="ident">name</span>() <span class="op">==</span> <span class="ident">config</span>.<span class="ident">name</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">jar</span> <span class="op">=</span> <span class="ident">CookieJar::new</span>();
<span class="ident">jar</span>.<span class="ident">add_original</span>(<span class="ident">session_cookie</span>.<span class="ident">clone</span>());
<span class="kw">let</span> <span class="ident">verification_result</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">config</span>.<span class="ident">content_security</span> {
<span class="ident">CookieContentSecurity::Signed</span> =&gt; <span class="ident">jar</span>.<span class="ident">signed</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">key</span>).<span class="ident">get</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">name</span>),
<span class="ident">CookieContentSecurity::Private</span> =&gt; <span class="ident">jar</span>.<span class="ident">private</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">key</span>).<span class="ident">get</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">name</span>),
};
<span class="kw">if</span> <span class="ident">verification_result</span>.<span class="ident">is_none</span>() {
<span class="macro">tracing::warn!</span>(
<span class="string">&quot;The session cookie attached to the incoming request failed to pass cryptographic \
checks (signature verification/decryption).&quot;</span>
);
}
<span class="kw">match</span> <span class="ident">verification_result</span><span class="question-mark">?</span>.<span class="ident">value</span>().<span class="ident">to_owned</span>().<span class="ident">try_into</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">session_key</span>) =&gt; <span class="prelude-val">Some</span>(<span class="ident">session_key</span>),
<span class="prelude-val">Err</span>(<span class="ident">err</span>) =&gt; {
<span class="macro">tracing::warn!</span>(
<span class="ident">error</span>.<span class="ident">message</span> <span class="op">=</span> <span class="op">%</span><span class="ident">err</span>,
<span class="ident">error</span>.<span class="ident">cause_chain</span> <span class="op">=</span> <span class="question-mark">?</span><span class="ident">err</span>,
<span class="string">&quot;Invalid session key, ignoring.&quot;</span>
);
<span class="prelude-val">None</span>
}
}
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">load_session_state</span><span class="op">&lt;</span><span class="ident">Store</span>: <span class="ident">SessionStore</span><span class="op">&gt;</span>(
<span class="ident">session_key</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">SessionKey</span><span class="op">&gt;</span>,
<span class="ident">storage_backend</span>: <span class="kw-2">&amp;</span><span class="ident">Store</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(<span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">SessionKey</span><span class="op">&gt;</span>, <span class="ident">HashMap</span><span class="op">&lt;</span><span class="ident">String</span>, <span class="ident">String</span><span class="op">&gt;</span>), <span class="ident">actix_web::Error</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">session_key</span>) <span class="op">=</span> <span class="ident">session_key</span> {
<span class="kw">match</span> <span class="ident">storage_backend</span>.<span class="ident">load</span>(<span class="kw-2">&amp;</span><span class="ident">session_key</span>).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="ident">state</span>) =&gt; {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">state</span>) <span class="op">=</span> <span class="ident">state</span> {
<span class="prelude-val">Ok</span>((<span class="prelude-val">Some</span>(<span class="ident">session_key</span>), <span class="ident">state</span>))
} <span class="kw">else</span> {
<span class="comment">// We discard the existing session key given that the state attached to it can</span>
<span class="comment">// no longer be found (e.g. it expired or we suffered some data loss in the</span>
<span class="comment">// storage). Regenerating the session key will trigger the `save` workflow</span>
<span class="comment">// instead of the `update` workflow if the session state is modified during the</span>
<span class="comment">// lifecycle of the current request.</span>
<span class="macro">tracing::info!</span>(
<span class="string">&quot;No session state has been found for a valid session key, creating a new \
empty session.&quot;</span>
);
<span class="prelude-val">Ok</span>((<span class="prelude-val">None</span>, <span class="ident">HashMap::new</span>()))
}
}
<span class="prelude-val">Err</span>(<span class="ident">err</span>) =&gt; <span class="kw">match</span> <span class="ident">err</span> {
<span class="ident">LoadError::Deserialization</span>(<span class="ident">err</span>) =&gt; {
<span class="macro">tracing::warn!</span>(
<span class="ident">error</span>.<span class="ident">message</span> <span class="op">=</span> <span class="op">%</span><span class="ident">err</span>,
<span class="ident">error</span>.<span class="ident">cause_chain</span> <span class="op">=</span> <span class="question-mark">?</span><span class="ident">err</span>,
<span class="string">&quot;Invalid session state, creating a new empty session.&quot;</span>
);
<span class="prelude-val">Ok</span>((<span class="prelude-val">Some</span>(<span class="ident">session_key</span>), <span class="ident">HashMap::new</span>()))
}
<span class="ident">LoadError::Other</span>(<span class="ident">err</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">e500</span>(<span class="ident">err</span>)),
},
}
} <span class="kw">else</span> {
<span class="prelude-val">Ok</span>((<span class="prelude-val">None</span>, <span class="ident">HashMap::new</span>()))
}
}
<span class="kw">fn</span> <span class="ident">set_session_cookie</span>(
<span class="ident">response</span>: <span class="kw-2">&amp;mut</span> <span class="ident">ResponseHead</span>,
<span class="ident">session_key</span>: <span class="ident">SessionKey</span>,
<span class="ident">config</span>: <span class="kw-2">&amp;</span><span class="ident">CookieConfiguration</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(), <span class="ident">anyhow::Error</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">value</span>: <span class="ident">String</span> <span class="op">=</span> <span class="ident">session_key</span>.<span class="ident">into</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">cookie</span> <span class="op">=</span> <span class="ident">Cookie::new</span>(<span class="ident">config</span>.<span class="ident">name</span>.<span class="ident">clone</span>(), <span class="ident">value</span>);
<span class="ident">cookie</span>.<span class="ident">set_secure</span>(<span class="ident">config</span>.<span class="ident">secure</span>);
<span class="ident">cookie</span>.<span class="ident">set_http_only</span>(<span class="ident">config</span>.<span class="ident">http_only</span>);
<span class="ident">cookie</span>.<span class="ident">set_same_site</span>(<span class="ident">config</span>.<span class="ident">same_site</span>);
<span class="ident">cookie</span>.<span class="ident">set_path</span>(<span class="ident">config</span>.<span class="ident">path</span>.<span class="ident">clone</span>());
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">max_age</span>) <span class="op">=</span> <span class="ident">config</span>.<span class="ident">max_age</span> {
<span class="ident">cookie</span>.<span class="ident">set_max_age</span>(<span class="ident">max_age</span>);
}
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="kw-2">ref</span> <span class="ident">domain</span>) <span class="op">=</span> <span class="ident">config</span>.<span class="ident">domain</span> {
<span class="ident">cookie</span>.<span class="ident">set_domain</span>(<span class="ident">domain</span>.<span class="ident">clone</span>());
}
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">jar</span> <span class="op">=</span> <span class="ident">CookieJar::new</span>();
<span class="kw">match</span> <span class="ident">config</span>.<span class="ident">content_security</span> {
<span class="ident">CookieContentSecurity::Signed</span> =&gt; <span class="ident">jar</span>.<span class="ident">signed_mut</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">key</span>).<span class="ident">add</span>(<span class="ident">cookie</span>),
<span class="ident">CookieContentSecurity::Private</span> =&gt; <span class="ident">jar</span>.<span class="ident">private_mut</span>(<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">key</span>).<span class="ident">add</span>(<span class="ident">cookie</span>),
}
<span class="comment">// set cookie</span>
<span class="kw">let</span> <span class="ident">cookie</span> <span class="op">=</span> <span class="ident">jar</span>.<span class="ident">delta</span>().<span class="ident">next</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">val</span> <span class="op">=</span> <span class="ident">HeaderValue::from_str</span>(<span class="kw-2">&amp;</span><span class="ident">cookie</span>.<span class="ident">encoded</span>().<span class="ident">to_string</span>())
.<span class="ident">context</span>(<span class="string">&quot;Failed to attach a session cookie to the outgoing response&quot;</span>)<span class="question-mark">?</span>;
<span class="ident">response</span>.<span class="ident">headers_mut</span>().<span class="ident">append</span>(<span class="ident">SET_COOKIE</span>, <span class="ident">val</span>);
<span class="prelude-val">Ok</span>(())
}
<span class="kw">fn</span> <span class="ident">delete_session_cookie</span>(
<span class="ident">response</span>: <span class="kw-2">&amp;mut</span> <span class="ident">ResponseHead</span>,
<span class="ident">config</span>: <span class="kw-2">&amp;</span><span class="ident">CookieConfiguration</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(), <span class="ident">anyhow::Error</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">removal_cookie</span> <span class="op">=</span> <span class="ident">Cookie::build</span>(<span class="ident">config</span>.<span class="ident">name</span>.<span class="ident">clone</span>(), <span class="string">&quot;&quot;</span>)
.<span class="ident">path</span>(<span class="ident">config</span>.<span class="ident">path</span>.<span class="ident">clone</span>())
.<span class="ident">http_only</span>(<span class="ident">config</span>.<span class="ident">http_only</span>);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">removal_cookie</span> <span class="op">=</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="kw-2">ref</span> <span class="ident">domain</span>) <span class="op">=</span> <span class="ident">config</span>.<span class="ident">domain</span> {
<span class="ident">removal_cookie</span>.<span class="ident">domain</span>(<span class="ident">domain</span>)
} <span class="kw">else</span> {
<span class="ident">removal_cookie</span>
}
.<span class="ident">finish</span>();
<span class="ident">removal_cookie</span>.<span class="ident">make_removal</span>();
<span class="kw">let</span> <span class="ident">val</span> <span class="op">=</span> <span class="ident">HeaderValue::from_str</span>(<span class="kw-2">&amp;</span><span class="ident">removal_cookie</span>.<span class="ident">to_string</span>())
.<span class="ident">context</span>(<span class="string">&quot;Failed to attach a session removal cookie to the outgoing response&quot;</span>)<span class="question-mark">?</span>;
<span class="ident">response</span>.<span class="ident">headers_mut</span>().<span class="ident">append</span>(<span class="ident">SET_COOKIE</span>, <span class="ident">val</span>);
<span class="prelude-val">Ok</span>(())
}
</code></pre></div>
</section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="actix_session" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.64.0-nightly (c396bb3b8 2022-07-10)" ></div>
</body></html>