1
0
mirror of https://github.com/actix/actix-website synced 2024-11-30 19:14:36 +01:00
actix-website/static/api/actix-web/0.7.12/src/actix_web/fs.rs.html
2018-10-10 08:38:33 -07:00

3575 lines
235 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source to the Rust file `src/fs.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>fs.rs.html -- source</title><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../dark.css"><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script src="../../storage.js"></script></head><body class="rustdoc source"><!--[if lte IE 8]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu">&#9776;</div></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!"><img src="../../brush.svg" width="18" alt="Pick another theme!"></button><div id="theme-choices"></div></div><script src="../../theme.js"></script><nav class="sub"><form class="search-form js-only"><div class="search-container"><input class="search-input" name="search" autocomplete="off" placeholder="Click or press S to search, ? for more options…" type="search"><a id="settings-menu" href="../../settings.html"><img src="../../wheel.svg" width="18" alt="Change settings"></a></div></form></nav><section id="main" class="content"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10"> 10</span>
<span id="11"> 11</span>
<span id="12"> 12</span>
<span id="13"> 13</span>
<span id="14"> 14</span>
<span id="15"> 15</span>
<span id="16"> 16</span>
<span id="17"> 17</span>
<span id="18"> 18</span>
<span id="19"> 19</span>
<span id="20"> 20</span>
<span id="21"> 21</span>
<span id="22"> 22</span>
<span id="23"> 23</span>
<span id="24"> 24</span>
<span id="25"> 25</span>
<span id="26"> 26</span>
<span id="27"> 27</span>
<span id="28"> 28</span>
<span id="29"> 29</span>
<span id="30"> 30</span>
<span id="31"> 31</span>
<span id="32"> 32</span>
<span id="33"> 33</span>
<span id="34"> 34</span>
<span id="35"> 35</span>
<span id="36"> 36</span>
<span id="37"> 37</span>
<span id="38"> 38</span>
<span id="39"> 39</span>
<span id="40"> 40</span>
<span id="41"> 41</span>
<span id="42"> 42</span>
<span id="43"> 43</span>
<span id="44"> 44</span>
<span id="45"> 45</span>
<span id="46"> 46</span>
<span id="47"> 47</span>
<span id="48"> 48</span>
<span id="49"> 49</span>
<span id="50"> 50</span>
<span id="51"> 51</span>
<span id="52"> 52</span>
<span id="53"> 53</span>
<span id="54"> 54</span>
<span id="55"> 55</span>
<span id="56"> 56</span>
<span id="57"> 57</span>
<span id="58"> 58</span>
<span id="59"> 59</span>
<span id="60"> 60</span>
<span id="61"> 61</span>
<span id="62"> 62</span>
<span id="63"> 63</span>
<span id="64"> 64</span>
<span id="65"> 65</span>
<span id="66"> 66</span>
<span id="67"> 67</span>
<span id="68"> 68</span>
<span id="69"> 69</span>
<span id="70"> 70</span>
<span id="71"> 71</span>
<span id="72"> 72</span>
<span id="73"> 73</span>
<span id="74"> 74</span>
<span id="75"> 75</span>
<span id="76"> 76</span>
<span id="77"> 77</span>
<span id="78"> 78</span>
<span id="79"> 79</span>
<span id="80"> 80</span>
<span id="81"> 81</span>
<span id="82"> 82</span>
<span id="83"> 83</span>
<span id="84"> 84</span>
<span id="85"> 85</span>
<span id="86"> 86</span>
<span id="87"> 87</span>
<span id="88"> 88</span>
<span id="89"> 89</span>
<span id="90"> 90</span>
<span id="91"> 91</span>
<span id="92"> 92</span>
<span id="93"> 93</span>
<span id="94"> 94</span>
<span id="95"> 95</span>
<span id="96"> 96</span>
<span id="97"> 97</span>
<span id="98"> 98</span>
<span id="99"> 99</span>
<span id="100"> 100</span>
<span id="101"> 101</span>
<span id="102"> 102</span>
<span id="103"> 103</span>
<span id="104"> 104</span>
<span id="105"> 105</span>
<span id="106"> 106</span>
<span id="107"> 107</span>
<span id="108"> 108</span>
<span id="109"> 109</span>
<span id="110"> 110</span>
<span id="111"> 111</span>
<span id="112"> 112</span>
<span id="113"> 113</span>
<span id="114"> 114</span>
<span id="115"> 115</span>
<span id="116"> 116</span>
<span id="117"> 117</span>
<span id="118"> 118</span>
<span id="119"> 119</span>
<span id="120"> 120</span>
<span id="121"> 121</span>
<span id="122"> 122</span>
<span id="123"> 123</span>
<span id="124"> 124</span>
<span id="125"> 125</span>
<span id="126"> 126</span>
<span id="127"> 127</span>
<span id="128"> 128</span>
<span id="129"> 129</span>
<span id="130"> 130</span>
<span id="131"> 131</span>
<span id="132"> 132</span>
<span id="133"> 133</span>
<span id="134"> 134</span>
<span id="135"> 135</span>
<span id="136"> 136</span>
<span id="137"> 137</span>
<span id="138"> 138</span>
<span id="139"> 139</span>
<span id="140"> 140</span>
<span id="141"> 141</span>
<span id="142"> 142</span>
<span id="143"> 143</span>
<span id="144"> 144</span>
<span id="145"> 145</span>
<span id="146"> 146</span>
<span id="147"> 147</span>
<span id="148"> 148</span>
<span id="149"> 149</span>
<span id="150"> 150</span>
<span id="151"> 151</span>
<span id="152"> 152</span>
<span id="153"> 153</span>
<span id="154"> 154</span>
<span id="155"> 155</span>
<span id="156"> 156</span>
<span id="157"> 157</span>
<span id="158"> 158</span>
<span id="159"> 159</span>
<span id="160"> 160</span>
<span id="161"> 161</span>
<span id="162"> 162</span>
<span id="163"> 163</span>
<span id="164"> 164</span>
<span id="165"> 165</span>
<span id="166"> 166</span>
<span id="167"> 167</span>
<span id="168"> 168</span>
<span id="169"> 169</span>
<span id="170"> 170</span>
<span id="171"> 171</span>
<span id="172"> 172</span>
<span id="173"> 173</span>
<span id="174"> 174</span>
<span id="175"> 175</span>
<span id="176"> 176</span>
<span id="177"> 177</span>
<span id="178"> 178</span>
<span id="179"> 179</span>
<span id="180"> 180</span>
<span id="181"> 181</span>
<span id="182"> 182</span>
<span id="183"> 183</span>
<span id="184"> 184</span>
<span id="185"> 185</span>
<span id="186"> 186</span>
<span id="187"> 187</span>
<span id="188"> 188</span>
<span id="189"> 189</span>
<span id="190"> 190</span>
<span id="191"> 191</span>
<span id="192"> 192</span>
<span id="193"> 193</span>
<span id="194"> 194</span>
<span id="195"> 195</span>
<span id="196"> 196</span>
<span id="197"> 197</span>
<span id="198"> 198</span>
<span id="199"> 199</span>
<span id="200"> 200</span>
<span id="201"> 201</span>
<span id="202"> 202</span>
<span id="203"> 203</span>
<span id="204"> 204</span>
<span id="205"> 205</span>
<span id="206"> 206</span>
<span id="207"> 207</span>
<span id="208"> 208</span>
<span id="209"> 209</span>
<span id="210"> 210</span>
<span id="211"> 211</span>
<span id="212"> 212</span>
<span id="213"> 213</span>
<span id="214"> 214</span>
<span id="215"> 215</span>
<span id="216"> 216</span>
<span id="217"> 217</span>
<span id="218"> 218</span>
<span id="219"> 219</span>
<span id="220"> 220</span>
<span id="221"> 221</span>
<span id="222"> 222</span>
<span id="223"> 223</span>
<span id="224"> 224</span>
<span id="225"> 225</span>
<span id="226"> 226</span>
<span id="227"> 227</span>
<span id="228"> 228</span>
<span id="229"> 229</span>
<span id="230"> 230</span>
<span id="231"> 231</span>
<span id="232"> 232</span>
<span id="233"> 233</span>
<span id="234"> 234</span>
<span id="235"> 235</span>
<span id="236"> 236</span>
<span id="237"> 237</span>
<span id="238"> 238</span>
<span id="239"> 239</span>
<span id="240"> 240</span>
<span id="241"> 241</span>
<span id="242"> 242</span>
<span id="243"> 243</span>
<span id="244"> 244</span>
<span id="245"> 245</span>
<span id="246"> 246</span>
<span id="247"> 247</span>
<span id="248"> 248</span>
<span id="249"> 249</span>
<span id="250"> 250</span>
<span id="251"> 251</span>
<span id="252"> 252</span>
<span id="253"> 253</span>
<span id="254"> 254</span>
<span id="255"> 255</span>
<span id="256"> 256</span>
<span id="257"> 257</span>
<span id="258"> 258</span>
<span id="259"> 259</span>
<span id="260"> 260</span>
<span id="261"> 261</span>
<span id="262"> 262</span>
<span id="263"> 263</span>
<span id="264"> 264</span>
<span id="265"> 265</span>
<span id="266"> 266</span>
<span id="267"> 267</span>
<span id="268"> 268</span>
<span id="269"> 269</span>
<span id="270"> 270</span>
<span id="271"> 271</span>
<span id="272"> 272</span>
<span id="273"> 273</span>
<span id="274"> 274</span>
<span id="275"> 275</span>
<span id="276"> 276</span>
<span id="277"> 277</span>
<span id="278"> 278</span>
<span id="279"> 279</span>
<span id="280"> 280</span>
<span id="281"> 281</span>
<span id="282"> 282</span>
<span id="283"> 283</span>
<span id="284"> 284</span>
<span id="285"> 285</span>
<span id="286"> 286</span>
<span id="287"> 287</span>
<span id="288"> 288</span>
<span id="289"> 289</span>
<span id="290"> 290</span>
<span id="291"> 291</span>
<span id="292"> 292</span>
<span id="293"> 293</span>
<span id="294"> 294</span>
<span id="295"> 295</span>
<span id="296"> 296</span>
<span id="297"> 297</span>
<span id="298"> 298</span>
<span id="299"> 299</span>
<span id="300"> 300</span>
<span id="301"> 301</span>
<span id="302"> 302</span>
<span id="303"> 303</span>
<span id="304"> 304</span>
<span id="305"> 305</span>
<span id="306"> 306</span>
<span id="307"> 307</span>
<span id="308"> 308</span>
<span id="309"> 309</span>
<span id="310"> 310</span>
<span id="311"> 311</span>
<span id="312"> 312</span>
<span id="313"> 313</span>
<span id="314"> 314</span>
<span id="315"> 315</span>
<span id="316"> 316</span>
<span id="317"> 317</span>
<span id="318"> 318</span>
<span id="319"> 319</span>
<span id="320"> 320</span>
<span id="321"> 321</span>
<span id="322"> 322</span>
<span id="323"> 323</span>
<span id="324"> 324</span>
<span id="325"> 325</span>
<span id="326"> 326</span>
<span id="327"> 327</span>
<span id="328"> 328</span>
<span id="329"> 329</span>
<span id="330"> 330</span>
<span id="331"> 331</span>
<span id="332"> 332</span>
<span id="333"> 333</span>
<span id="334"> 334</span>
<span id="335"> 335</span>
<span id="336"> 336</span>
<span id="337"> 337</span>
<span id="338"> 338</span>
<span id="339"> 339</span>
<span id="340"> 340</span>
<span id="341"> 341</span>
<span id="342"> 342</span>
<span id="343"> 343</span>
<span id="344"> 344</span>
<span id="345"> 345</span>
<span id="346"> 346</span>
<span id="347"> 347</span>
<span id="348"> 348</span>
<span id="349"> 349</span>
<span id="350"> 350</span>
<span id="351"> 351</span>
<span id="352"> 352</span>
<span id="353"> 353</span>
<span id="354"> 354</span>
<span id="355"> 355</span>
<span id="356"> 356</span>
<span id="357"> 357</span>
<span id="358"> 358</span>
<span id="359"> 359</span>
<span id="360"> 360</span>
<span id="361"> 361</span>
<span id="362"> 362</span>
<span id="363"> 363</span>
<span id="364"> 364</span>
<span id="365"> 365</span>
<span id="366"> 366</span>
<span id="367"> 367</span>
<span id="368"> 368</span>
<span id="369"> 369</span>
<span id="370"> 370</span>
<span id="371"> 371</span>
<span id="372"> 372</span>
<span id="373"> 373</span>
<span id="374"> 374</span>
<span id="375"> 375</span>
<span id="376"> 376</span>
<span id="377"> 377</span>
<span id="378"> 378</span>
<span id="379"> 379</span>
<span id="380"> 380</span>
<span id="381"> 381</span>
<span id="382"> 382</span>
<span id="383"> 383</span>
<span id="384"> 384</span>
<span id="385"> 385</span>
<span id="386"> 386</span>
<span id="387"> 387</span>
<span id="388"> 388</span>
<span id="389"> 389</span>
<span id="390"> 390</span>
<span id="391"> 391</span>
<span id="392"> 392</span>
<span id="393"> 393</span>
<span id="394"> 394</span>
<span id="395"> 395</span>
<span id="396"> 396</span>
<span id="397"> 397</span>
<span id="398"> 398</span>
<span id="399"> 399</span>
<span id="400"> 400</span>
<span id="401"> 401</span>
<span id="402"> 402</span>
<span id="403"> 403</span>
<span id="404"> 404</span>
<span id="405"> 405</span>
<span id="406"> 406</span>
<span id="407"> 407</span>
<span id="408"> 408</span>
<span id="409"> 409</span>
<span id="410"> 410</span>
<span id="411"> 411</span>
<span id="412"> 412</span>
<span id="413"> 413</span>
<span id="414"> 414</span>
<span id="415"> 415</span>
<span id="416"> 416</span>
<span id="417"> 417</span>
<span id="418"> 418</span>
<span id="419"> 419</span>
<span id="420"> 420</span>
<span id="421"> 421</span>
<span id="422"> 422</span>
<span id="423"> 423</span>
<span id="424"> 424</span>
<span id="425"> 425</span>
<span id="426"> 426</span>
<span id="427"> 427</span>
<span id="428"> 428</span>
<span id="429"> 429</span>
<span id="430"> 430</span>
<span id="431"> 431</span>
<span id="432"> 432</span>
<span id="433"> 433</span>
<span id="434"> 434</span>
<span id="435"> 435</span>
<span id="436"> 436</span>
<span id="437"> 437</span>
<span id="438"> 438</span>
<span id="439"> 439</span>
<span id="440"> 440</span>
<span id="441"> 441</span>
<span id="442"> 442</span>
<span id="443"> 443</span>
<span id="444"> 444</span>
<span id="445"> 445</span>
<span id="446"> 446</span>
<span id="447"> 447</span>
<span id="448"> 448</span>
<span id="449"> 449</span>
<span id="450"> 450</span>
<span id="451"> 451</span>
<span id="452"> 452</span>
<span id="453"> 453</span>
<span id="454"> 454</span>
<span id="455"> 455</span>
<span id="456"> 456</span>
<span id="457"> 457</span>
<span id="458"> 458</span>
<span id="459"> 459</span>
<span id="460"> 460</span>
<span id="461"> 461</span>
<span id="462"> 462</span>
<span id="463"> 463</span>
<span id="464"> 464</span>
<span id="465"> 465</span>
<span id="466"> 466</span>
<span id="467"> 467</span>
<span id="468"> 468</span>
<span id="469"> 469</span>
<span id="470"> 470</span>
<span id="471"> 471</span>
<span id="472"> 472</span>
<span id="473"> 473</span>
<span id="474"> 474</span>
<span id="475"> 475</span>
<span id="476"> 476</span>
<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>
<span id="661"> 661</span>
<span id="662"> 662</span>
<span id="663"> 663</span>
<span id="664"> 664</span>
<span id="665"> 665</span>
<span id="666"> 666</span>
<span id="667"> 667</span>
<span id="668"> 668</span>
<span id="669"> 669</span>
<span id="670"> 670</span>
<span id="671"> 671</span>
<span id="672"> 672</span>
<span id="673"> 673</span>
<span id="674"> 674</span>
<span id="675"> 675</span>
<span id="676"> 676</span>
<span id="677"> 677</span>
<span id="678"> 678</span>
<span id="679"> 679</span>
<span id="680"> 680</span>
<span id="681"> 681</span>
<span id="682"> 682</span>
<span id="683"> 683</span>
<span id="684"> 684</span>
<span id="685"> 685</span>
<span id="686"> 686</span>
<span id="687"> 687</span>
<span id="688"> 688</span>
<span id="689"> 689</span>
<span id="690"> 690</span>
<span id="691"> 691</span>
<span id="692"> 692</span>
<span id="693"> 693</span>
<span id="694"> 694</span>
<span id="695"> 695</span>
<span id="696"> 696</span>
<span id="697"> 697</span>
<span id="698"> 698</span>
<span id="699"> 699</span>
<span id="700"> 700</span>
<span id="701"> 701</span>
<span id="702"> 702</span>
<span id="703"> 703</span>
<span id="704"> 704</span>
<span id="705"> 705</span>
<span id="706"> 706</span>
<span id="707"> 707</span>
<span id="708"> 708</span>
<span id="709"> 709</span>
<span id="710"> 710</span>
<span id="711"> 711</span>
<span id="712"> 712</span>
<span id="713"> 713</span>
<span id="714"> 714</span>
<span id="715"> 715</span>
<span id="716"> 716</span>
<span id="717"> 717</span>
<span id="718"> 718</span>
<span id="719"> 719</span>
<span id="720"> 720</span>
<span id="721"> 721</span>
<span id="722"> 722</span>
<span id="723"> 723</span>
<span id="724"> 724</span>
<span id="725"> 725</span>
<span id="726"> 726</span>
<span id="727"> 727</span>
<span id="728"> 728</span>
<span id="729"> 729</span>
<span id="730"> 730</span>
<span id="731"> 731</span>
<span id="732"> 732</span>
<span id="733"> 733</span>
<span id="734"> 734</span>
<span id="735"> 735</span>
<span id="736"> 736</span>
<span id="737"> 737</span>
<span id="738"> 738</span>
<span id="739"> 739</span>
<span id="740"> 740</span>
<span id="741"> 741</span>
<span id="742"> 742</span>
<span id="743"> 743</span>
<span id="744"> 744</span>
<span id="745"> 745</span>
<span id="746"> 746</span>
<span id="747"> 747</span>
<span id="748"> 748</span>
<span id="749"> 749</span>
<span id="750"> 750</span>
<span id="751"> 751</span>
<span id="752"> 752</span>
<span id="753"> 753</span>
<span id="754"> 754</span>
<span id="755"> 755</span>
<span id="756"> 756</span>
<span id="757"> 757</span>
<span id="758"> 758</span>
<span id="759"> 759</span>
<span id="760"> 760</span>
<span id="761"> 761</span>
<span id="762"> 762</span>
<span id="763"> 763</span>
<span id="764"> 764</span>
<span id="765"> 765</span>
<span id="766"> 766</span>
<span id="767"> 767</span>
<span id="768"> 768</span>
<span id="769"> 769</span>
<span id="770"> 770</span>
<span id="771"> 771</span>
<span id="772"> 772</span>
<span id="773"> 773</span>
<span id="774"> 774</span>
<span id="775"> 775</span>
<span id="776"> 776</span>
<span id="777"> 777</span>
<span id="778"> 778</span>
<span id="779"> 779</span>
<span id="780"> 780</span>
<span id="781"> 781</span>
<span id="782"> 782</span>
<span id="783"> 783</span>
<span id="784"> 784</span>
<span id="785"> 785</span>
<span id="786"> 786</span>
<span id="787"> 787</span>
<span id="788"> 788</span>
<span id="789"> 789</span>
<span id="790"> 790</span>
<span id="791"> 791</span>
<span id="792"> 792</span>
<span id="793"> 793</span>
<span id="794"> 794</span>
<span id="795"> 795</span>
<span id="796"> 796</span>
<span id="797"> 797</span>
<span id="798"> 798</span>
<span id="799"> 799</span>
<span id="800"> 800</span>
<span id="801"> 801</span>
<span id="802"> 802</span>
<span id="803"> 803</span>
<span id="804"> 804</span>
<span id="805"> 805</span>
<span id="806"> 806</span>
<span id="807"> 807</span>
<span id="808"> 808</span>
<span id="809"> 809</span>
<span id="810"> 810</span>
<span id="811"> 811</span>
<span id="812"> 812</span>
<span id="813"> 813</span>
<span id="814"> 814</span>
<span id="815"> 815</span>
<span id="816"> 816</span>
<span id="817"> 817</span>
<span id="818"> 818</span>
<span id="819"> 819</span>
<span id="820"> 820</span>
<span id="821"> 821</span>
<span id="822"> 822</span>
<span id="823"> 823</span>
<span id="824"> 824</span>
<span id="825"> 825</span>
<span id="826"> 826</span>
<span id="827"> 827</span>
<span id="828"> 828</span>
<span id="829"> 829</span>
<span id="830"> 830</span>
<span id="831"> 831</span>
<span id="832"> 832</span>
<span id="833"> 833</span>
<span id="834"> 834</span>
<span id="835"> 835</span>
<span id="836"> 836</span>
<span id="837"> 837</span>
<span id="838"> 838</span>
<span id="839"> 839</span>
<span id="840"> 840</span>
<span id="841"> 841</span>
<span id="842"> 842</span>
<span id="843"> 843</span>
<span id="844"> 844</span>
<span id="845"> 845</span>
<span id="846"> 846</span>
<span id="847"> 847</span>
<span id="848"> 848</span>
<span id="849"> 849</span>
<span id="850"> 850</span>
<span id="851"> 851</span>
<span id="852"> 852</span>
<span id="853"> 853</span>
<span id="854"> 854</span>
<span id="855"> 855</span>
<span id="856"> 856</span>
<span id="857"> 857</span>
<span id="858"> 858</span>
<span id="859"> 859</span>
<span id="860"> 860</span>
<span id="861"> 861</span>
<span id="862"> 862</span>
<span id="863"> 863</span>
<span id="864"> 864</span>
<span id="865"> 865</span>
<span id="866"> 866</span>
<span id="867"> 867</span>
<span id="868"> 868</span>
<span id="869"> 869</span>
<span id="870"> 870</span>
<span id="871"> 871</span>
<span id="872"> 872</span>
<span id="873"> 873</span>
<span id="874"> 874</span>
<span id="875"> 875</span>
<span id="876"> 876</span>
<span id="877"> 877</span>
<span id="878"> 878</span>
<span id="879"> 879</span>
<span id="880"> 880</span>
<span id="881"> 881</span>
<span id="882"> 882</span>
<span id="883"> 883</span>
<span id="884"> 884</span>
<span id="885"> 885</span>
<span id="886"> 886</span>
<span id="887"> 887</span>
<span id="888"> 888</span>
<span id="889"> 889</span>
<span id="890"> 890</span>
<span id="891"> 891</span>
<span id="892"> 892</span>
<span id="893"> 893</span>
<span id="894"> 894</span>
<span id="895"> 895</span>
<span id="896"> 896</span>
<span id="897"> 897</span>
<span id="898"> 898</span>
<span id="899"> 899</span>
<span id="900"> 900</span>
<span id="901"> 901</span>
<span id="902"> 902</span>
<span id="903"> 903</span>
<span id="904"> 904</span>
<span id="905"> 905</span>
<span id="906"> 906</span>
<span id="907"> 907</span>
<span id="908"> 908</span>
<span id="909"> 909</span>
<span id="910"> 910</span>
<span id="911"> 911</span>
<span id="912"> 912</span>
<span id="913"> 913</span>
<span id="914"> 914</span>
<span id="915"> 915</span>
<span id="916"> 916</span>
<span id="917"> 917</span>
<span id="918"> 918</span>
<span id="919"> 919</span>
<span id="920"> 920</span>
<span id="921"> 921</span>
<span id="922"> 922</span>
<span id="923"> 923</span>
<span id="924"> 924</span>
<span id="925"> 925</span>
<span id="926"> 926</span>
<span id="927"> 927</span>
<span id="928"> 928</span>
<span id="929"> 929</span>
<span id="930"> 930</span>
<span id="931"> 931</span>
<span id="932"> 932</span>
<span id="933"> 933</span>
<span id="934"> 934</span>
<span id="935"> 935</span>
<span id="936"> 936</span>
<span id="937"> 937</span>
<span id="938"> 938</span>
<span id="939"> 939</span>
<span id="940"> 940</span>
<span id="941"> 941</span>
<span id="942"> 942</span>
<span id="943"> 943</span>
<span id="944"> 944</span>
<span id="945"> 945</span>
<span id="946"> 946</span>
<span id="947"> 947</span>
<span id="948"> 948</span>
<span id="949"> 949</span>
<span id="950"> 950</span>
<span id="951"> 951</span>
<span id="952"> 952</span>
<span id="953"> 953</span>
<span id="954"> 954</span>
<span id="955"> 955</span>
<span id="956"> 956</span>
<span id="957"> 957</span>
<span id="958"> 958</span>
<span id="959"> 959</span>
<span id="960"> 960</span>
<span id="961"> 961</span>
<span id="962"> 962</span>
<span id="963"> 963</span>
<span id="964"> 964</span>
<span id="965"> 965</span>
<span id="966"> 966</span>
<span id="967"> 967</span>
<span id="968"> 968</span>
<span id="969"> 969</span>
<span id="970"> 970</span>
<span id="971"> 971</span>
<span id="972"> 972</span>
<span id="973"> 973</span>
<span id="974"> 974</span>
<span id="975"> 975</span>
<span id="976"> 976</span>
<span id="977"> 977</span>
<span id="978"> 978</span>
<span id="979"> 979</span>
<span id="980"> 980</span>
<span id="981"> 981</span>
<span id="982"> 982</span>
<span id="983"> 983</span>
<span id="984"> 984</span>
<span id="985"> 985</span>
<span id="986"> 986</span>
<span id="987"> 987</span>
<span id="988"> 988</span>
<span id="989"> 989</span>
<span id="990"> 990</span>
<span id="991"> 991</span>
<span id="992"> 992</span>
<span id="993"> 993</span>
<span id="994"> 994</span>
<span id="995"> 995</span>
<span id="996"> 996</span>
<span id="997"> 997</span>
<span id="998"> 998</span>
<span id="999"> 999</span>
<span id="1000">1000</span>
<span id="1001">1001</span>
<span id="1002">1002</span>
<span id="1003">1003</span>
<span id="1004">1004</span>
<span id="1005">1005</span>
<span id="1006">1006</span>
<span id="1007">1007</span>
<span id="1008">1008</span>
<span id="1009">1009</span>
<span id="1010">1010</span>
<span id="1011">1011</span>
<span id="1012">1012</span>
<span id="1013">1013</span>
<span id="1014">1014</span>
<span id="1015">1015</span>
<span id="1016">1016</span>
<span id="1017">1017</span>
<span id="1018">1018</span>
<span id="1019">1019</span>
<span id="1020">1020</span>
<span id="1021">1021</span>
<span id="1022">1022</span>
<span id="1023">1023</span>
<span id="1024">1024</span>
<span id="1025">1025</span>
<span id="1026">1026</span>
<span id="1027">1027</span>
<span id="1028">1028</span>
<span id="1029">1029</span>
<span id="1030">1030</span>
<span id="1031">1031</span>
<span id="1032">1032</span>
<span id="1033">1033</span>
<span id="1034">1034</span>
<span id="1035">1035</span>
<span id="1036">1036</span>
<span id="1037">1037</span>
<span id="1038">1038</span>
<span id="1039">1039</span>
<span id="1040">1040</span>
<span id="1041">1041</span>
<span id="1042">1042</span>
<span id="1043">1043</span>
<span id="1044">1044</span>
<span id="1045">1045</span>
<span id="1046">1046</span>
<span id="1047">1047</span>
<span id="1048">1048</span>
<span id="1049">1049</span>
<span id="1050">1050</span>
<span id="1051">1051</span>
<span id="1052">1052</span>
<span id="1053">1053</span>
<span id="1054">1054</span>
<span id="1055">1055</span>
<span id="1056">1056</span>
<span id="1057">1057</span>
<span id="1058">1058</span>
<span id="1059">1059</span>
<span id="1060">1060</span>
<span id="1061">1061</span>
<span id="1062">1062</span>
<span id="1063">1063</span>
<span id="1064">1064</span>
<span id="1065">1065</span>
<span id="1066">1066</span>
<span id="1067">1067</span>
<span id="1068">1068</span>
<span id="1069">1069</span>
<span id="1070">1070</span>
<span id="1071">1071</span>
<span id="1072">1072</span>
<span id="1073">1073</span>
<span id="1074">1074</span>
<span id="1075">1075</span>
<span id="1076">1076</span>
<span id="1077">1077</span>
<span id="1078">1078</span>
<span id="1079">1079</span>
<span id="1080">1080</span>
<span id="1081">1081</span>
<span id="1082">1082</span>
<span id="1083">1083</span>
<span id="1084">1084</span>
<span id="1085">1085</span>
<span id="1086">1086</span>
<span id="1087">1087</span>
<span id="1088">1088</span>
<span id="1089">1089</span>
<span id="1090">1090</span>
<span id="1091">1091</span>
<span id="1092">1092</span>
<span id="1093">1093</span>
<span id="1094">1094</span>
<span id="1095">1095</span>
<span id="1096">1096</span>
<span id="1097">1097</span>
<span id="1098">1098</span>
<span id="1099">1099</span>
<span id="1100">1100</span>
<span id="1101">1101</span>
<span id="1102">1102</span>
<span id="1103">1103</span>
<span id="1104">1104</span>
<span id="1105">1105</span>
<span id="1106">1106</span>
<span id="1107">1107</span>
<span id="1108">1108</span>
<span id="1109">1109</span>
<span id="1110">1110</span>
<span id="1111">1111</span>
<span id="1112">1112</span>
<span id="1113">1113</span>
<span id="1114">1114</span>
<span id="1115">1115</span>
<span id="1116">1116</span>
<span id="1117">1117</span>
<span id="1118">1118</span>
<span id="1119">1119</span>
<span id="1120">1120</span>
<span id="1121">1121</span>
<span id="1122">1122</span>
<span id="1123">1123</span>
<span id="1124">1124</span>
<span id="1125">1125</span>
<span id="1126">1126</span>
<span id="1127">1127</span>
<span id="1128">1128</span>
<span id="1129">1129</span>
<span id="1130">1130</span>
<span id="1131">1131</span>
<span id="1132">1132</span>
<span id="1133">1133</span>
<span id="1134">1134</span>
<span id="1135">1135</span>
<span id="1136">1136</span>
<span id="1137">1137</span>
<span id="1138">1138</span>
<span id="1139">1139</span>
<span id="1140">1140</span>
<span id="1141">1141</span>
<span id="1142">1142</span>
<span id="1143">1143</span>
<span id="1144">1144</span>
<span id="1145">1145</span>
<span id="1146">1146</span>
<span id="1147">1147</span>
<span id="1148">1148</span>
<span id="1149">1149</span>
<span id="1150">1150</span>
<span id="1151">1151</span>
<span id="1152">1152</span>
<span id="1153">1153</span>
<span id="1154">1154</span>
<span id="1155">1155</span>
<span id="1156">1156</span>
<span id="1157">1157</span>
<span id="1158">1158</span>
<span id="1159">1159</span>
<span id="1160">1160</span>
<span id="1161">1161</span>
<span id="1162">1162</span>
<span id="1163">1163</span>
<span id="1164">1164</span>
<span id="1165">1165</span>
<span id="1166">1166</span>
<span id="1167">1167</span>
<span id="1168">1168</span>
<span id="1169">1169</span>
<span id="1170">1170</span>
<span id="1171">1171</span>
<span id="1172">1172</span>
<span id="1173">1173</span>
<span id="1174">1174</span>
<span id="1175">1175</span>
<span id="1176">1176</span>
<span id="1177">1177</span>
<span id="1178">1178</span>
<span id="1179">1179</span>
<span id="1180">1180</span>
<span id="1181">1181</span>
<span id="1182">1182</span>
<span id="1183">1183</span>
<span id="1184">1184</span>
<span id="1185">1185</span>
<span id="1186">1186</span>
<span id="1187">1187</span>
<span id="1188">1188</span>
<span id="1189">1189</span>
<span id="1190">1190</span>
<span id="1191">1191</span>
<span id="1192">1192</span>
<span id="1193">1193</span>
<span id="1194">1194</span>
<span id="1195">1195</span>
<span id="1196">1196</span>
<span id="1197">1197</span>
<span id="1198">1198</span>
<span id="1199">1199</span>
<span id="1200">1200</span>
<span id="1201">1201</span>
<span id="1202">1202</span>
<span id="1203">1203</span>
<span id="1204">1204</span>
<span id="1205">1205</span>
<span id="1206">1206</span>
<span id="1207">1207</span>
<span id="1208">1208</span>
<span id="1209">1209</span>
<span id="1210">1210</span>
<span id="1211">1211</span>
<span id="1212">1212</span>
<span id="1213">1213</span>
<span id="1214">1214</span>
<span id="1215">1215</span>
<span id="1216">1216</span>
<span id="1217">1217</span>
<span id="1218">1218</span>
<span id="1219">1219</span>
<span id="1220">1220</span>
<span id="1221">1221</span>
<span id="1222">1222</span>
<span id="1223">1223</span>
<span id="1224">1224</span>
<span id="1225">1225</span>
<span id="1226">1226</span>
<span id="1227">1227</span>
<span id="1228">1228</span>
<span id="1229">1229</span>
<span id="1230">1230</span>
<span id="1231">1231</span>
<span id="1232">1232</span>
<span id="1233">1233</span>
<span id="1234">1234</span>
<span id="1235">1235</span>
<span id="1236">1236</span>
<span id="1237">1237</span>
<span id="1238">1238</span>
<span id="1239">1239</span>
<span id="1240">1240</span>
<span id="1241">1241</span>
<span id="1242">1242</span>
<span id="1243">1243</span>
<span id="1244">1244</span>
<span id="1245">1245</span>
<span id="1246">1246</span>
<span id="1247">1247</span>
<span id="1248">1248</span>
<span id="1249">1249</span>
<span id="1250">1250</span>
<span id="1251">1251</span>
<span id="1252">1252</span>
<span id="1253">1253</span>
<span id="1254">1254</span>
<span id="1255">1255</span>
<span id="1256">1256</span>
<span id="1257">1257</span>
<span id="1258">1258</span>
<span id="1259">1259</span>
<span id="1260">1260</span>
<span id="1261">1261</span>
<span id="1262">1262</span>
<span id="1263">1263</span>
<span id="1264">1264</span>
<span id="1265">1265</span>
<span id="1266">1266</span>
<span id="1267">1267</span>
<span id="1268">1268</span>
<span id="1269">1269</span>
<span id="1270">1270</span>
<span id="1271">1271</span>
<span id="1272">1272</span>
<span id="1273">1273</span>
<span id="1274">1274</span>
<span id="1275">1275</span>
<span id="1276">1276</span>
<span id="1277">1277</span>
<span id="1278">1278</span>
<span id="1279">1279</span>
<span id="1280">1280</span>
<span id="1281">1281</span>
<span id="1282">1282</span>
<span id="1283">1283</span>
<span id="1284">1284</span>
<span id="1285">1285</span>
<span id="1286">1286</span>
<span id="1287">1287</span>
<span id="1288">1288</span>
<span id="1289">1289</span>
<span id="1290">1290</span>
<span id="1291">1291</span>
<span id="1292">1292</span>
<span id="1293">1293</span>
<span id="1294">1294</span>
<span id="1295">1295</span>
<span id="1296">1296</span>
<span id="1297">1297</span>
<span id="1298">1298</span>
<span id="1299">1299</span>
<span id="1300">1300</span>
<span id="1301">1301</span>
<span id="1302">1302</span>
<span id="1303">1303</span>
<span id="1304">1304</span>
<span id="1305">1305</span>
<span id="1306">1306</span>
<span id="1307">1307</span>
<span id="1308">1308</span>
<span id="1309">1309</span>
<span id="1310">1310</span>
<span id="1311">1311</span>
<span id="1312">1312</span>
<span id="1313">1313</span>
<span id="1314">1314</span>
<span id="1315">1315</span>
<span id="1316">1316</span>
<span id="1317">1317</span>
<span id="1318">1318</span>
<span id="1319">1319</span>
<span id="1320">1320</span>
<span id="1321">1321</span>
<span id="1322">1322</span>
<span id="1323">1323</span>
<span id="1324">1324</span>
<span id="1325">1325</span>
<span id="1326">1326</span>
<span id="1327">1327</span>
<span id="1328">1328</span>
<span id="1329">1329</span>
<span id="1330">1330</span>
<span id="1331">1331</span>
<span id="1332">1332</span>
<span id="1333">1333</span>
<span id="1334">1334</span>
<span id="1335">1335</span>
<span id="1336">1336</span>
<span id="1337">1337</span>
<span id="1338">1338</span>
<span id="1339">1339</span>
<span id="1340">1340</span>
<span id="1341">1341</span>
<span id="1342">1342</span>
<span id="1343">1343</span>
<span id="1344">1344</span>
<span id="1345">1345</span>
<span id="1346">1346</span>
<span id="1347">1347</span>
<span id="1348">1348</span>
<span id="1349">1349</span>
<span id="1350">1350</span>
<span id="1351">1351</span>
<span id="1352">1352</span>
<span id="1353">1353</span>
<span id="1354">1354</span>
<span id="1355">1355</span>
<span id="1356">1356</span>
<span id="1357">1357</span>
<span id="1358">1358</span>
<span id="1359">1359</span>
<span id="1360">1360</span>
<span id="1361">1361</span>
<span id="1362">1362</span>
<span id="1363">1363</span>
<span id="1364">1364</span>
<span id="1365">1365</span>
<span id="1366">1366</span>
<span id="1367">1367</span>
<span id="1368">1368</span>
<span id="1369">1369</span>
<span id="1370">1370</span>
<span id="1371">1371</span>
<span id="1372">1372</span>
<span id="1373">1373</span>
<span id="1374">1374</span>
<span id="1375">1375</span>
<span id="1376">1376</span>
<span id="1377">1377</span>
<span id="1378">1378</span>
<span id="1379">1379</span>
<span id="1380">1380</span>
<span id="1381">1381</span>
<span id="1382">1382</span>
<span id="1383">1383</span>
<span id="1384">1384</span>
<span id="1385">1385</span>
<span id="1386">1386</span>
<span id="1387">1387</span>
<span id="1388">1388</span>
<span id="1389">1389</span>
<span id="1390">1390</span>
<span id="1391">1391</span>
<span id="1392">1392</span>
<span id="1393">1393</span>
<span id="1394">1394</span>
<span id="1395">1395</span>
<span id="1396">1396</span>
<span id="1397">1397</span>
<span id="1398">1398</span>
<span id="1399">1399</span>
<span id="1400">1400</span>
<span id="1401">1401</span>
<span id="1402">1402</span>
<span id="1403">1403</span>
<span id="1404">1404</span>
<span id="1405">1405</span>
<span id="1406">1406</span>
<span id="1407">1407</span>
<span id="1408">1408</span>
<span id="1409">1409</span>
<span id="1410">1410</span>
<span id="1411">1411</span>
<span id="1412">1412</span>
<span id="1413">1413</span>
<span id="1414">1414</span>
<span id="1415">1415</span>
<span id="1416">1416</span>
<span id="1417">1417</span>
<span id="1418">1418</span>
<span id="1419">1419</span>
<span id="1420">1420</span>
<span id="1421">1421</span>
<span id="1422">1422</span>
<span id="1423">1423</span>
<span id="1424">1424</span>
<span id="1425">1425</span>
<span id="1426">1426</span>
<span id="1427">1427</span>
<span id="1428">1428</span>
<span id="1429">1429</span>
<span id="1430">1430</span>
<span id="1431">1431</span>
<span id="1432">1432</span>
<span id="1433">1433</span>
<span id="1434">1434</span>
<span id="1435">1435</span>
<span id="1436">1436</span>
<span id="1437">1437</span>
<span id="1438">1438</span>
<span id="1439">1439</span>
<span id="1440">1440</span>
<span id="1441">1441</span>
<span id="1442">1442</span>
<span id="1443">1443</span>
<span id="1444">1444</span>
<span id="1445">1445</span>
<span id="1446">1446</span>
<span id="1447">1447</span>
<span id="1448">1448</span>
<span id="1449">1449</span>
<span id="1450">1450</span>
<span id="1451">1451</span>
<span id="1452">1452</span>
<span id="1453">1453</span>
<span id="1454">1454</span>
<span id="1455">1455</span>
<span id="1456">1456</span>
<span id="1457">1457</span>
<span id="1458">1458</span>
<span id="1459">1459</span>
<span id="1460">1460</span>
<span id="1461">1461</span>
<span id="1462">1462</span>
<span id="1463">1463</span>
<span id="1464">1464</span>
<span id="1465">1465</span>
<span id="1466">1466</span>
<span id="1467">1467</span>
<span id="1468">1468</span>
<span id="1469">1469</span>
<span id="1470">1470</span>
<span id="1471">1471</span>
<span id="1472">1472</span>
<span id="1473">1473</span>
<span id="1474">1474</span>
<span id="1475">1475</span>
<span id="1476">1476</span>
<span id="1477">1477</span>
<span id="1478">1478</span>
<span id="1479">1479</span>
<span id="1480">1480</span>
<span id="1481">1481</span>
<span id="1482">1482</span>
<span id="1483">1483</span>
<span id="1484">1484</span>
<span id="1485">1485</span>
<span id="1486">1486</span>
<span id="1487">1487</span>
<span id="1488">1488</span>
<span id="1489">1489</span>
<span id="1490">1490</span>
<span id="1491">1491</span>
<span id="1492">1492</span>
<span id="1493">1493</span>
<span id="1494">1494</span>
<span id="1495">1495</span>
<span id="1496">1496</span>
<span id="1497">1497</span>
<span id="1498">1498</span>
<span id="1499">1499</span>
<span id="1500">1500</span>
<span id="1501">1501</span>
<span id="1502">1502</span>
<span id="1503">1503</span>
<span id="1504">1504</span>
<span id="1505">1505</span>
<span id="1506">1506</span>
<span id="1507">1507</span>
<span id="1508">1508</span>
<span id="1509">1509</span>
<span id="1510">1510</span>
<span id="1511">1511</span>
<span id="1512">1512</span>
<span id="1513">1513</span>
<span id="1514">1514</span>
<span id="1515">1515</span>
<span id="1516">1516</span>
<span id="1517">1517</span>
<span id="1518">1518</span>
<span id="1519">1519</span>
<span id="1520">1520</span>
<span id="1521">1521</span>
<span id="1522">1522</span>
<span id="1523">1523</span>
<span id="1524">1524</span>
<span id="1525">1525</span>
<span id="1526">1526</span>
<span id="1527">1527</span>
<span id="1528">1528</span>
<span id="1529">1529</span>
<span id="1530">1530</span>
<span id="1531">1531</span>
<span id="1532">1532</span>
<span id="1533">1533</span>
<span id="1534">1534</span>
<span id="1535">1535</span>
<span id="1536">1536</span>
<span id="1537">1537</span>
<span id="1538">1538</span>
<span id="1539">1539</span>
<span id="1540">1540</span>
<span id="1541">1541</span>
<span id="1542">1542</span>
<span id="1543">1543</span>
<span id="1544">1544</span>
<span id="1545">1545</span>
<span id="1546">1546</span>
<span id="1547">1547</span>
<span id="1548">1548</span>
<span id="1549">1549</span>
<span id="1550">1550</span>
<span id="1551">1551</span>
<span id="1552">1552</span>
<span id="1553">1553</span>
<span id="1554">1554</span>
<span id="1555">1555</span>
<span id="1556">1556</span>
<span id="1557">1557</span>
<span id="1558">1558</span>
<span id="1559">1559</span>
<span id="1560">1560</span>
<span id="1561">1561</span>
<span id="1562">1562</span>
<span id="1563">1563</span>
<span id="1564">1564</span>
<span id="1565">1565</span>
<span id="1566">1566</span>
<span id="1567">1567</span>
<span id="1568">1568</span>
<span id="1569">1569</span>
<span id="1570">1570</span>
<span id="1571">1571</span>
<span id="1572">1572</span>
<span id="1573">1573</span>
<span id="1574">1574</span>
<span id="1575">1575</span>
<span id="1576">1576</span>
<span id="1577">1577</span>
<span id="1578">1578</span>
<span id="1579">1579</span>
<span id="1580">1580</span>
<span id="1581">1581</span>
<span id="1582">1582</span>
<span id="1583">1583</span>
<span id="1584">1584</span>
<span id="1585">1585</span>
<span id="1586">1586</span>
<span id="1587">1587</span>
<span id="1588">1588</span>
<span id="1589">1589</span>
<span id="1590">1590</span>
<span id="1591">1591</span>
<span id="1592">1592</span>
<span id="1593">1593</span>
<span id="1594">1594</span>
<span id="1595">1595</span>
<span id="1596">1596</span>
<span id="1597">1597</span>
<span id="1598">1598</span>
<span id="1599">1599</span>
<span id="1600">1600</span>
<span id="1601">1601</span>
<span id="1602">1602</span>
<span id="1603">1603</span>
<span id="1604">1604</span>
<span id="1605">1605</span>
<span id="1606">1606</span>
<span id="1607">1607</span>
<span id="1608">1608</span>
<span id="1609">1609</span>
<span id="1610">1610</span>
<span id="1611">1611</span>
<span id="1612">1612</span>
<span id="1613">1613</span>
<span id="1614">1614</span>
<span id="1615">1615</span>
<span id="1616">1616</span>
<span id="1617">1617</span>
<span id="1618">1618</span>
<span id="1619">1619</span>
<span id="1620">1620</span>
<span id="1621">1621</span>
<span id="1622">1622</span>
<span id="1623">1623</span>
<span id="1624">1624</span>
<span id="1625">1625</span>
<span id="1626">1626</span>
<span id="1627">1627</span>
<span id="1628">1628</span>
<span id="1629">1629</span>
<span id="1630">1630</span>
<span id="1631">1631</span>
<span id="1632">1632</span>
<span id="1633">1633</span>
<span id="1634">1634</span>
<span id="1635">1635</span>
<span id="1636">1636</span>
<span id="1637">1637</span>
<span id="1638">1638</span>
<span id="1639">1639</span>
<span id="1640">1640</span>
<span id="1641">1641</span>
<span id="1642">1642</span>
<span id="1643">1643</span>
<span id="1644">1644</span>
<span id="1645">1645</span>
<span id="1646">1646</span>
<span id="1647">1647</span>
<span id="1648">1648</span>
<span id="1649">1649</span>
<span id="1650">1650</span>
<span id="1651">1651</span>
<span id="1652">1652</span>
<span id="1653">1653</span>
<span id="1654">1654</span>
<span id="1655">1655</span>
<span id="1656">1656</span>
<span id="1657">1657</span>
<span id="1658">1658</span>
<span id="1659">1659</span>
<span id="1660">1660</span>
<span id="1661">1661</span>
<span id="1662">1662</span>
<span id="1663">1663</span>
<span id="1664">1664</span>
<span id="1665">1665</span>
<span id="1666">1666</span>
<span id="1667">1667</span>
<span id="1668">1668</span>
<span id="1669">1669</span>
<span id="1670">1670</span>
<span id="1671">1671</span>
<span id="1672">1672</span>
<span id="1673">1673</span>
<span id="1674">1674</span>
<span id="1675">1675</span>
<span id="1676">1676</span>
<span id="1677">1677</span>
<span id="1678">1678</span>
<span id="1679">1679</span>
<span id="1680">1680</span>
<span id="1681">1681</span>
<span id="1682">1682</span>
<span id="1683">1683</span>
<span id="1684">1684</span>
<span id="1685">1685</span>
<span id="1686">1686</span>
<span id="1687">1687</span>
<span id="1688">1688</span>
<span id="1689">1689</span>
<span id="1690">1690</span>
<span id="1691">1691</span>
<span id="1692">1692</span>
<span id="1693">1693</span>
<span id="1694">1694</span>
<span id="1695">1695</span>
<span id="1696">1696</span>
<span id="1697">1697</span>
<span id="1698">1698</span>
<span id="1699">1699</span>
<span id="1700">1700</span>
<span id="1701">1701</span>
<span id="1702">1702</span>
<span id="1703">1703</span>
<span id="1704">1704</span>
<span id="1705">1705</span>
<span id="1706">1706</span>
<span id="1707">1707</span>
<span id="1708">1708</span>
<span id="1709">1709</span>
<span id="1710">1710</span>
<span id="1711">1711</span>
<span id="1712">1712</span>
<span id="1713">1713</span>
<span id="1714">1714</span>
<span id="1715">1715</span>
<span id="1716">1716</span>
<span id="1717">1717</span>
<span id="1718">1718</span>
<span id="1719">1719</span>
<span id="1720">1720</span>
<span id="1721">1721</span>
<span id="1722">1722</span>
<span id="1723">1723</span>
<span id="1724">1724</span>
<span id="1725">1725</span>
<span id="1726">1726</span>
<span id="1727">1727</span>
<span id="1728">1728</span>
<span id="1729">1729</span>
<span id="1730">1730</span>
<span id="1731">1731</span>
<span id="1732">1732</span>
<span id="1733">1733</span>
<span id="1734">1734</span>
<span id="1735">1735</span>
<span id="1736">1736</span>
<span id="1737">1737</span>
<span id="1738">1738</span>
<span id="1739">1739</span>
<span id="1740">1740</span>
<span id="1741">1741</span>
<span id="1742">1742</span>
<span id="1743">1743</span>
<span id="1744">1744</span>
<span id="1745">1745</span>
<span id="1746">1746</span>
<span id="1747">1747</span>
<span id="1748">1748</span>
<span id="1749">1749</span>
<span id="1750">1750</span>
<span id="1751">1751</span>
<span id="1752">1752</span>
<span id="1753">1753</span>
<span id="1754">1754</span>
<span id="1755">1755</span>
<span id="1756">1756</span>
<span id="1757">1757</span>
<span id="1758">1758</span>
<span id="1759">1759</span>
<span id="1760">1760</span>
<span id="1761">1761</span>
<span id="1762">1762</span>
<span id="1763">1763</span>
<span id="1764">1764</span>
<span id="1765">1765</span>
<span id="1766">1766</span>
<span id="1767">1767</span>
<span id="1768">1768</span>
<span id="1769">1769</span>
<span id="1770">1770</span>
<span id="1771">1771</span>
<span id="1772">1772</span>
<span id="1773">1773</span>
<span id="1774">1774</span>
<span id="1775">1775</span>
<span id="1776">1776</span>
<span id="1777">1777</span>
<span id="1778">1778</span>
<span id="1779">1779</span>
<span id="1780">1780</span>
<span id="1781">1781</span>
<span id="1782">1782</span>
<span id="1783">1783</span>
<span id="1784">1784</span>
<span id="1785">1785</span>
<span id="1786">1786</span>
</pre><pre class="rust ">
<span class="doccomment">//! Static files support</span>
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">fmt</span>::<span class="ident">Write</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">fs</span>::{<span class="ident">DirEntry</span>, <span class="ident">File</span>, <span class="ident">Metadata</span>};
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">io</span>::{<span class="ident">Read</span>, <span class="ident">Seek</span>};
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">marker</span>::<span class="ident">PhantomData</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">ops</span>::{<span class="ident">Deref</span>, <span class="ident">DerefMut</span>};
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">path</span>::{<span class="ident">Path</span>, <span class="ident">PathBuf</span>};
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">time</span>::{<span class="ident">SystemTime</span>, <span class="ident">UNIX_EPOCH</span>};
<span class="kw">use</span> <span class="ident">std</span>::{<span class="ident">cmp</span>, <span class="ident">io</span>};
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">unix</span>)]</span>
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">os</span>::<span class="ident">unix</span>::<span class="ident">fs</span>::<span class="ident">MetadataExt</span>;
<span class="kw">use</span> <span class="ident">bytes</span>::<span class="ident">Bytes</span>;
<span class="kw">use</span> <span class="ident">futures</span>::{<span class="ident">Async</span>, <span class="ident">Future</span>, <span class="ident">Poll</span>, <span class="ident">Stream</span>};
<span class="kw">use</span> <span class="ident">futures_cpupool</span>::{<span class="ident">CpuFuture</span>, <span class="ident">CpuPool</span>};
<span class="kw">use</span> <span class="ident">htmlescape</span>::<span class="ident">encode_minimal</span> <span class="kw">as</span> <span class="ident">escape_html_entity</span>;
<span class="kw">use</span> <span class="ident">mime</span>;
<span class="kw">use</span> <span class="ident">mime_guess</span>::{<span class="ident">get_mime_type</span>, <span class="ident">guess_mime_type</span>};
<span class="kw">use</span> <span class="ident">percent_encoding</span>::{<span class="ident">utf8_percent_encode</span>, <span class="ident">DEFAULT_ENCODE_SET</span>};
<span class="kw">use</span> <span class="ident">error</span>::{<span class="ident">Error</span>, <span class="ident">StaticFileError</span>};
<span class="kw">use</span> <span class="ident">handler</span>::{<span class="ident">AsyncResult</span>, <span class="ident">Handler</span>, <span class="ident">Responder</span>, <span class="ident">RouteHandler</span>, <span class="ident">WrapHandler</span>};
<span class="kw">use</span> <span class="ident">header</span>;
<span class="kw">use</span> <span class="ident">header</span>::{<span class="ident">ContentDisposition</span>, <span class="ident">DispositionParam</span>, <span class="ident">DispositionType</span>};
<span class="kw">use</span> <span class="ident">http</span>::{<span class="ident">ContentEncoding</span>, <span class="ident">Method</span>, <span class="ident">StatusCode</span>};
<span class="kw">use</span> <span class="ident">httpmessage</span>::<span class="ident">HttpMessage</span>;
<span class="kw">use</span> <span class="ident">httprequest</span>::<span class="ident">HttpRequest</span>;
<span class="kw">use</span> <span class="ident">httpresponse</span>::<span class="ident">HttpResponse</span>;
<span class="kw">use</span> <span class="ident">param</span>::<span class="ident">FromParam</span>;
<span class="kw">use</span> <span class="ident">server</span>::<span class="ident">settings</span>::<span class="ident">DEFAULT_CPUPOOL</span>;
<span class="doccomment">///Describes `StaticFiles` configiration</span>
<span class="doccomment">///</span>
<span class="doccomment">///To configure actix&#39;s static resources you need</span>
<span class="doccomment">///to define own configiration type and implement any method</span>
<span class="doccomment">///you wish to customize.</span>
<span class="doccomment">///As trait implements reasonable defaults for Actix.</span>
<span class="doccomment">///</span>
<span class="doccomment">///## Example</span>
<span class="doccomment">///</span>
<span class="doccomment">///```rust</span>
<span class="doccomment">/// extern crate mime;</span>
<span class="doccomment">/// extern crate actix_web;</span>
<span class="doccomment">/// use actix_web::http::header::DispositionType;</span>
<span class="doccomment">/// use actix_web::fs::{StaticFileConfig, NamedFile};</span>
<span class="doccomment">///</span>
<span class="doccomment">/// #[derive(Default)]</span>
<span class="doccomment">/// struct MyConfig;</span>
<span class="doccomment">///</span>
<span class="doccomment">/// impl StaticFileConfig for MyConfig {</span>
<span class="doccomment">/// fn content_disposition_map(typ: mime::Name) -&gt; DispositionType {</span>
<span class="doccomment">/// DispositionType::Attachment</span>
<span class="doccomment">/// }</span>
<span class="doccomment">/// }</span>
<span class="doccomment">///</span>
<span class="doccomment">/// let file = NamedFile::open_with_config(&quot;foo.txt&quot;, MyConfig);</span>
<span class="doccomment">///```</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">StaticFileConfig</span>: <span class="ident">Default</span> {
<span class="doccomment">///Describes mapping for mime type to content disposition header</span>
<span class="doccomment">///</span>
<span class="doccomment">///By default `IMAGE`, `TEXT` and `VIDEO` are mapped to Inline.</span>
<span class="doccomment">///Others are mapped to Attachment</span>
<span class="kw">fn</span> <span class="ident">content_disposition_map</span>(<span class="ident">typ</span>: <span class="ident">mime</span>::<span class="ident">Name</span>) <span class="op">-&gt;</span> <span class="ident">DispositionType</span> {
<span class="kw">match</span> <span class="ident">typ</span> {
<span class="ident">mime</span>::<span class="ident">IMAGE</span> <span class="op">|</span> <span class="ident">mime</span>::<span class="ident">TEXT</span> <span class="op">|</span> <span class="ident">mime</span>::<span class="ident">VIDEO</span> <span class="op">=&gt;</span> <span class="ident">DispositionType</span>::<span class="ident">Inline</span>,
<span class="kw">_</span> <span class="op">=&gt;</span> <span class="ident">DispositionType</span>::<span class="ident">Attachment</span>,
}
}
<span class="doccomment">///Describes whether Actix should attempt to calculate `ETag`</span>
<span class="doccomment">///</span>
<span class="doccomment">///Defaults to `true`</span>
<span class="kw">fn</span> <span class="ident">is_use_etag</span>() <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="bool-val">true</span>
}
<span class="doccomment">///Describes whether Actix should use last modified date of file.</span>
<span class="doccomment">///</span>
<span class="doccomment">///Defaults to `true`</span>
<span class="kw">fn</span> <span class="ident">is_use_last_modifier</span>() <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="bool-val">true</span>
}
<span class="doccomment">///Describes allowed methods to access static resources.</span>
<span class="doccomment">///</span>
<span class="doccomment">///By default all methods are allowed</span>
<span class="kw">fn</span> <span class="ident">is_method_allowed</span>(<span class="ident">_method</span>: <span class="kw-2">&amp;</span><span class="ident">Method</span>) <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="bool-val">true</span>
}
}
<span class="doccomment">///Default content disposition as described in</span>
<span class="doccomment">///[StaticFileConfig](trait.StaticFileConfig.html)</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">DefaultConfig</span>;
<span class="kw">impl</span> <span class="ident">StaticFileConfig</span> <span class="kw">for</span> <span class="ident">DefaultConfig</span> {}
<span class="doccomment">/// Return the MIME type associated with a filename extension (case-insensitive).</span>
<span class="doccomment">/// If `ext` is empty or no associated type for the extension was found, returns</span>
<span class="doccomment">/// the type `application/octet-stream`.</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">file_extension_to_mime</span>(<span class="ident">ext</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) <span class="op">-&gt;</span> <span class="ident">mime</span>::<span class="ident">Mime</span> {
<span class="ident">get_mime_type</span>(<span class="ident">ext</span>)
}
<span class="doccomment">/// A file with an associated name.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span> <span class="op">=</span> <span class="ident">DefaultConfig</span><span class="op">&gt;</span> {
<span class="ident">path</span>: <span class="ident">PathBuf</span>,
<span class="ident">file</span>: <span class="ident">File</span>,
<span class="ident">content_type</span>: <span class="ident">mime</span>::<span class="ident">Mime</span>,
<span class="ident">content_disposition</span>: <span class="ident">header</span>::<span class="ident">ContentDisposition</span>,
<span class="ident">md</span>: <span class="ident">Metadata</span>,
<span class="ident">modified</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">SystemTime</span><span class="op">&gt;</span>,
<span class="ident">cpu_pool</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">CpuPool</span><span class="op">&gt;</span>,
<span class="ident">encoding</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">ContentEncoding</span><span class="op">&gt;</span>,
<span class="ident">status_code</span>: <span class="ident">StatusCode</span>,
<span class="ident">_cd_map</span>: <span class="ident">PhantomData</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span> <span class="ident">NamedFile</span> {
<span class="doccomment">/// Attempts to open a file in read-only mode.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Examples</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```rust</span>
<span class="doccomment">/// use actix_web::fs::NamedFile;</span>
<span class="doccomment">///</span>
<span class="doccomment">/// let file = NamedFile::open(&quot;foo.txt&quot;);</span>
<span class="doccomment">/// ```</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">open</span><span class="op">&lt;</span><span class="ident">P</span>: <span class="ident">AsRef</span><span class="op">&lt;</span><span class="ident">Path</span><span class="op">&gt;&gt;</span>(<span class="ident">path</span>: <span class="ident">P</span>) <span class="op">-&gt;</span> <span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">NamedFile</span><span class="op">&gt;</span> {
<span class="self">Self</span>::<span class="ident">open_with_config</span>(<span class="ident">path</span>, <span class="ident">DefaultConfig</span>)
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">C</span>: <span class="ident">StaticFileConfig</span><span class="op">&gt;</span> <span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> {
<span class="doccomment">/// Attempts to open a file in read-only mode using provided configiration.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Examples</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```rust</span>
<span class="doccomment">/// use actix_web::fs::{DefaultConfig, NamedFile};</span>
<span class="doccomment">///</span>
<span class="doccomment">/// let file = NamedFile::open_with_config(&quot;foo.txt&quot;, DefaultConfig);</span>
<span class="doccomment">/// ```</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">open_with_config</span><span class="op">&lt;</span><span class="ident">P</span>: <span class="ident">AsRef</span><span class="op">&lt;</span><span class="ident">Path</span><span class="op">&gt;&gt;</span>(<span class="ident">path</span>: <span class="ident">P</span>, <span class="kw">_</span>: <span class="ident">C</span>) <span class="op">-&gt;</span> <span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;&gt;</span> {
<span class="kw">let</span> <span class="ident">path</span> <span class="op">=</span> <span class="ident">path</span>.<span class="ident">as_ref</span>().<span class="ident">to_path_buf</span>();
<span class="comment">// Get the name of the file and use it to construct default Content-Type</span>
<span class="comment">// and Content-Disposition values</span>
<span class="kw">let</span> (<span class="ident">content_type</span>, <span class="ident">content_disposition</span>) <span class="op">=</span> {
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">path</span>.<span class="ident">file_name</span>() {
<span class="prelude-val">Some</span>(<span class="ident">name</span>) <span class="op">=&gt;</span> <span class="ident">name</span>.<span class="ident">to_string_lossy</span>(),
<span class="prelude-val">None</span> <span class="op">=&gt;</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">io</span>::<span class="ident">Error</span>::<span class="ident">new</span>(
<span class="ident">io</span>::<span class="ident">ErrorKind</span>::<span class="ident">InvalidInput</span>,
<span class="string">&quot;Provided path has no filename&quot;</span>,
))
}
};
<span class="kw">let</span> <span class="ident">ct</span> <span class="op">=</span> <span class="ident">guess_mime_type</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>);
<span class="kw">let</span> <span class="ident">disposition_type</span> <span class="op">=</span> <span class="ident">C</span>::<span class="ident">content_disposition_map</span>(<span class="ident">ct</span>.<span class="ident">type_</span>());
<span class="kw">let</span> <span class="ident">cd</span> <span class="op">=</span> <span class="ident">ContentDisposition</span> {
<span class="ident">disposition</span>: <span class="ident">disposition_type</span>,
<span class="ident">parameters</span>: <span class="macro">vec</span><span class="macro">!</span>[<span class="ident">DispositionParam</span>::<span class="ident">Filename</span>(<span class="ident">filename</span>.<span class="ident">into_owned</span>())],
};
(<span class="ident">ct</span>, <span class="ident">cd</span>)
};
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">File</span>::<span class="ident">open</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">md</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">metadata</span>()<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">modified</span> <span class="op">=</span> <span class="ident">md</span>.<span class="ident">modified</span>().<span class="ident">ok</span>();
<span class="kw">let</span> <span class="ident">cpu_pool</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="kw">let</span> <span class="ident">encoding</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="prelude-val">Ok</span>(<span class="ident">NamedFile</span> {
<span class="ident">path</span>,
<span class="ident">file</span>,
<span class="ident">content_type</span>,
<span class="ident">content_disposition</span>,
<span class="ident">md</span>,
<span class="ident">modified</span>,
<span class="ident">cpu_pool</span>,
<span class="ident">encoding</span>,
<span class="ident">status_code</span>: <span class="ident">StatusCode</span>::<span class="ident">OK</span>,
<span class="ident">_cd_map</span>: <span class="ident">PhantomData</span>,
})
}
<span class="doccomment">/// Returns reference to the underlying `File` object.</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">file</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="kw-2">&amp;</span><span class="ident">File</span> {
<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">file</span>
}
<span class="doccomment">/// Retrieve the path of this file.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Examples</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```rust</span>
<span class="doccomment">/// # use std::io;</span>
<span class="doccomment">/// use actix_web::fs::NamedFile;</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # fn path() -&gt; io::Result&lt;()&gt; {</span>
<span class="doccomment">/// let file = NamedFile::open(&quot;test.txt&quot;)?;</span>
<span class="doccomment">/// assert_eq!(file.path().as_os_str(), &quot;foo.txt&quot;);</span>
<span class="doccomment">/// # Ok(())</span>
<span class="doccomment">/// # }</span>
<span class="doccomment">/// ```</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">path</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="kw-2">&amp;</span><span class="ident">Path</span> {
<span class="self">self</span>.<span class="ident">path</span>.<span class="ident">as_path</span>()
}
<span class="doccomment">/// Set `CpuPool` to use</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">set_cpu_pool</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">cpu_pool</span>: <span class="ident">CpuPool</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">cpu_pool</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">cpu_pool</span>);
<span class="self">self</span>
}
<span class="doccomment">/// Set response **Status Code**</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">set_status_code</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">status</span>: <span class="ident">StatusCode</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">status_code</span> <span class="op">=</span> <span class="ident">status</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the MIME Content-Type for serving this file. By default</span>
<span class="doccomment">/// the Content-Type is inferred from the filename extension.</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">set_content_type</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">mime_type</span>: <span class="ident">mime</span>::<span class="ident">Mime</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">content_type</span> <span class="op">=</span> <span class="ident">mime_type</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set the Content-Disposition for serving this file. This allows</span>
<span class="doccomment">/// changing the inline/attachment disposition as well as the filename</span>
<span class="doccomment">/// sent to the peer. By default the disposition is `inline` for text,</span>
<span class="doccomment">/// image, and video content types, and `attachment` otherwise, and</span>
<span class="doccomment">/// the filename is taken from the path provided in the `open` method</span>
<span class="doccomment">/// after converting it to UTF-8 using</span>
<span class="doccomment">/// [to_string_lossy](https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_string_lossy).</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">set_content_disposition</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">cd</span>: <span class="ident">header</span>::<span class="ident">ContentDisposition</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">content_disposition</span> <span class="op">=</span> <span class="ident">cd</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set content encoding for serving this file</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">set_content_encoding</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">enc</span>: <span class="ident">ContentEncoding</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">encoding</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">enc</span>);
<span class="self">self</span>
}
<span class="kw">fn</span> <span class="ident">etag</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">header</span>::<span class="ident">EntityTag</span><span class="op">&gt;</span> {
<span class="comment">// This etag format is similar to Apache&#39;s.</span>
<span class="self">self</span>.<span class="ident">modified</span>.<span class="ident">as_ref</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">mtime</span><span class="op">|</span> {
<span class="kw">let</span> <span class="ident">ino</span> <span class="op">=</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">unix</span>)]</span>
{
<span class="self">self</span>.<span class="ident">md</span>.<span class="ident">ino</span>()
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">unix</span>))]</span>
{
<span class="number">0</span>
}
};
<span class="kw">let</span> <span class="ident">dur</span> <span class="op">=</span> <span class="ident">mtime</span>
.<span class="ident">duration_since</span>(<span class="ident">UNIX_EPOCH</span>)
.<span class="ident">expect</span>(<span class="string">&quot;modification time must be after epoch&quot;</span>);
<span class="ident">header</span>::<span class="ident">EntityTag</span>::<span class="ident">strong</span>(<span class="macro">format</span><span class="macro">!</span>(
<span class="string">&quot;{:x}:{:x}:{:x}:{:x}&quot;</span>,
<span class="ident">ino</span>,
<span class="self">self</span>.<span class="ident">md</span>.<span class="ident">len</span>(),
<span class="ident">dur</span>.<span class="ident">as_secs</span>(),
<span class="ident">dur</span>.<span class="ident">subsec_nanos</span>()
))
})
}
<span class="kw">fn</span> <span class="ident">last_modified</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">header</span>::<span class="ident">HttpDate</span><span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">modified</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">mtime</span><span class="op">|</span> <span class="ident">mtime</span>.<span class="ident">into</span>())
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> <span class="ident">Deref</span> <span class="kw">for</span> <span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> {
<span class="kw">type</span> <span class="ident">Target</span> <span class="op">=</span> <span class="ident">File</span>;
<span class="kw">fn</span> <span class="ident">deref</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) <span class="op">-&gt;</span> <span class="kw-2">&amp;</span><span class="ident">File</span> {
<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">file</span>
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> <span class="ident">DerefMut</span> <span class="kw">for</span> <span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">deref_mut</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-&gt;</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> {
<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>.<span class="ident">file</span>
}
}
<span class="doccomment">/// Returns true if `req` has no `If-Match` header or one which matches `etag`.</span>
<span class="kw">fn</span> <span class="ident">any_match</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>(<span class="ident">etag</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">header</span>::<span class="ident">EntityTag</span><span class="op">&gt;</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="kw">match</span> <span class="ident">req</span>.<span class="ident">get_header</span>::<span class="op">&lt;</span><span class="ident">header</span>::<span class="ident">IfMatch</span><span class="op">&gt;</span>() {
<span class="prelude-val">None</span> <span class="op">|</span> <span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfMatch</span>::<span class="ident">Any</span>) <span class="op">=&gt;</span> <span class="bool-val">true</span>,
<span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfMatch</span>::<span class="ident">Items</span>(<span class="kw-2">ref</span> <span class="ident">items</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">some_etag</span>) <span class="op">=</span> <span class="ident">etag</span> {
<span class="kw">for</span> <span class="ident">item</span> <span class="kw">in</span> <span class="ident">items</span> {
<span class="kw">if</span> <span class="ident">item</span>.<span class="ident">strong_eq</span>(<span class="ident">some_etag</span>) {
<span class="kw">return</span> <span class="bool-val">true</span>;
}
}
}
<span class="bool-val">false</span>
}
}
}
<span class="doccomment">/// Returns true if `req` doesn&#39;t have an `If-None-Match` header matching `req`.</span>
<span class="kw">fn</span> <span class="ident">none_match</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>(<span class="ident">etag</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">header</span>::<span class="ident">EntityTag</span><span class="op">&gt;</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="kw">match</span> <span class="ident">req</span>.<span class="ident">get_header</span>::<span class="op">&lt;</span><span class="ident">header</span>::<span class="ident">IfNoneMatch</span><span class="op">&gt;</span>() {
<span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfNoneMatch</span>::<span class="ident">Any</span>) <span class="op">=&gt;</span> <span class="bool-val">false</span>,
<span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfNoneMatch</span>::<span class="ident">Items</span>(<span class="kw-2">ref</span> <span class="ident">items</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">some_etag</span>) <span class="op">=</span> <span class="ident">etag</span> {
<span class="kw">for</span> <span class="ident">item</span> <span class="kw">in</span> <span class="ident">items</span> {
<span class="kw">if</span> <span class="ident">item</span>.<span class="ident">weak_eq</span>(<span class="ident">some_etag</span>) {
<span class="kw">return</span> <span class="bool-val">false</span>;
}
}
}
<span class="bool-val">true</span>
}
<span class="prelude-val">None</span> <span class="op">=&gt;</span> <span class="bool-val">true</span>,
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">C</span>: <span class="ident">StaticFileConfig</span><span class="op">&gt;</span> <span class="ident">Responder</span> <span class="kw">for</span> <span class="ident">NamedFile</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span> {
<span class="kw">type</span> <span class="ident">Item</span> <span class="op">=</span> <span class="ident">HttpResponse</span>;
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">io</span>::<span class="ident">Error</span>;
<span class="kw">fn</span> <span class="ident">respond_to</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>(<span class="self">self</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponse</span>, <span class="ident">io</span>::<span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">status_code</span> <span class="op">!=</span> <span class="ident">StatusCode</span>::<span class="ident">OK</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">HttpResponse</span>::<span class="ident">build</span>(<span class="self">self</span>.<span class="ident">status_code</span>);
<span class="ident">resp</span>.<span class="ident">set</span>(<span class="ident">header</span>::<span class="ident">ContentType</span>(<span class="self">self</span>.<span class="ident">content_type</span>.<span class="ident">clone</span>()))
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>,
<span class="self">self</span>.<span class="ident">content_disposition</span>.<span class="ident">to_string</span>(),
);
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">current_encoding</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">encoding</span> {
<span class="ident">resp</span>.<span class="ident">content_encoding</span>(<span class="ident">current_encoding</span>);
}
<span class="kw">let</span> <span class="ident">reader</span> <span class="op">=</span> <span class="ident">ChunkedReadFile</span> {
<span class="ident">size</span>: <span class="self">self</span>.<span class="ident">md</span>.<span class="ident">len</span>(),
<span class="ident">offset</span>: <span class="number">0</span>,
<span class="ident">cpu_pool</span>: <span class="self">self</span>.<span class="ident">cpu_pool</span>.<span class="ident">unwrap_or_else</span>(<span class="op">||</span> <span class="ident">req</span>.<span class="ident">cpu_pool</span>().<span class="ident">clone</span>()),
<span class="ident">file</span>: <span class="prelude-val">Some</span>(<span class="self">self</span>.<span class="ident">file</span>),
<span class="ident">fut</span>: <span class="prelude-val">None</span>,
<span class="ident">counter</span>: <span class="number">0</span>,
};
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">streaming</span>(<span class="ident">reader</span>));
}
<span class="kw">if</span> <span class="op">!</span><span class="ident">C</span>::<span class="ident">is_method_allowed</span>(<span class="ident">req</span>.<span class="ident">method</span>()) {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">HttpResponse</span>::<span class="ident">MethodNotAllowed</span>()
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>, <span class="string">&quot;text/plain&quot;</span>)
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">ALLOW</span>, <span class="string">&quot;GET, HEAD&quot;</span>)
.<span class="ident">body</span>(<span class="string">&quot;This resource only supports GET and HEAD.&quot;</span>));
}
<span class="kw">let</span> <span class="ident">etag</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">C</span>::<span class="ident">is_use_etag</span>() { <span class="self">self</span>.<span class="ident">etag</span>() } <span class="kw">else</span> { <span class="prelude-val">None</span> };
<span class="kw">let</span> <span class="ident">last_modified</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">C</span>::<span class="ident">is_use_last_modifier</span>() {
<span class="self">self</span>.<span class="ident">last_modified</span>()
} <span class="kw">else</span> {
<span class="prelude-val">None</span>
};
<span class="comment">// check preconditions</span>
<span class="kw">let</span> <span class="ident">precondition_failed</span> <span class="op">=</span> <span class="kw">if</span> <span class="op">!</span><span class="ident">any_match</span>(<span class="ident">etag</span>.<span class="ident">as_ref</span>(), <span class="ident">req</span>) {
<span class="bool-val">true</span>
} <span class="kw">else</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">m</span>), <span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfUnmodifiedSince</span>(<span class="kw-2">ref</span> <span class="ident">since</span>))) <span class="op">=</span>
(<span class="ident">last_modified</span>, <span class="ident">req</span>.<span class="ident">get_header</span>())
{
<span class="ident">m</span> <span class="op">&gt;</span> <span class="ident">since</span>
} <span class="kw">else</span> {
<span class="bool-val">false</span>
};
<span class="comment">// check last modified</span>
<span class="kw">let</span> <span class="ident">not_modified</span> <span class="op">=</span> <span class="kw">if</span> <span class="op">!</span><span class="ident">none_match</span>(<span class="ident">etag</span>.<span class="ident">as_ref</span>(), <span class="ident">req</span>) {
<span class="bool-val">true</span>
} <span class="kw">else</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">m</span>), <span class="prelude-val">Some</span>(<span class="ident">header</span>::<span class="ident">IfModifiedSince</span>(<span class="kw-2">ref</span> <span class="ident">since</span>))) <span class="op">=</span>
(<span class="ident">last_modified</span>, <span class="ident">req</span>.<span class="ident">get_header</span>())
{
<span class="ident">m</span> <span class="op">&lt;=</span> <span class="ident">since</span>
} <span class="kw">else</span> {
<span class="bool-val">false</span>
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">HttpResponse</span>::<span class="ident">build</span>(<span class="self">self</span>.<span class="ident">status_code</span>);
<span class="ident">resp</span>.<span class="ident">set</span>(<span class="ident">header</span>::<span class="ident">ContentType</span>(<span class="self">self</span>.<span class="ident">content_type</span>.<span class="ident">clone</span>()))
.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>,
<span class="self">self</span>.<span class="ident">content_disposition</span>.<span class="ident">to_string</span>(),
);
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">current_encoding</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">encoding</span> {
<span class="ident">resp</span>.<span class="ident">content_encoding</span>(<span class="ident">current_encoding</span>);
}
<span class="ident">resp</span>.<span class="ident">if_some</span>(<span class="ident">last_modified</span>, <span class="op">|</span><span class="ident">lm</span>, <span class="ident">resp</span><span class="op">|</span> {
<span class="ident">resp</span>.<span class="ident">set</span>(<span class="ident">header</span>::<span class="ident">LastModified</span>(<span class="ident">lm</span>));
}).<span class="ident">if_some</span>(<span class="ident">etag</span>, <span class="op">|</span><span class="ident">etag</span>, <span class="ident">resp</span><span class="op">|</span> {
<span class="ident">resp</span>.<span class="ident">set</span>(<span class="ident">header</span>::<span class="ident">ETag</span>(<span class="ident">etag</span>));
});
<span class="ident">resp</span>.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">ACCEPT_RANGES</span>, <span class="string">&quot;bytes&quot;</span>);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">length</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">md</span>.<span class="ident">len</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">offset</span> <span class="op">=</span> <span class="number">0</span>;
<span class="comment">// check for range header</span>
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">ranges</span>) <span class="op">=</span> <span class="ident">req</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>) {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">rangesheader</span>) <span class="op">=</span> <span class="ident">ranges</span>.<span class="ident">to_str</span>() {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">rangesvec</span>) <span class="op">=</span> <span class="ident">HttpRange</span>::<span class="ident">parse</span>(<span class="ident">rangesheader</span>, <span class="ident">length</span>) {
<span class="ident">length</span> <span class="op">=</span> <span class="ident">rangesvec</span>[<span class="number">0</span>].<span class="ident">length</span>;
<span class="ident">offset</span> <span class="op">=</span> <span class="ident">rangesvec</span>[<span class="number">0</span>].<span class="ident">start</span>;
<span class="ident">resp</span>.<span class="ident">content_encoding</span>(<span class="ident">ContentEncoding</span>::<span class="ident">Identity</span>);
<span class="ident">resp</span>.<span class="ident">header</span>(
<span class="ident">header</span>::<span class="ident">CONTENT_RANGE</span>,
<span class="macro">format</span><span class="macro">!</span>(
<span class="string">&quot;bytes {}-{}/{}&quot;</span>,
<span class="ident">offset</span>,
<span class="ident">offset</span> <span class="op">+</span> <span class="ident">length</span> <span class="op">-</span> <span class="number">1</span>,
<span class="self">self</span>.<span class="ident">md</span>.<span class="ident">len</span>()
),
);
} <span class="kw">else</span> {
<span class="ident">resp</span>.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">CONTENT_RANGE</span>, <span class="macro">format</span><span class="macro">!</span>(<span class="string">&quot;bytes */{}&quot;</span>, <span class="ident">length</span>));
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">status</span>(<span class="ident">StatusCode</span>::<span class="ident">RANGE_NOT_SATISFIABLE</span>).<span class="ident">finish</span>());
};
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">status</span>(<span class="ident">StatusCode</span>::<span class="ident">BAD_REQUEST</span>).<span class="ident">finish</span>());
};
};
<span class="ident">resp</span>.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">CONTENT_LENGTH</span>, <span class="macro">format</span><span class="macro">!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">length</span>));
<span class="kw">if</span> <span class="ident">precondition_failed</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">status</span>(<span class="ident">StatusCode</span>::<span class="ident">PRECONDITION_FAILED</span>).<span class="ident">finish</span>());
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">not_modified</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">status</span>(<span class="ident">StatusCode</span>::<span class="ident">NOT_MODIFIED</span>).<span class="ident">finish</span>());
}
<span class="kw">if</span> <span class="kw-2">*</span><span class="ident">req</span>.<span class="ident">method</span>() <span class="op">==</span> <span class="ident">Method</span>::<span class="ident">HEAD</span> {
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">finish</span>())
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">reader</span> <span class="op">=</span> <span class="ident">ChunkedReadFile</span> {
<span class="ident">offset</span>,
<span class="ident">size</span>: <span class="ident">length</span>,
<span class="ident">cpu_pool</span>: <span class="self">self</span>.<span class="ident">cpu_pool</span>.<span class="ident">unwrap_or_else</span>(<span class="op">||</span> <span class="ident">req</span>.<span class="ident">cpu_pool</span>().<span class="ident">clone</span>()),
<span class="ident">file</span>: <span class="prelude-val">Some</span>(<span class="self">self</span>.<span class="ident">file</span>),
<span class="ident">fut</span>: <span class="prelude-val">None</span>,
<span class="ident">counter</span>: <span class="number">0</span>,
};
<span class="kw">if</span> <span class="ident">offset</span> <span class="op">!=</span> <span class="number">0</span> <span class="op">||</span> <span class="ident">length</span> <span class="op">!=</span> <span class="self">self</span>.<span class="ident">md</span>.<span class="ident">len</span>() {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">status</span>(<span class="ident">StatusCode</span>::<span class="ident">PARTIAL_CONTENT</span>).<span class="ident">streaming</span>(<span class="ident">reader</span>));
};
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">streaming</span>(<span class="ident">reader</span>))
}
}
}
<span class="doccomment">/// A helper created from a `std::fs::File` which reads the file</span>
<span class="doccomment">/// chunk-by-chunk on a `CpuPool`.</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">ChunkedReadFile</span> {
<span class="ident">size</span>: <span class="ident">u64</span>,
<span class="ident">offset</span>: <span class="ident">u64</span>,
<span class="ident">cpu_pool</span>: <span class="ident">CpuPool</span>,
<span class="ident">file</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">File</span><span class="op">&gt;</span>,
<span class="ident">fut</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">CpuFuture</span><span class="op">&lt;</span>(<span class="ident">File</span>, <span class="ident">Bytes</span>), <span class="ident">io</span>::<span class="ident">Error</span><span class="op">&gt;&gt;</span>,
<span class="ident">counter</span>: <span class="ident">u64</span>,
}
<span class="kw">impl</span> <span class="ident">Stream</span> <span class="kw">for</span> <span class="ident">ChunkedReadFile</span> {
<span class="kw">type</span> <span class="ident">Item</span> <span class="op">=</span> <span class="ident">Bytes</span>;
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">Error</span>;
<span class="kw">fn</span> <span class="ident">poll</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-&gt;</span> <span class="ident">Poll</span><span class="op">&lt;</span><span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Bytes</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">fut</span>.<span class="ident">is_some</span>() {
<span class="kw">return</span> <span class="kw">match</span> <span class="self">self</span>.<span class="ident">fut</span>.<span class="ident">as_mut</span>().<span class="ident">unwrap</span>().<span class="ident">poll</span>()<span class="question-mark">?</span> {
<span class="ident">Async</span>::<span class="ident">Ready</span>((<span class="ident">file</span>, <span class="ident">bytes</span>)) <span class="op">=&gt;</span> {
<span class="self">self</span>.<span class="ident">fut</span>.<span class="ident">take</span>();
<span class="self">self</span>.<span class="ident">file</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">file</span>);
<span class="self">self</span>.<span class="ident">offset</span> <span class="op">+=</span> <span class="ident">bytes</span>.<span class="ident">len</span>() <span class="kw">as</span> <span class="ident">u64</span>;
<span class="self">self</span>.<span class="ident">counter</span> <span class="op">+=</span> <span class="ident">bytes</span>.<span class="ident">len</span>() <span class="kw">as</span> <span class="ident">u64</span>;
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">Some</span>(<span class="ident">bytes</span>)))
}
<span class="ident">Async</span>::<span class="ident">NotReady</span> <span class="op">=&gt;</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">NotReady</span>),
};
}
<span class="kw">let</span> <span class="ident">size</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">size</span>;
<span class="kw">let</span> <span class="ident">offset</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">offset</span>;
<span class="kw">let</span> <span class="ident">counter</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">counter</span>;
<span class="kw">if</span> <span class="ident">size</span> <span class="op">==</span> <span class="ident">counter</span> {
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="prelude-val">None</span>))
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">file</span>.<span class="ident">take</span>().<span class="ident">expect</span>(<span class="string">&quot;Use after completion&quot;</span>);
<span class="self">self</span>.<span class="ident">fut</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="self">self</span>.<span class="ident">cpu_pool</span>.<span class="ident">spawn_fn</span>(<span class="kw">move</span> <span class="op">||</span> {
<span class="kw">let</span> <span class="ident">max_bytes</span>: <span class="ident">usize</span>;
<span class="ident">max_bytes</span> <span class="op">=</span> <span class="ident">cmp</span>::<span class="ident">min</span>(<span class="ident">size</span>.<span class="ident">saturating_sub</span>(<span class="ident">counter</span>), <span class="number">65_536</span>) <span class="kw">as</span> <span class="ident">usize</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">buf</span> <span class="op">=</span> <span class="ident">Vec</span>::<span class="ident">with_capacity</span>(<span class="ident">max_bytes</span>);
<span class="ident">file</span>.<span class="ident">seek</span>(<span class="ident">io</span>::<span class="ident">SeekFrom</span>::<span class="ident">Start</span>(<span class="ident">offset</span>))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">nbytes</span> <span class="op">=</span>
<span class="ident">file</span>.<span class="ident">by_ref</span>().<span class="ident">take</span>(<span class="ident">max_bytes</span> <span class="kw">as</span> <span class="ident">u64</span>).<span class="ident">read_to_end</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">buf</span>)<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">nbytes</span> <span class="op">==</span> <span class="number">0</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">io</span>::<span class="ident">ErrorKind</span>::<span class="ident">UnexpectedEof</span>.<span class="ident">into</span>());
}
<span class="prelude-val">Ok</span>((<span class="ident">file</span>, <span class="ident">Bytes</span>::<span class="ident">from</span>(<span class="ident">buf</span>)))
}));
<span class="self">self</span>.<span class="ident">poll</span>()
}
}
}
<span class="kw">type</span> <span class="ident">DirectoryRenderer</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> <span class="op">=</span>
<span class="ident">Fn</span>(<span class="kw-2">&amp;</span><span class="ident">Directory</span>, <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponse</span>, <span class="ident">io</span>::<span class="ident">Error</span><span class="op">&gt;</span>;
<span class="doccomment">/// A directory; responds with the generated directory listing.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Directory</span> {
<span class="doccomment">/// Base directory</span>
<span class="kw">pub</span> <span class="ident">base</span>: <span class="ident">PathBuf</span>,
<span class="doccomment">/// Path of subdirectory to generate listing for</span>
<span class="kw">pub</span> <span class="ident">path</span>: <span class="ident">PathBuf</span>,
}
<span class="kw">impl</span> <span class="ident">Directory</span> {
<span class="doccomment">/// Create a new directory</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">base</span>: <span class="ident">PathBuf</span>, <span class="ident">path</span>: <span class="ident">PathBuf</span>) <span class="op">-&gt;</span> <span class="ident">Directory</span> {
<span class="ident">Directory</span> { <span class="ident">base</span>, <span class="ident">path</span> }
}
<span class="doccomment">/// Is this entry visible from this directory?</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">is_visible</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">entry</span>: <span class="kw-2">&amp;</span><span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">DirEntry</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="kw-2">ref</span> <span class="ident">entry</span>) <span class="op">=</span> <span class="kw-2">*</span><span class="ident">entry</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">name</span>) <span class="op">=</span> <span class="ident">entry</span>.<span class="ident">file_name</span>().<span class="ident">to_str</span>() {
<span class="kw">if</span> <span class="ident">name</span>.<span class="ident">starts_with</span>(<span class="string">&#39;.&#39;</span>) {
<span class="kw">return</span> <span class="bool-val">false</span>;
}
}
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="kw-2">ref</span> <span class="ident">md</span>) <span class="op">=</span> <span class="ident">entry</span>.<span class="ident">metadata</span>() {
<span class="kw">let</span> <span class="ident">ft</span> <span class="op">=</span> <span class="ident">md</span>.<span class="ident">file_type</span>();
<span class="kw">return</span> <span class="ident">ft</span>.<span class="ident">is_dir</span>() <span class="op">||</span> <span class="ident">ft</span>.<span class="ident">is_file</span>() <span class="op">||</span> <span class="ident">ft</span>.<span class="ident">is_symlink</span>();
}
}
<span class="bool-val">false</span>
}
}
<span class="kw">fn</span> <span class="ident">directory_listing</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>(
<span class="ident">dir</span>: <span class="kw-2">&amp;</span><span class="ident">Directory</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponse</span>, <span class="ident">io</span>::<span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">index_of</span> <span class="op">=</span> <span class="macro">format</span><span class="macro">!</span>(<span class="string">&quot;Index of {}&quot;</span>, <span class="ident">req</span>.<span class="ident">path</span>());
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">String</span>::<span class="ident">new</span>();
<span class="kw">let</span> <span class="ident">base</span> <span class="op">=</span> <span class="ident">Path</span>::<span class="ident">new</span>(<span class="ident">req</span>.<span class="ident">path</span>());
<span class="kw">for</span> <span class="ident">entry</span> <span class="kw">in</span> <span class="ident">dir</span>.<span class="ident">path</span>.<span class="ident">read_dir</span>()<span class="question-mark">?</span> {
<span class="kw">if</span> <span class="ident">dir</span>.<span class="ident">is_visible</span>(<span class="kw-2">&amp;</span><span class="ident">entry</span>) {
<span class="kw">let</span> <span class="ident">entry</span> <span class="op">=</span> <span class="ident">entry</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">p</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">entry</span>.<span class="ident">path</span>().<span class="ident">strip_prefix</span>(<span class="kw-2">&amp;</span><span class="ident">dir</span>.<span class="ident">path</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">p</span>) <span class="op">=&gt;</span> <span class="ident">base</span>.<span class="ident">join</span>(<span class="ident">p</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=&gt;</span> <span class="kw">continue</span>,
};
<span class="comment">// show file url as relative to static path</span>
<span class="kw">let</span> <span class="ident">file_url</span> <span class="op">=</span> <span class="ident">utf8_percent_encode</span>(<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">to_string_lossy</span>(), <span class="ident">DEFAULT_ENCODE_SET</span>)
.<span class="ident">to_string</span>();
<span class="comment">// &quot; -- &amp;quot; &amp; -- &amp;amp; &#39; -- &amp;#x27; &lt; -- &amp;lt; &gt; -- &amp;gt;</span>
<span class="kw">let</span> <span class="ident">file_name</span> <span class="op">=</span> <span class="ident">escape_html_entity</span>(<span class="kw-2">&amp;</span><span class="ident">entry</span>.<span class="ident">file_name</span>().<span class="ident">to_string_lossy</span>());
<span class="comment">// if file is a directory, add &#39;/&#39; to the end of the name</span>
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">metadata</span>) <span class="op">=</span> <span class="ident">entry</span>.<span class="ident">metadata</span>() {
<span class="kw">if</span> <span class="ident">metadata</span>.<span class="ident">is_dir</span>() {
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="macro">write</span><span class="macro">!</span>(
<span class="ident">body</span>,
<span class="string">&quot;&lt;li&gt;&lt;a href=\&quot;{}\&quot;&gt;{}/&lt;/a&gt;&lt;/li&gt;&quot;</span>,
<span class="ident">file_url</span>, <span class="ident">file_name</span>
);
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="macro">write</span><span class="macro">!</span>(
<span class="ident">body</span>,
<span class="string">&quot;&lt;li&gt;&lt;a href=\&quot;{}\&quot;&gt;{}&lt;/a&gt;&lt;/li&gt;&quot;</span>,
<span class="ident">file_url</span>, <span class="ident">file_name</span>
);
}
} <span class="kw">else</span> {
<span class="kw">continue</span>;
}
}
}
<span class="kw">let</span> <span class="ident">html</span> <span class="op">=</span> <span class="macro">format</span><span class="macro">!</span>(
<span class="string">&quot;&lt;html&gt;\
&lt;head&gt;&lt;title&gt;{}&lt;/title&gt;&lt;/head&gt;\
&lt;body&gt;&lt;h1&gt;{}&lt;/h1&gt;\
&lt;ul&gt;\
{}\
&lt;/ul&gt;&lt;/body&gt;\n&lt;/html&gt;&quot;</span>,
<span class="ident">index_of</span>, <span class="ident">index_of</span>, <span class="ident">body</span>
);
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse</span>::<span class="prelude-val">Ok</span>()
.<span class="ident">content_type</span>(<span class="string">&quot;text/html; charset=utf-8&quot;</span>)
.<span class="ident">body</span>(<span class="ident">html</span>))
}
<span class="doccomment">/// Static files handling</span>
<span class="doccomment">///</span>
<span class="doccomment">/// `StaticFile` handler must be registered with `App::handler()` method,</span>
<span class="doccomment">/// because `StaticFile` handler requires access sub-path information.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```rust</span>
<span class="doccomment">/// # extern crate actix_web;</span>
<span class="doccomment">/// use actix_web::{fs, App};</span>
<span class="doccomment">///</span>
<span class="doccomment">/// fn main() {</span>
<span class="doccomment">/// let app = App::new()</span>
<span class="doccomment">/// .handler(&quot;/static&quot;, fs::StaticFiles::new(&quot;.&quot;).unwrap())</span>
<span class="doccomment">/// .finish();</span>
<span class="doccomment">/// }</span>
<span class="doccomment">/// ```</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span> <span class="op">=</span> <span class="ident">DefaultConfig</span><span class="op">&gt;</span> {
<span class="ident">directory</span>: <span class="ident">PathBuf</span>,
<span class="ident">index</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">show_index</span>: <span class="ident">bool</span>,
<span class="ident">cpu_pool</span>: <span class="ident">CpuPool</span>,
<span class="ident">default</span>: <span class="ident">Box</span><span class="op">&lt;</span><span class="ident">RouteHandler</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;&gt;</span>,
<span class="ident">renderer</span>: <span class="ident">Box</span><span class="op">&lt;</span><span class="ident">DirectoryRenderer</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;&gt;</span>,
<span class="ident">_chunk_size</span>: <span class="ident">usize</span>,
<span class="ident">_follow_symlinks</span>: <span class="ident">bool</span>,
<span class="ident">_cd_map</span>: <span class="ident">PhantomData</span><span class="op">&lt;</span><span class="ident">C</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span>: <span class="lifetime">&#39;static</span><span class="op">&gt;</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> {
<span class="doccomment">/// Create new `StaticFiles` instance for specified base directory.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// `StaticFile` uses `CpuPool` for blocking filesystem operations.</span>
<span class="doccomment">/// By default pool with 20 threads is used.</span>
<span class="doccomment">/// Pool size can be changed by setting ACTIX_CPU_POOL environment variable.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">PathBuf</span><span class="op">&gt;&gt;</span>(<span class="ident">dir</span>: <span class="ident">T</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="self">Self</span>::<span class="ident">with_config</span>(<span class="ident">dir</span>, <span class="ident">DefaultConfig</span>)
}
<span class="doccomment">/// Create new `StaticFiles` instance for specified base directory and</span>
<span class="doccomment">/// `CpuPool`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">with_pool</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">PathBuf</span><span class="op">&gt;&gt;</span>(
<span class="ident">dir</span>: <span class="ident">T</span>, <span class="ident">pool</span>: <span class="ident">CpuPool</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="self">Self</span>::<span class="ident">with_config_pool</span>(<span class="ident">dir</span>, <span class="ident">pool</span>, <span class="ident">DefaultConfig</span>)
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span>: <span class="lifetime">&#39;static</span>, <span class="ident">C</span>: <span class="ident">StaticFileConfig</span><span class="op">&gt;</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span> {
<span class="doccomment">/// Create new `StaticFiles` instance for specified base directory.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Identical with `new` but allows to specify configiration to use.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">with_config</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">PathBuf</span><span class="op">&gt;&gt;</span>(
<span class="ident">dir</span>: <span class="ident">T</span>, <span class="ident">config</span>: <span class="ident">C</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="comment">// use default CpuPool</span>
<span class="kw">let</span> <span class="ident">pool</span> <span class="op">=</span> { <span class="ident">DEFAULT_CPUPOOL</span>.<span class="ident">lock</span>().<span class="ident">clone</span>() };
<span class="ident">StaticFiles</span>::<span class="ident">with_config_pool</span>(<span class="ident">dir</span>, <span class="ident">pool</span>, <span class="ident">config</span>)
}
<span class="doccomment">/// Create new `StaticFiles` instance for specified base directory with config and</span>
<span class="doccomment">/// `CpuPool`.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">with_config_pool</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">PathBuf</span><span class="op">&gt;&gt;</span>(
<span class="ident">dir</span>: <span class="ident">T</span>, <span class="ident">pool</span>: <span class="ident">CpuPool</span>, <span class="kw">_</span>: <span class="ident">C</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">dir</span> <span class="op">=</span> <span class="ident">dir</span>.<span class="ident">into</span>().<span class="ident">canonicalize</span>()<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="op">!</span><span class="ident">dir</span>.<span class="ident">is_dir</span>() {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">StaticFileError</span>::<span class="ident">IsNotDirectory</span>.<span class="ident">into</span>());
}
<span class="prelude-val">Ok</span>(<span class="ident">StaticFiles</span> {
<span class="ident">directory</span>: <span class="ident">dir</span>,
<span class="ident">index</span>: <span class="prelude-val">None</span>,
<span class="ident">show_index</span>: <span class="bool-val">false</span>,
<span class="ident">cpu_pool</span>: <span class="ident">pool</span>,
<span class="ident">default</span>: <span class="ident">Box</span>::<span class="ident">new</span>(<span class="ident">WrapHandler</span>::<span class="ident">new</span>(<span class="op">|</span><span class="kw">_</span>: <span class="kw-2">&amp;</span><span class="kw">_</span><span class="op">|</span> {
<span class="ident">HttpResponse</span>::<span class="ident">new</span>(<span class="ident">StatusCode</span>::<span class="ident">NOT_FOUND</span>)
})),
<span class="ident">renderer</span>: <span class="ident">Box</span>::<span class="ident">new</span>(<span class="ident">directory_listing</span>),
<span class="ident">_chunk_size</span>: <span class="number">0</span>,
<span class="ident">_follow_symlinks</span>: <span class="bool-val">false</span>,
<span class="ident">_cd_map</span>: <span class="ident">PhantomData</span>,
})
}
<span class="doccomment">/// Show files listing for directories.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// By default show files listing is disabled.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">show_files_listing</span>(<span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-&gt;</span> <span class="self">Self</span> {
<span class="self">self</span>.<span class="ident">show_index</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="self">self</span>
}
<span class="doccomment">/// Set custom directory renderer</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">files_listing_renderer</span><span class="op">&lt;</span><span class="ident">F</span><span class="op">&gt;</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">f</span>: <span class="ident">F</span>) <span class="op">-&gt;</span> <span class="self">Self</span>
<span class="kw">where</span>
<span class="kw">for</span><span class="op">&lt;</span><span class="lifetime">&#39;r</span>, <span class="lifetime">&#39;s</span><span class="op">&gt;</span> <span class="ident">F</span>: <span class="ident">Fn</span>(<span class="kw-2">&amp;</span><span class="lifetime">&#39;r</span> <span class="ident">Directory</span>, <span class="kw-2">&amp;</span><span class="lifetime">&#39;s</span> <span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>)
<span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">HttpResponse</span>, <span class="ident">io</span>::<span class="ident">Error</span><span class="op">&gt;</span>
<span class="op">+</span> <span class="lifetime">&#39;static</span>,
{
<span class="self">self</span>.<span class="ident">renderer</span> <span class="op">=</span> <span class="ident">Box</span>::<span class="ident">new</span>(<span class="ident">f</span>);
<span class="self">self</span>
}
<span class="doccomment">/// Set index file</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Redirects to specific index file for directory &quot;/&quot; instead of</span>
<span class="doccomment">/// showing files listing.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">index_file</span><span class="op">&lt;</span><span class="ident">T</span>: <span class="ident">Into</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;&gt;</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">index</span>: <span class="ident">T</span>) <span class="op">-&gt;</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">index</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">index</span>.<span class="ident">into</span>());
<span class="self">self</span>
}
<span class="doccomment">/// Sets default handler which is used when no matched file could be found.</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">default_handler</span><span class="op">&lt;</span><span class="ident">H</span>: <span class="ident">Handler</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;&gt;</span>(<span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">handler</span>: <span class="ident">H</span>) <span class="op">-&gt;</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">default</span> <span class="op">=</span> <span class="ident">Box</span>::<span class="ident">new</span>(<span class="ident">WrapHandler</span>::<span class="ident">new</span>(<span class="ident">handler</span>));
<span class="self">self</span>
}
<span class="kw">fn</span> <span class="ident">try_handle</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>,
) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AsyncResult</span><span class="op">&lt;</span><span class="ident">HttpResponse</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">tail</span>: <span class="ident">String</span> <span class="op">=</span> <span class="ident">req</span>.<span class="ident">match_info</span>().<span class="ident">query</span>(<span class="string">&quot;tail&quot;</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">relpath</span> <span class="op">=</span> <span class="ident">PathBuf</span>::<span class="ident">from_param</span>(<span class="ident">tail</span>.<span class="ident">trim_left_matches</span>(<span class="string">&#39;/&#39;</span>))<span class="question-mark">?</span>;
<span class="comment">// full filepath</span>
<span class="kw">let</span> <span class="ident">path</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">directory</span>.<span class="ident">join</span>(<span class="kw-2">&amp;</span><span class="ident">relpath</span>).<span class="ident">canonicalize</span>()<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">path</span>.<span class="ident">is_dir</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">redir_index</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">index</span> {
<span class="comment">// TODO: Don&#39;t redirect, just return the index content.</span>
<span class="comment">// TODO: It&#39;d be nice if there were a good usable URL manipulation</span>
<span class="comment">// library</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">new_path</span>: <span class="ident">String</span> <span class="op">=</span> <span class="ident">req</span>.<span class="ident">path</span>().<span class="ident">to_owned</span>();
<span class="kw">if</span> <span class="op">!</span><span class="ident">new_path</span>.<span class="ident">ends_with</span>(<span class="string">&#39;/&#39;</span>) {
<span class="ident">new_path</span>.<span class="ident">push</span>(<span class="string">&#39;/&#39;</span>);
}
<span class="ident">new_path</span>.<span class="ident">push_str</span>(<span class="ident">redir_index</span>);
<span class="ident">HttpResponse</span>::<span class="ident">Found</span>()
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>, <span class="ident">new_path</span>.<span class="ident">as_str</span>())
.<span class="ident">finish</span>()
.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>)
} <span class="kw">else</span> <span class="kw">if</span> <span class="self">self</span>.<span class="ident">show_index</span> {
<span class="kw">let</span> <span class="ident">dir</span> <span class="op">=</span> <span class="ident">Directory</span>::<span class="ident">new</span>(<span class="self">self</span>.<span class="ident">directory</span>.<span class="ident">clone</span>(), <span class="ident">path</span>);
<span class="prelude-val">Ok</span>((<span class="kw-2">*</span><span class="self">self</span>.<span class="ident">renderer</span>)(<span class="kw-2">&amp;</span><span class="ident">dir</span>, <span class="kw-2">&amp;</span><span class="ident">req</span>)<span class="question-mark">?</span>.<span class="ident">into</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">StaticFileError</span>::<span class="ident">IsDirectory</span>.<span class="ident">into</span>())
}
} <span class="kw">else</span> {
<span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="ident">path</span>, <span class="ident">C</span>::<span class="ident">default</span>())<span class="question-mark">?</span>
.<span class="ident">set_cpu_pool</span>(<span class="self">self</span>.<span class="ident">cpu_pool</span>.<span class="ident">clone</span>())
.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>)<span class="question-mark">?</span>
.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>)
}
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">S</span>: <span class="lifetime">&#39;static</span>, <span class="ident">C</span>: <span class="lifetime">&#39;static</span> <span class="op">+</span> <span class="ident">StaticFileConfig</span><span class="op">&gt;</span> <span class="ident">Handler</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">StaticFiles</span><span class="op">&lt;</span><span class="ident">S</span>, <span class="ident">C</span><span class="op">&gt;</span> {
<span class="kw">type</span> <span class="prelude-ty">Result</span> <span class="op">=</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AsyncResult</span><span class="op">&lt;</span><span class="ident">HttpResponse</span><span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span>;
<span class="kw">fn</span> <span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">req</span>: <span class="kw-2">&amp;</span><span class="ident">HttpRequest</span><span class="op">&lt;</span><span class="ident">S</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="self">Self</span>::<span class="prelude-ty">Result</span> {
<span class="self">self</span>.<span class="ident">try_handle</span>(<span class="ident">req</span>).<span class="ident">or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">debug</span><span class="macro">!</span>(<span class="string">&quot;StaticFiles: Failed to handle {}: {}&quot;</span>, <span class="ident">req</span>.<span class="ident">path</span>(), <span class="ident">e</span>);
<span class="prelude-val">Ok</span>(<span class="self">self</span>.<span class="ident">default</span>.<span class="ident">handle</span>(<span class="ident">req</span>))
})
}
}
<span class="doccomment">/// HTTP Range header representation.</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">struct</span> <span class="ident">HttpRange</span> {
<span class="kw">pub</span> <span class="ident">start</span>: <span class="ident">u64</span>,
<span class="kw">pub</span> <span class="ident">length</span>: <span class="ident">u64</span>,
}
<span class="kw">static</span> <span class="ident">PREFIX</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;static</span> <span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;bytes=&quot;</span>;
<span class="kw">const</span> <span class="ident">PREFIX_LEN</span>: <span class="ident">usize</span> <span class="op">=</span> <span class="number">6</span>;
<span class="kw">impl</span> <span class="ident">HttpRange</span> {
<span class="doccomment">/// Parses Range HTTP header string as per RFC 2616.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// `header` is HTTP Range header (e.g. `bytes=bytes=0-9`).</span>
<span class="doccomment">/// `size` is full size of response (file).</span>
<span class="kw">fn</span> <span class="ident">parse</span>(<span class="ident">header</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">size</span>: <span class="ident">u64</span>) <span class="op">-&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">HttpRange</span><span class="op">&gt;</span>, ()<span class="op">&gt;</span> {
<span class="kw">if</span> <span class="ident">header</span>.<span class="ident">is_empty</span>() {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">Vec</span>::<span class="ident">new</span>());
}
<span class="kw">if</span> <span class="op">!</span><span class="ident">header</span>.<span class="ident">starts_with</span>(<span class="ident">PREFIX</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
}
<span class="kw">let</span> <span class="ident">size_sig</span> <span class="op">=</span> <span class="ident">size</span> <span class="kw">as</span> <span class="ident">i64</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">no_overlap</span> <span class="op">=</span> <span class="bool-val">false</span>;
<span class="kw">let</span> <span class="ident">all_ranges</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">HttpRange</span><span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="ident">header</span>[<span class="ident">PREFIX_LEN</span>..]
.<span class="ident">split</span>(<span class="string">&#39;,&#39;</span>)
.<span class="ident">map</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> <span class="ident">x</span>.<span class="ident">trim</span>())
.<span class="ident">filter</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> <span class="op">!</span><span class="ident">x</span>.<span class="ident">is_empty</span>())
.<span class="ident">map</span>(<span class="op">|</span><span class="ident">ra</span><span class="op">|</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">start_end_iter</span> <span class="op">=</span> <span class="ident">ra</span>.<span class="ident">split</span>(<span class="string">&#39;-&#39;</span>);
<span class="kw">let</span> <span class="ident">start_str</span> <span class="op">=</span> <span class="ident">start_end_iter</span>.<span class="ident">next</span>().<span class="ident">ok_or</span>(())<span class="question-mark">?</span>.<span class="ident">trim</span>();
<span class="kw">let</span> <span class="ident">end_str</span> <span class="op">=</span> <span class="ident">start_end_iter</span>.<span class="ident">next</span>().<span class="ident">ok_or</span>(())<span class="question-mark">?</span>.<span class="ident">trim</span>();
<span class="kw">if</span> <span class="ident">start_str</span>.<span class="ident">is_empty</span>() {
<span class="comment">// If no start is specified, end specifies the</span>
<span class="comment">// range start relative to the end of the file.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">length</span>: <span class="ident">i64</span> <span class="op">=</span> <span class="macro">try</span><span class="macro">!</span>(<span class="ident">end_str</span>.<span class="ident">parse</span>().<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> ()));
<span class="kw">if</span> <span class="ident">length</span> <span class="op">&gt;</span> <span class="ident">size_sig</span> {
<span class="ident">length</span> <span class="op">=</span> <span class="ident">size_sig</span>;
}
<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(<span class="ident">HttpRange</span> {
<span class="ident">start</span>: (<span class="ident">size_sig</span> <span class="op">-</span> <span class="ident">length</span>) <span class="kw">as</span> <span class="ident">u64</span>,
<span class="ident">length</span>: <span class="ident">length</span> <span class="kw">as</span> <span class="ident">u64</span>,
}))
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">start</span>: <span class="ident">i64</span> <span class="op">=</span> <span class="ident">start_str</span>.<span class="ident">parse</span>().<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> ())<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">start</span> <span class="op">&lt;</span> <span class="number">0</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
}
<span class="kw">if</span> <span class="ident">start</span> <span class="op">&gt;=</span> <span class="ident">size_sig</span> {
<span class="ident">no_overlap</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>);
}
<span class="kw">let</span> <span class="ident">length</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">end_str</span>.<span class="ident">is_empty</span>() {
<span class="comment">// If no end is specified, range extends to end of the file.</span>
<span class="ident">size_sig</span> <span class="op">-</span> <span class="ident">start</span>
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">end</span>: <span class="ident">i64</span> <span class="op">=</span> <span class="ident">end_str</span>.<span class="ident">parse</span>().<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> ())<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">start</span> <span class="op">&gt;</span> <span class="ident">end</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
}
<span class="kw">if</span> <span class="ident">end</span> <span class="op">&gt;=</span> <span class="ident">size_sig</span> {
<span class="ident">end</span> <span class="op">=</span> <span class="ident">size_sig</span> <span class="op">-</span> <span class="number">1</span>;
}
<span class="ident">end</span> <span class="op">-</span> <span class="ident">start</span> <span class="op">+</span> <span class="number">1</span>
};
<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="ident">start</span> <span class="kw">as</span> <span class="ident">u64</span>,
<span class="ident">length</span>: <span class="ident">length</span> <span class="kw">as</span> <span class="ident">u64</span>,
}))
}
}).<span class="ident">collect</span>::<span class="op">&lt;</span><span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="kw">_</span>, <span class="kw">_</span><span class="op">&gt;&gt;</span>()<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">ranges</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">HttpRange</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">all_ranges</span>.<span class="ident">into_iter</span>().<span class="ident">filter_map</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> <span class="ident">x</span>).<span class="ident">collect</span>();
<span class="kw">if</span> <span class="ident">no_overlap</span> <span class="op">&amp;&amp;</span> <span class="ident">ranges</span>.<span class="ident">is_empty</span>() {
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
}
<span class="prelude-val">Ok</span>(<span class="ident">ranges</span>)
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">fs</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">application</span>::<span class="ident">App</span>;
<span class="kw">use</span> <span class="ident">body</span>::{<span class="ident">Binary</span>, <span class="ident">Body</span>};
<span class="kw">use</span> <span class="ident">http</span>::{<span class="ident">header</span>, <span class="ident">Method</span>, <span class="ident">StatusCode</span>};
<span class="kw">use</span> <span class="ident">test</span>::{<span class="self">self</span>, <span class="ident">TestRequest</span>};
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_file_extension_to_mime</span>() {
<span class="kw">let</span> <span class="ident">m</span> <span class="op">=</span> <span class="ident">file_extension_to_mime</span>(<span class="string">&quot;jpg&quot;</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">m</span>, <span class="ident">mime</span>::<span class="ident">IMAGE_JPEG</span>);
<span class="kw">let</span> <span class="ident">m</span> <span class="op">=</span> <span class="ident">file_extension_to_mime</span>(<span class="string">&quot;invalid extension!!&quot;</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">m</span>, <span class="ident">mime</span>::<span class="ident">APPLICATION_OCTET_STREAM</span>);
<span class="kw">let</span> <span class="ident">m</span> <span class="op">=</span> <span class="ident">file_extension_to_mime</span>(<span class="string">&quot;&quot;</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">m</span>, <span class="ident">mime</span>::<span class="ident">APPLICATION_OCTET_STREAM</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_text</span>() {
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;test--&quot;</span>).<span class="ident">is_err</span>());
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;Cargo.toml&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;text/x-toml&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;inline; filename=\&quot;Cargo.toml\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_set_content_type</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;Cargo.toml&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_content_type</span>(<span class="ident">mime</span>::<span class="ident">TEXT_XML</span>)
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;text/xml&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;inline; filename=\&quot;Cargo.toml\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_image</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;tests/test.png&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;image/png&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;inline; filename=\&quot;test.png\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_image_attachment</span>() {
<span class="kw">use</span> <span class="ident">header</span>::{<span class="ident">ContentDisposition</span>, <span class="ident">DispositionParam</span>, <span class="ident">DispositionType</span>};
<span class="kw">let</span> <span class="ident">cd</span> <span class="op">=</span> <span class="ident">ContentDisposition</span> {
<span class="ident">disposition</span>: <span class="ident">DispositionType</span>::<span class="ident">Attachment</span>,
<span class="ident">parameters</span>: <span class="macro">vec</span><span class="macro">!</span>[<span class="ident">DispositionParam</span>::<span class="ident">Filename</span>(<span class="ident">String</span>::<span class="ident">from</span>(<span class="string">&quot;test.png&quot;</span>))],
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;tests/test.png&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_content_disposition</span>(<span class="ident">cd</span>)
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;image/png&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;attachment; filename=\&quot;test.png\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">AllAttachmentConfig</span>;
<span class="kw">impl</span> <span class="ident">StaticFileConfig</span> <span class="kw">for</span> <span class="ident">AllAttachmentConfig</span> {
<span class="kw">fn</span> <span class="ident">content_disposition_map</span>(<span class="ident">_typ</span>: <span class="ident">mime</span>::<span class="ident">Name</span>) <span class="op">-&gt;</span> <span class="ident">DispositionType</span> {
<span class="ident">DispositionType</span>::<span class="ident">Attachment</span>
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">AllInlineConfig</span>;
<span class="kw">impl</span> <span class="ident">StaticFileConfig</span> <span class="kw">for</span> <span class="ident">AllInlineConfig</span> {
<span class="kw">fn</span> <span class="ident">content_disposition_map</span>(<span class="ident">_typ</span>: <span class="ident">mime</span>::<span class="ident">Name</span>) <span class="op">-&gt;</span> <span class="ident">DispositionType</span> {
<span class="ident">DispositionType</span>::<span class="ident">Inline</span>
}
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_image_attachment_and_custom_config</span>() {
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="string">&quot;tests/test.png&quot;</span>, <span class="ident">AllAttachmentConfig</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;image/png&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;attachment; filename=\&quot;test.png\&quot;&quot;</span>
);
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="string">&quot;tests/test.png&quot;</span>, <span class="ident">AllInlineConfig</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;image/png&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;inline; filename=\&quot;test.png\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_binary</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;tests/test.binary&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;application/octet-stream&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;attachment; filename=\&quot;test.binary\&quot;&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_status_code_text</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;Cargo.toml&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">set_status_code</span>(<span class="ident">StatusCode</span>::<span class="ident">NOT_FOUND</span>)
.<span class="ident">set_cpu_pool</span>(<span class="ident">CpuPool</span>::<span class="ident">new</span>(<span class="number">1</span>));
{
<span class="ident">file</span>.<span class="ident">file</span>();
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">file</span>;
}
{
<span class="kw">let</span> <span class="ident">_f</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">File</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">file</span>;
}
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;text/x-toml&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_DISPOSITION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;inline; filename=\&quot;Cargo.toml\&quot;&quot;</span>
);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">NOT_FOUND</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_ranges_status_code</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>().<span class="ident">handler</span>(
<span class="string">&quot;test&quot;</span>,
<span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;Cargo.toml&quot;</span>),
)
});
<span class="comment">// Valid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/Cargo.toml&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=10-20&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">PARTIAL_CONTENT</span>);
<span class="comment">// Invalid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/Cargo.toml&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=1-0&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">RANGE_NOT_SATISFIABLE</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_content_range_headers</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>().<span class="ident">handler</span>(
<span class="string">&quot;test&quot;</span>,
<span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">index_file</span>(<span class="string">&quot;tests/test.binary&quot;</span>),
)
});
<span class="comment">// Valid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=10-20&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">contentrange</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_RANGE</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">contentrange</span>, <span class="string">&quot;bytes 10-20/100&quot;</span>);
<span class="comment">// Invalid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=10-5&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">contentrange</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_RANGE</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">contentrange</span>, <span class="string">&quot;bytes */100&quot;</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_content_length_headers</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>().<span class="ident">handler</span>(
<span class="string">&quot;test&quot;</span>,
<span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">index_file</span>(<span class="string">&quot;tests/test.binary&quot;</span>),
)
});
<span class="comment">// Valid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=10-20&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">contentlength</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_LENGTH</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">contentlength</span>, <span class="string">&quot;11&quot;</span>);
<span class="comment">// Invalid range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">header</span>(<span class="ident">header</span>::<span class="ident">RANGE</span>, <span class="string">&quot;bytes=10-8&quot;</span>)
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">contentlength</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_LENGTH</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">contentlength</span>, <span class="string">&quot;0&quot;</span>);
<span class="comment">// Without range header</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">no_default_headers</span>()
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">contentlength</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_LENGTH</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">contentlength</span>, <span class="string">&quot;100&quot;</span>);
<span class="comment">// chunked</span>
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/t%65st/tests/test.binary&quot;</span>))
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
{
<span class="kw">let</span> <span class="ident">te</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">TRANSFER_ENCODING</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">te</span>, <span class="string">&quot;chunked&quot;</span>);
}
<span class="kw">let</span> <span class="ident">bytes</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">response</span>.<span class="ident">body</span>()).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Bytes</span>::<span class="ident">from</span>(<span class="ident">fs</span>::<span class="ident">read</span>(<span class="string">&quot;tests/test.binary&quot;</span>).<span class="ident">unwrap</span>());
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">bytes</span>, <span class="ident">data</span>);
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">OnlyMethodHeadConfig</span>;
<span class="kw">impl</span> <span class="ident">StaticFileConfig</span> <span class="kw">for</span> <span class="ident">OnlyMethodHeadConfig</span> {
<span class="kw">fn</span> <span class="ident">is_method_allowed</span>(<span class="ident">method</span>: <span class="kw-2">&amp;</span><span class="ident">Method</span>) <span class="op">-&gt;</span> <span class="ident">bool</span> {
<span class="kw">match</span> <span class="kw-2">*</span><span class="ident">method</span> {
<span class="ident">Method</span>::<span class="ident">HEAD</span> <span class="op">=&gt;</span> <span class="bool-val">true</span>,
<span class="kw">_</span> <span class="op">=&gt;</span> <span class="bool-val">false</span>,
}
}
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_not_allowed</span>() {
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span>
<span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="string">&quot;Cargo.toml&quot;</span>, <span class="ident">OnlyMethodHeadConfig</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">POST</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">METHOD_NOT_ALLOWED</span>);
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span>
<span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="string">&quot;Cargo.toml&quot;</span>, <span class="ident">OnlyMethodHeadConfig</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">PUT</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">METHOD_NOT_ALLOWED</span>);
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span>
<span class="ident">NamedFile</span>::<span class="ident">open_with_config</span>(<span class="string">&quot;Cargo.toml&quot;</span>, <span class="ident">OnlyMethodHeadConfig</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">GET</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">METHOD_NOT_ALLOWED</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_content_encoding</span>() {
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">GET</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;Cargo.toml&quot;</span>).<span class="ident">unwrap</span>();
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">file</span>.<span class="ident">encoding</span>.<span class="ident">is_none</span>());
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>
.<span class="ident">set_content_encoding</span>(<span class="ident">ContentEncoding</span>::<span class="ident">Identity</span>)
.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>)
.<span class="ident">unwrap</span>();
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">content_encoding</span>().<span class="ident">is_some</span>());
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">content_encoding</span>().<span class="ident">unwrap</span>().<span class="ident">as_str</span>(), <span class="string">&quot;identity&quot;</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_named_file_any_method</span>() {
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">method</span>(<span class="ident">Method</span>::<span class="ident">POST</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">NamedFile</span>::<span class="ident">open</span>(<span class="string">&quot;Cargo.toml&quot;</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">file</span>.<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">OK</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_static_files</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">st</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">show_files_listing</span>();
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">with_uri</span>(<span class="string">&quot;/missing&quot;</span>)
.<span class="ident">param</span>(<span class="string">&quot;tail&quot;</span>, <span class="string">&quot;missing&quot;</span>)
.<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">NOT_FOUND</span>);
<span class="ident">st</span>.<span class="ident">show_index</span> <span class="op">=</span> <span class="bool-val">false</span>;
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">NOT_FOUND</span>);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">param</span>(<span class="string">&quot;tail&quot;</span>, <span class="string">&quot;&quot;</span>).<span class="ident">finish</span>();
<span class="ident">st</span>.<span class="ident">show_index</span> <span class="op">=</span> <span class="bool-val">true</span>;
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">CONTENT_TYPE</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;text/html; charset=utf-8&quot;</span>
);
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">body</span>().<span class="ident">is_binary</span>());
<span class="macro">assert</span><span class="macro">!</span>(<span class="macro">format</span><span class="macro">!</span>(<span class="string">&quot;{:?}&quot;</span>, <span class="ident">resp</span>.<span class="ident">body</span>()).<span class="ident">contains</span>(<span class="string">&quot;README.md&quot;</span>));
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_static_files_bad_directory</span>() {
<span class="kw">let</span> <span class="ident">st</span>: <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span>()<span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;missing&quot;</span>);
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">st</span>.<span class="ident">is_err</span>());
<span class="kw">let</span> <span class="ident">st</span>: <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">StaticFiles</span><span class="op">&lt;</span>()<span class="op">&gt;</span>, <span class="ident">Error</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;Cargo.toml&quot;</span>);
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">st</span>.<span class="ident">is_err</span>());
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_default_handler_file_missing</span>() {
<span class="kw">let</span> <span class="ident">st</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">default_handler</span>(<span class="op">|</span><span class="kw">_</span>: <span class="kw-2">&amp;</span><span class="kw">_</span><span class="op">|</span> <span class="string">&quot;default content&quot;</span>);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">with_uri</span>(<span class="string">&quot;/missing&quot;</span>)
.<span class="ident">param</span>(<span class="string">&quot;tail&quot;</span>, <span class="string">&quot;missing&quot;</span>)
.<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">OK</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">body</span>(),
<span class="kw-2">&amp;</span><span class="ident">Body</span>::<span class="ident">Binary</span>(<span class="ident">Binary</span>::<span class="ident">Slice</span>(<span class="string">b&quot;default content&quot;</span>))
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_redirect_to_index</span>() {
<span class="kw">let</span> <span class="ident">st</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;index.html&quot;</span>);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">uri</span>(<span class="string">&quot;/tests&quot;</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;/tests/index.html&quot;</span>
);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">uri</span>(<span class="string">&quot;/tests/&quot;</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;/tests/index.html&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_redirect_to_index_nested</span>() {
<span class="kw">let</span> <span class="ident">st</span> <span class="op">=</span> <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;mod.rs&quot;</span>);
<span class="kw">let</span> <span class="ident">req</span> <span class="op">=</span> <span class="ident">TestRequest</span>::<span class="ident">default</span>().<span class="ident">uri</span>(<span class="string">&quot;/src/client&quot;</span>).<span class="ident">finish</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">st</span>.<span class="ident">handle</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">respond_to</span>(<span class="kw-2">&amp;</span><span class="ident">req</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">as_msg</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(
<span class="ident">resp</span>.<span class="ident">headers</span>().<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>).<span class="ident">unwrap</span>(),
<span class="string">&quot;/src/client/mod.rs&quot;</span>
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">integration_redirect_to_index_with_prefix</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>()
.<span class="ident">prefix</span>(<span class="string">&quot;public&quot;</span>)
.<span class="ident">handler</span>(<span class="string">&quot;/&quot;</span>, <span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;Cargo.toml&quot;</span>))
});
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">get</span>().<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/public&quot;</span>)).<span class="ident">finish</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="kw">let</span> <span class="ident">loc</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">loc</span>, <span class="string">&quot;/public/Cargo.toml&quot;</span>);
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">get</span>().<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/public/&quot;</span>)).<span class="ident">finish</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="kw">let</span> <span class="ident">loc</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">loc</span>, <span class="string">&quot;/public/Cargo.toml&quot;</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">integration_redirect_to_index</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>().<span class="ident">handler</span>(
<span class="string">&quot;test&quot;</span>,
<span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;Cargo.toml&quot;</span>),
)
});
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">get</span>().<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/test&quot;</span>)).<span class="ident">finish</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="kw">let</span> <span class="ident">loc</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">loc</span>, <span class="string">&quot;/test/Cargo.toml&quot;</span>);
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">get</span>().<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/test/&quot;</span>)).<span class="ident">finish</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">FOUND</span>);
<span class="kw">let</span> <span class="ident">loc</span> <span class="op">=</span> <span class="ident">response</span>
.<span class="ident">headers</span>()
.<span class="ident">get</span>(<span class="ident">header</span>::<span class="ident">LOCATION</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_str</span>()
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">loc</span>, <span class="string">&quot;/test/Cargo.toml&quot;</span>);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">integration_percent_encoded</span>() {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">srv</span> <span class="op">=</span> <span class="ident">test</span>::<span class="ident">TestServer</span>::<span class="ident">with_factory</span>(<span class="op">||</span> {
<span class="ident">App</span>::<span class="ident">new</span>().<span class="ident">handler</span>(
<span class="string">&quot;test&quot;</span>,
<span class="ident">StaticFiles</span>::<span class="ident">new</span>(<span class="string">&quot;.&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">index_file</span>(<span class="string">&quot;Cargo.toml&quot;</span>),
)
});
<span class="kw">let</span> <span class="ident">request</span> <span class="op">=</span> <span class="ident">srv</span>
.<span class="ident">get</span>()
.<span class="ident">uri</span>(<span class="ident">srv</span>.<span class="ident">url</span>(<span class="string">&quot;/test/%43argo.toml&quot;</span>))
.<span class="ident">finish</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">srv</span>.<span class="ident">execute</span>(<span class="ident">request</span>.<span class="ident">send</span>()).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">response</span>.<span class="ident">status</span>(), <span class="ident">StatusCode</span>::<span class="ident">OK</span>);
}
<span class="kw">struct</span> <span class="ident">T</span>(<span class="kw-2">&amp;</span><span class="lifetime">&#39;static</span> <span class="ident">str</span>, <span class="ident">u64</span>, <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">HttpRange</span><span class="op">&gt;</span>);
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_parse</span>() {
<span class="kw">let</span> <span class="ident">tests</span> <span class="op">=</span> <span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">T</span>(<span class="string">&quot;&quot;</span>, <span class="number">0</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;&quot;</span>, <span class="number">1000</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;foo&quot;</span>, <span class="number">0</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=&quot;</span>, <span class="number">0</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=7&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes= 7 &quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=1-&quot;</span>, <span class="number">0</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=5-4&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=0-2,5-4&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=2-5,4-3&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=--5,4--3&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=A-&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=A- &quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=A-Z&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes= -Z&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=5-Z&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=Ran-dom, garbage&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes=0x01-0x02&quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes= &quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(<span class="string">&quot;bytes= , , , &quot;</span>, <span class="number">10</span>, <span class="macro">vec</span><span class="macro">!</span>[]),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-9&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">10</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">10</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=5-&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">5</span>,
<span class="ident">length</span>: <span class="number">5</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-20&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">10</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=15-,0-5&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">6</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=1-2,5-&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">1</span>,
<span class="ident">length</span>: <span class="number">2</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">5</span>,
<span class="ident">length</span>: <span class="number">5</span>,
},
],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=-2 , 7-&quot;</span>,
<span class="number">11</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">9</span>,
<span class="ident">length</span>: <span class="number">2</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">7</span>,
<span class="ident">length</span>: <span class="number">4</span>,
},
],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-0 ,2-2, 7-&quot;</span>,
<span class="number">11</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">1</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">2</span>,
<span class="ident">length</span>: <span class="number">1</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">7</span>,
<span class="ident">length</span>: <span class="number">4</span>,
},
],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=-5&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">5</span>,
<span class="ident">length</span>: <span class="number">5</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=-15&quot;</span>,
<span class="number">10</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">10</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-499&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">500</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=500-999&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">500</span>,
<span class="ident">length</span>: <span class="number">500</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=-500&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">9500</span>,
<span class="ident">length</span>: <span class="number">500</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=9500-&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">9500</span>,
<span class="ident">length</span>: <span class="number">500</span>,
}],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=0-0,-1&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">0</span>,
<span class="ident">length</span>: <span class="number">1</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">9999</span>,
<span class="ident">length</span>: <span class="number">1</span>,
},
],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=500-600,601-999&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">500</span>,
<span class="ident">length</span>: <span class="number">101</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">601</span>,
<span class="ident">length</span>: <span class="number">399</span>,
},
],
),
<span class="ident">T</span>(
<span class="string">&quot;bytes=500-700,601-999&quot;</span>,
<span class="number">10000</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">500</span>,
<span class="ident">length</span>: <span class="number">201</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">601</span>,
<span class="ident">length</span>: <span class="number">399</span>,
},
],
),
<span class="comment">// Match Apache laxity:</span>
<span class="ident">T</span>(
<span class="string">&quot;bytes= 1 -2 , 4- 5, 7 - 8 , ,,&quot;</span>,
<span class="number">11</span>,
<span class="macro">vec</span><span class="macro">!</span>[
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">1</span>,
<span class="ident">length</span>: <span class="number">2</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">4</span>,
<span class="ident">length</span>: <span class="number">2</span>,
},
<span class="ident">HttpRange</span> {
<span class="ident">start</span>: <span class="number">7</span>,
<span class="ident">length</span>: <span class="number">2</span>,
},
],
),
];
<span class="kw">for</span> <span class="ident">t</span> <span class="kw">in</span> <span class="ident">tests</span> {
<span class="kw">let</span> <span class="ident">header</span> <span class="op">=</span> <span class="ident">t</span>.<span class="number">0</span>;
<span class="kw">let</span> <span class="ident">size</span> <span class="op">=</span> <span class="ident">t</span>.<span class="number">1</span>;
<span class="kw">let</span> <span class="ident">expected</span> <span class="op">=</span> <span class="ident">t</span>.<span class="number">2</span>;
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">HttpRange</span>::<span class="ident">parse</span>(<span class="ident">header</span>, <span class="ident">size</span>);
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_err</span>() {
<span class="kw">if</span> <span class="ident">expected</span>.<span class="ident">is_empty</span>() {
<span class="kw">continue</span>;
} <span class="kw">else</span> {
<span class="macro">assert</span><span class="macro">!</span>(
<span class="bool-val">false</span>,
<span class="string">&quot;parse({}, {}) returned error {:?}&quot;</span>,
<span class="ident">header</span>,
<span class="ident">size</span>,
<span class="ident">res</span>.<span class="ident">unwrap_err</span>()
);
}
}
<span class="kw">let</span> <span class="ident">got</span> <span class="op">=</span> <span class="ident">res</span>.<span class="ident">unwrap</span>();
<span class="kw">if</span> <span class="ident">got</span>.<span class="ident">len</span>() <span class="op">!=</span> <span class="ident">expected</span>.<span class="ident">len</span>() {
<span class="macro">assert</span><span class="macro">!</span>(
<span class="bool-val">false</span>,
<span class="string">&quot;len(parseRange({}, {})) = {}, want {}&quot;</span>,
<span class="ident">header</span>,
<span class="ident">size</span>,
<span class="ident">got</span>.<span class="ident">len</span>(),
<span class="ident">expected</span>.<span class="ident">len</span>()
);
<span class="kw">continue</span>;
}
<span class="kw">for</span> <span class="ident">i</span> <span class="kw">in</span> <span class="number">0</span>..<span class="ident">expected</span>.<span class="ident">len</span>() {
<span class="kw">if</span> <span class="ident">got</span>[<span class="ident">i</span>].<span class="ident">start</span> <span class="op">!=</span> <span class="ident">expected</span>[<span class="ident">i</span>].<span class="ident">start</span> {
<span class="macro">assert</span><span class="macro">!</span>(
<span class="bool-val">false</span>,
<span class="string">&quot;parseRange({}, {})[{}].start = {}, want {}&quot;</span>,
<span class="ident">header</span>, <span class="ident">size</span>, <span class="ident">i</span>, <span class="ident">got</span>[<span class="ident">i</span>].<span class="ident">start</span>, <span class="ident">expected</span>[<span class="ident">i</span>].<span class="ident">start</span>
)
}
<span class="kw">if</span> <span class="ident">got</span>[<span class="ident">i</span>].<span class="ident">length</span> <span class="op">!=</span> <span class="ident">expected</span>[<span class="ident">i</span>].<span class="ident">length</span> {
<span class="macro">assert</span><span class="macro">!</span>(
<span class="bool-val">false</span>,
<span class="string">&quot;parseRange({}, {})[{}].length = {}, want {}&quot;</span>,
<span class="ident">header</span>, <span class="ident">size</span>, <span class="ident">i</span>, <span class="ident">got</span>[<span class="ident">i</span>].<span class="ident">length</span>, <span class="ident">expected</span>[<span class="ident">i</span>].<span class="ident">length</span>
)
}
}
}
}
}
</pre>
</section><section id="search" class="content hidden"></section><section class="footer"></section><aside id="help" class="hidden"><div><h1 class="hidden">Help</h1><div class="shortcuts"><h2>Keyboard Shortcuts</h2><dl><dt><kbd>?</kbd></dt><dd>Show this help dialog</dd><dt><kbd>S</kbd></dt><dd>Focus the search field</dd><dt><kbd></kbd></dt><dd>Move up in search results</dd><dt><kbd></kbd></dt><dd>Move down in search results</dd><dt><kbd></kbd></dt><dd>Switch tab</dd><dt><kbd>&#9166;</kbd></dt><dd>Go to active search result</dd><dt><kbd>+</kbd></dt><dd>Expand all sections</dd><dt><kbd>-</kbd></dt><dd>Collapse all sections</dd></dl></div><div class="infos"><h2>Search Tricks</h2><p>Prefix searches with a type followed by a colon (e.g. <code>fn:</code>) to restrict the search to a given type.</p><p>Accepted types are: <code>fn</code>, <code>mod</code>, <code>struct</code>, <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, and <code>const</code>.</p><p>Search functions by type signature (e.g. <code>vec -> usize</code> or <code>* -> vec</code>)</p><p>Search multiple things at once by splitting your query with comma (e.g. <code>str,u8</code> or <code>String,struct:Vec,test</code>)</p></div></div></aside><script>window.rootPath = "../../";window.currentCrate = "actix_web";</script><script src="../../aliases.js"></script><script src="../../main.js"></script><script defer src="../../search-index.js"></script></body></html>