1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-03-13 00:52:50 +01:00
actix-extras/src/actix_session/middleware.rs.html

1331 lines
83 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"><button type="button" id="help-button" title="help">?</button><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>
<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>
<span id="477">477</span>
<span id="478">478</span>
<span id="479">479</span>
<span id="480">480</span>
<span id="481">481</span>
<span id="482">482</span>
<span id="483">483</span>
<span id="484">484</span>
<span id="485">485</span>
<span id="486">486</span>
<span id="487">487</span>
<span id="488">488</span>
<span id="489">489</span>
<span id="490">490</span>
<span id="491">491</span>
<span id="492">492</span>
<span id="493">493</span>
<span id="494">494</span>
<span id="495">495</span>
<span id="496">496</span>
<span id="497">497</span>
<span id="498">498</span>
<span id="499">499</span>
<span id="500">500</span>
<span id="501">501</span>
<span id="502">502</span>
<span id="503">503</span>
<span id="504">504</span>
<span id="505">505</span>
<span id="506">506</span>
<span id="507">507</span>
<span id="508">508</span>
<span id="509">509</span>
<span id="510">510</span>
<span id="511">511</span>
<span id="512">512</span>
<span id="513">513</span>
<span id="514">514</span>
<span id="515">515</span>
<span id="516">516</span>
<span id="517">517</span>
<span id="518">518</span>
<span id="519">519</span>
<span id="520">520</span>
<span id="521">521</span>
<span id="522">522</span>
<span id="523">523</span>
<span id="524">524</span>
<span id="525">525</span>
<span id="526">526</span>
<span id="527">527</span>
<span id="528">528</span>
<span id="529">529</span>
<span id="530">530</span>
<span id="531">531</span>
<span id="532">532</span>
<span id="533">533</span>
<span id="534">534</span>
<span id="535">535</span>
<span id="536">536</span>
<span id="537">537</span>
<span id="538">538</span>
<span id="539">539</span>
<span id="540">540</span>
<span id="541">541</span>
<span id="542">542</span>
<span id="543">543</span>
<span id="544">544</span>
<span id="545">545</span>
<span id="546">546</span>
<span id="547">547</span>
<span id="548">548</span>
<span id="549">549</span>
<span id="550">550</span>
<span id="551">551</span>
<span id="552">552</span>
<span id="553">553</span>
<span id="554">554</span>
<span id="555">555</span>
<span id="556">556</span>
<span id="557">557</span>
<span id="558">558</span>
<span id="559">559</span>
<span id="560">560</span>
<span id="561">561</span>
<span id="562">562</span>
<span id="563">563</span>
<span id="564">564</span>
<span id="565">565</span>
<span id="566">566</span>
<span id="567">567</span>
<span id="568">568</span>
<span id="569">569</span>
<span id="570">570</span>
<span id="571">571</span>
<span id="572">572</span>
<span id="573">573</span>
<span id="574">574</span>
<span id="575">575</span>
<span id="576">576</span>
<span id="577">577</span>
<span id="578">578</span>
<span id="579">579</span>
<span id="580">580</span>
<span id="581">581</span>
<span id="582">582</span>
<span id="583">583</span>
<span id="584">584</span>
<span id="585">585</span>
<span id="586">586</span>
<span id="587">587</span>
<span id="588">588</span>
<span id="589">589</span>
<span id="590">590</span>
<span id="591">591</span>
<span id="592">592</span>
<span id="593">593</span>
<span id="594">594</span>
<span id="595">595</span>
<span id="596">596</span>
<span id="597">597</span>
<span id="598">598</span>
<span id="599">599</span>
<span id="600">600</span>
<span id="601">601</span>
<span id="602">602</span>
<span id="603">603</span>
<span id="604">604</span>
<span id="605">605</span>
<span id="606">606</span>
<span id="607">607</span>
<span id="608">608</span>
<span id="609">609</span>
<span id="610">610</span>
<span id="611">611</span>
<span id="612">612</span>
<span id="613">613</span>
<span id="614">614</span>
<span id="615">615</span>
<span id="616">616</span>
<span id="617">617</span>
<span id="618">618</span>
<span id="619">619</span>
<span id="620">620</span>
<span id="621">621</span>
<span id="622">622</span>
<span id="623">623</span>
<span id="624">624</span>
<span id="625">625</span>
<span id="626">626</span>
<span id="627">627</span>
<span id="628">628</span>
<span id="629">629</span>
<span id="630">630</span>
<span id="631">631</span>
<span id="632">632</span>
<span id="633">633</span>
<span id="634">634</span>
<span id="635">635</span>
<span id="636">636</span>
<span id="637">637</span>
<span id="638">638</span>
<span id="639">639</span>
<span id="640">640</span>
<span id="641">641</span>
<span id="642">642</span>
<span id="643">643</span>
<span id="644">644</span>
<span id="645">645</span>
<span id="646">646</span>
<span id="647">647</span>
<span id="648">648</span>
<span id="649">649</span>
<span id="650">650</span>
<span id="651">651</span>
<span id="652">652</span>
<span id="653">653</span>
<span id="654">654</span>
<span id="655">655</span>
<span id="656">656</span>
<span id="657">657</span>
<span id="658">658</span>
<span id="659">659</span>
<span id="660">660</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">SameSite</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="ident">time::Duration</span>;
<span class="kw">use</span> <span class="kw">crate</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::{cookie::Key, web, App, HttpServer, HttpResponse, Error};</span>
<span class="doccomment">/// use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore, SessionLength};</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_length(SessionLength::Predetermined {</span>
<span class="doccomment">/// max_session_length: Some(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="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">Configuration</span> {
<span class="ident">cookie</span>: <span class="ident">CookieConfiguration</span>,
<span class="ident">session</span>: <span class="ident">SessionConfiguration</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">SessionConfiguration</span> {
<span class="ident">state_ttl</span>: <span class="ident">Duration</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">CookieConfiguration</span> {
<span class="ident">secure</span>: <span class="ident">bool</span>,
<span class="ident">http_only</span>: <span class="ident">bool</span>,
<span class="ident">name</span>: <span class="ident">String</span>,
<span class="ident">same_site</span>: <span class="ident">SameSite</span>,
<span class="ident">path</span>: <span class="ident">String</span>,
<span class="ident">domain</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
<span class="ident">max_age</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Duration</span><span class="op">&gt;</span>,
<span class="ident">content_security</span>: <span class="ident">CookieContentSecurity</span>,
<span class="ident">key</span>: <span class="ident">Key</span>,
}
<span class="doccomment">/// Describes how long a session should last.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Used by [`SessionMiddlewareBuilder::session_length`].</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">SessionLength</span> {
<span class="doccomment">/// The session cookie will expire when the current browser session ends.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// When does a browser session end? It depends on the browser! Chrome, for example, will often</span>
<span class="doccomment">/// continue running in the background when the browser is closed—session cookies are not</span>
<span class="doccomment">/// deleted and they will still be available when the browser is opened again. Check the</span>
<span class="doccomment">/// documentation of the browsers you are targeting for up-to-date information.</span>
<span class="ident">BrowserSession</span> {
<span class="doccomment">/// We must provide a time-to-live (TTL) when storing the session state in the storage</span>
<span class="doccomment">/// backend—we do not want to store session states indefinitely, otherwise we will</span>
<span class="doccomment">/// inevitably run out of storage by holding on to the state of countless abandoned or</span>
<span class="doccomment">/// expired sessions!</span>
<span class="doccomment">///</span>
<span class="doccomment">/// We are dealing with the lifecycle of two uncorrelated object here: the session cookie</span>
<span class="doccomment">/// and the session state. It is not a big issue if the session state outlives the cookie—</span>
<span class="doccomment">/// we are wasting some space in the backend storage, but it will be cleaned up eventually.</span>
<span class="doccomment">/// What happens, instead, if the cookie outlives the session state? A new session starts—</span>
<span class="doccomment">/// e.g. if sessions are being used for authentication, the user is de-facto logged out.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// It is not possible to predict with certainty how long a browser session is going to</span>
<span class="doccomment">/// last—you need to provide a reasonable upper bound. You do so via `state_ttl`—it dictates</span>
<span class="doccomment">/// what TTL should be used for session state when the lifecycle of the session cookie is</span>
<span class="doccomment">/// tied to the browser session length. [`SessionMiddleware`] will default to 1 day if</span>
<span class="doccomment">/// `state_ttl` is left unspecified.</span>
<span class="ident">state_ttl</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Duration</span><span class="op">&gt;</span>,
},
<span class="doccomment">/// The session cookie will be a [persistent cookie].</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Persistent cookies have a pre-determined lifetime, specified via the `Max-Age` or `Expires`</span>
<span class="doccomment">/// attribute. They do not disappear when the current browser session ends.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// [persistent cookie]: https://www.whitehatsec.com/glossary/content/persistent-session-cookie</span>
<span class="ident">Predetermined</span> {
<span class="doccomment">/// Set `max_session_length` to specify how long the session cookie should live.</span>
<span class="doccomment">/// [`SessionMiddleware`] will default to 1 day if `max_session_length` is set to `None`.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// `max_session_length` is also used as the TTL for the session state in the</span>
<span class="doccomment">/// storage backend.</span>
<span class="ident">max_session_length</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Duration</span><span class="op">&gt;</span>,
},
}
<span class="doccomment">/// Used by [`SessionMiddlewareBuilder::cookie_content_security`] to determine how to secure</span>
<span class="doccomment">/// the content of the session cookie.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Copy</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">CookieContentSecurity</span> {
<span class="doccomment">/// The cookie content is encrypted when using `CookieContentSecurity::Private`.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Encryption guarantees confidentiality and integrity: the client cannot tamper with the</span>
<span class="doccomment">/// cookie content nor decode it, as long as the encryption key remains confidential.</span>
<span class="ident">Private</span>,
<span class="doccomment">/// The cookie content is signed when using `CookieContentSecurity::Signed`.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Signing guarantees integrity, but it doesn&#39;t ensure confidentiality: the client cannot</span>
<span class="doccomment">/// tamper with the cookie content, but they can read it.</span>
<span class="ident">Signed</span>,
}
<span class="kw">fn</span> <span class="ident">default_configuration</span>(<span class="ident">key</span>: <span class="ident">Key</span>) -&gt; <span class="ident">Configuration</span> {
<span class="ident">Configuration</span> {
<span class="ident">cookie</span>: <span class="ident">CookieConfiguration</span> {
<span class="ident">secure</span>: <span class="bool-val">true</span>,
<span class="ident">http_only</span>: <span class="bool-val">true</span>,
<span class="ident">name</span>: <span class="string">&quot;id&quot;</span>.<span class="ident">into</span>(),
<span class="ident">same_site</span>: <span class="ident">SameSite::Lax</span>,
<span class="ident">path</span>: <span class="string">&quot;/&quot;</span>.<span class="ident">into</span>(),
<span class="ident">domain</span>: <span class="prelude-val">None</span>,
<span class="ident">max_age</span>: <span class="prelude-val">None</span>,
<span class="ident">content_security</span>: <span class="ident">CookieContentSecurity::Private</span>,
<span class="ident">key</span>,
},
<span class="ident">session</span>: <span class="ident">SessionConfiguration</span> {
<span class="ident">state_ttl</span>: <span class="ident">default_ttl</span>(),
},
}
}
<span class="kw">fn</span> <span class="ident">default_ttl</span>() -&gt; <span class="ident">Duration</span> {
<span class="ident">Duration::days</span>(<span class="number">1</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="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">default_configuration</span>(<span class="ident">key</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</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">default_configuration</span>(<span class="ident">key</span>),
}
}
}
<span class="doccomment">/// A fluent builder to construct a [`SessionMiddleware`] instance with custom configuration</span>
<span class="doccomment">/// parameters.</span>
<span class="attribute">#[<span class="ident">must_use</span>]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">SessionMiddlewareBuilder</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">Configuration</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">SessionMiddlewareBuilder</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span> {
<span class="doccomment">/// Set the name of the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Defaults to `id`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_name</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">name</span>: <span class="ident">String</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">name</span> <span class="op">=</span> <span class="ident">name</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the `Secure` attribute for the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// If the cookie is set as secure, it will only be transmitted when the connection is secure</span>
<span class="doccomment">/// (using `https`).</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Default is `true`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_secure</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">secure</span>: <span class="ident">bool</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">secure</span> <span class="op">=</span> <span class="ident">secure</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Determine how long a session should last - check out [`SessionLength`]&#39;s documentation for</span>
<span class="doccomment">/// more details on the available options.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Default is [`SessionLength::BrowserSession`].</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">session_length</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">session_length</span>: <span class="ident">SessionLength</span>) -&gt; <span class="self">Self</span> {
<span class="kw">match</span> <span class="ident">session_length</span> {
<span class="ident">SessionLength::BrowserSession</span> { <span class="ident">state_ttl</span> } =&gt; {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">max_age</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span> <span class="op">=</span> <span class="ident">state_ttl</span>.<span class="ident">unwrap_or_else</span>(<span class="ident">default_ttl</span>);
}
<span class="ident">SessionLength::Predetermined</span> { <span class="ident">max_session_length</span> } =&gt; {
<span class="kw">let</span> <span class="ident">ttl</span> <span class="op">=</span> <span class="ident">max_session_length</span>.<span class="ident">unwrap_or_else</span>(<span class="ident">default_ttl</span>);
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">max_age</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">ttl</span>);
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">session</span>.<span class="ident">state_ttl</span> <span class="op">=</span> <span class="ident">ttl</span>;
}
}
<span class="self">self</span>
}
<span class="doccomment">/// Set the `SameSite` attribute for the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// By default, the attribute is set to `Lax`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_same_site</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">same_site</span>: <span class="ident">SameSite</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">same_site</span> <span class="op">=</span> <span class="ident">same_site</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the `Path` attribute for the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// By default, the attribute is set to `/`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_path</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">path</span>: <span class="ident">String</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">path</span> <span class="op">=</span> <span class="ident">path</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the `Domain` attribute for the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Use `None` to leave the attribute unspecified. If unspecified, the attribute defaults</span>
<span class="doccomment">/// to the same host that set the cookie, excluding subdomains.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// By default, the attribute is left unspecified.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_domain</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">domain</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">domain</span> <span class="op">=</span> <span class="ident">domain</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Choose how the session cookie content should be secured.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// - [`CookieContentSecurity::Private`] selects encrypted cookie content.</span>
<span class="doccomment">/// - [`CookieContentSecurity::Signed`] selects signed cookie content.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Default</span>
<span class="doccomment">/// By default, the cookie content is encrypted. Encrypted was chosen instead of signed as</span>
<span class="doccomment">/// default because it reduces the chances of sensitive information being exposed in the session</span>
<span class="doccomment">/// key by accident, regardless of [`SessionStore`] implementation you chose to use.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// For example, if you are using cookie-based storage, you definitely want the cookie content</span>
<span class="doccomment">/// to be encrypted—the whole session state is embedded in the cookie! If you are using</span>
<span class="doccomment">/// Redis-based storage, signed is more than enough - the cookie content is just a unique</span>
<span class="doccomment">/// tamper-proof session key.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_content_security</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">content_security</span>: <span class="ident">CookieContentSecurity</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">content_security</span> <span class="op">=</span> <span class="ident">content_security</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the `HttpOnly` attribute for the cookie used to store the session ID.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// If the cookie is set as `HttpOnly`, it will not be visible to any JavaScript snippets</span>
<span class="doccomment">/// running in the browser.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Default is `true`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">cookie_http_only</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">http_only</span>: <span class="ident">bool</span>) -&gt; <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">configuration</span>.<span class="ident">cookie</span>.<span class="ident">http_only</span> <span class="op">=</span> <span class="ident">http_only</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Finalise the builder and return a [`SessionMiddleware`] instance.</span>
<span class="attribute">#[<span class="ident">must_use</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">build</span>(<span class="self">self</span>) -&gt; <span class="ident">SessionMiddleware</span><span class="op">&lt;</span><span class="ident">Store</span><span class="op">&gt;</span> {
<span class="ident">SessionMiddleware</span> {
<span class="ident">storage_backend</span>: <span class="self">self</span>.<span class="ident">storage_backend</span>,
<span class="ident">configuration</span>: <span class="ident">Rc::new</span>(<span class="self">self</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="comment">// Nothing to do; we avoid the unnecessary call to the storage.</span>
}
}
}
};
<span class="prelude-val">Ok</span>(<span class="ident">res</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.63.0-nightly (dc80ca78b 2022-06-21)" ></div>
</body></html>