mirror of
https://github.com/actix/actix-website
synced 2025-07-01 17:15:08 +02:00
update actix-web api docs
This commit is contained in:
@ -298,74 +298,47 @@
|
||||
<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>
|
||||
</pre><pre class="rust ">
|
||||
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">net</span>::{<span class="ident">Shutdown</span>, <span class="ident">SocketAddr</span>};
|
||||
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">rc</span>::<span class="ident">Rc</span>;
|
||||
<span class="kw">use</span> <span class="ident">std</span>::{<span class="ident">io</span>, <span class="ident">ptr</span>, <span class="ident">time</span>};
|
||||
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">net</span>::<span class="ident">Shutdown</span>;
|
||||
<span class="kw">use</span> <span class="ident">std</span>::{<span class="ident">io</span>, <span class="ident">mem</span>, <span class="ident">time</span>};
|
||||
|
||||
<span class="kw">use</span> <span class="ident">bytes</span>::{<span class="ident">Buf</span>, <span class="ident">BufMut</span>, <span class="ident">Bytes</span>, <span class="ident">BytesMut</span>};
|
||||
<span class="kw">use</span> <span class="ident">bytes</span>::{<span class="ident">Buf</span>, <span class="ident">BufMut</span>, <span class="ident">BytesMut</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="kw">use</span> <span class="ident">tokio_io</span>::{<span class="ident">AsyncRead</span>, <span class="ident">AsyncWrite</span>};
|
||||
<span class="kw">use</span> <span class="ident">tokio_timer</span>::<span class="ident">Delay</span>;
|
||||
|
||||
<span class="kw">use</span> <span class="kw">super</span>::<span class="ident">settings</span>::<span class="ident">WorkerSettings</span>;
|
||||
<span class="kw">use</span> <span class="kw">super</span>::<span class="ident">error</span>::<span class="ident">HttpDispatchError</span>;
|
||||
<span class="kw">use</span> <span class="kw">super</span>::<span class="ident">settings</span>::<span class="ident">ServiceConfig</span>;
|
||||
<span class="kw">use</span> <span class="kw">super</span>::{<span class="ident">h1</span>, <span class="ident">h2</span>, <span class="ident">HttpHandler</span>, <span class="ident">IoStream</span>};
|
||||
<span class="kw">use</span> <span class="ident">http</span>::<span class="ident">StatusCode</span>;
|
||||
|
||||
<span class="kw">const</span> <span class="ident">HTTP2_PREFACE</span>: [<span class="ident">u8</span>; <span class="number">14</span>] <span class="op">=</span> <span class="kw-2">*</span><span class="string">b"PRI * HTTP/2.0"</span>;
|
||||
|
||||
<span class="kw">enum</span> <span class="ident">HttpProtocol</span><span class="op"><</span><span class="ident">T</span>: <span class="ident">IoStream</span>, <span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span><span class="op">></span> {
|
||||
<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>),
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">enum</span> <span class="ident">HttpProtocol</span><span class="op"><</span><span class="ident">T</span>: <span class="ident">IoStream</span>, <span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span><span class="op">></span> {
|
||||
<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1Dispatcher</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>),
|
||||
<span class="ident">H2</span>(<span class="ident">h2</span>::<span class="ident">Http2</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>),
|
||||
<span class="ident">Unknown</span>(<span class="ident">Rc</span><span class="op"><</span><span class="ident">WorkerSettings</span><span class="op"><</span><span class="ident">H</span><span class="op">>></span>, <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">SocketAddr</span><span class="op">></span>, <span class="ident">T</span>, <span class="ident">BytesMut</span>),
|
||||
<span class="ident">Unknown</span>(<span class="ident">ServiceConfig</span><span class="op"><</span><span class="ident">H</span><span class="op">></span>, <span class="ident">T</span>, <span class="ident">BytesMut</span>),
|
||||
<span class="prelude-val">None</span>,
|
||||
}
|
||||
|
||||
<span class="comment">// impl<T: IoStream, H: HttpHandler + 'static> HttpProtocol<T, H> {</span>
|
||||
<span class="comment">// fn shutdown_(&mut self) {</span>
|
||||
<span class="comment">// match self {</span>
|
||||
<span class="comment">// HttpProtocol::H1(ref mut h1) => {</span>
|
||||
<span class="comment">// let io = h1.io();</span>
|
||||
<span class="comment">// let _ = IoStream::set_linger(io, Some(time::Duration::new(0, 0)));</span>
|
||||
<span class="comment">// let _ = IoStream::shutdown(io, Shutdown::Both);</span>
|
||||
<span class="comment">// }</span>
|
||||
<span class="comment">// HttpProtocol::H2(ref mut h2) => h2.shutdown(),</span>
|
||||
<span class="comment">// HttpProtocol::Unknown(_, io, _) => {</span>
|
||||
<span class="comment">// let _ = IoStream::set_linger(io, Some(time::Duration::new(0, 0)));</span>
|
||||
<span class="comment">// let _ = IoStream::shutdown(io, Shutdown::Both);</span>
|
||||
<span class="comment">// }</span>
|
||||
<span class="comment">// HttpProtocol::None => (),</span>
|
||||
<span class="comment">// }</span>
|
||||
<span class="comment">// }</span>
|
||||
<span class="comment">// }</span>
|
||||
|
||||
<span class="kw">enum</span> <span class="ident">ProtocolKind</span> {
|
||||
<span class="ident">Http1</span>,
|
||||
<span class="ident">Http2</span>,
|
||||
@ -377,8 +350,8 @@
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="ident">proto</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">HttpProtocol</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">>></span>,
|
||||
<span class="ident">node</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">Node</span><span class="op"><</span><span class="ident">HttpChannel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">>></span><span class="op">></span>,
|
||||
<span class="ident">proto</span>: <span class="ident">HttpProtocol</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>,
|
||||
<span class="ident">ka_timeout</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">Delay</span><span class="op">></span>,
|
||||
}
|
||||
|
||||
<span class="kw">impl</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> <span class="ident">HttpChannel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>
|
||||
@ -386,45 +359,12 @@
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">new</span>(
|
||||
<span class="ident">settings</span>: <span class="ident">Rc</span><span class="op"><</span><span class="ident">WorkerSettings</span><span class="op"><</span><span class="ident">H</span><span class="op">>></span>, <span class="kw-2">mut</span> <span class="ident">io</span>: <span class="ident">T</span>, <span class="ident">peer</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">SocketAddr</span><span class="op">></span>,
|
||||
<span class="ident">http2</span>: <span class="ident">bool</span>,
|
||||
) <span class="op">-></span> <span class="ident">HttpChannel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> {
|
||||
<span class="ident">settings</span>.<span class="ident">add_channel</span>();
|
||||
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="ident">io</span>.<span class="ident">set_nodelay</span>(<span class="bool-val">true</span>);
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">settings</span>: <span class="ident">ServiceConfig</span><span class="op"><</span><span class="ident">H</span><span class="op">></span>, <span class="ident">io</span>: <span class="ident">T</span>) <span class="op">-></span> <span class="ident">HttpChannel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> {
|
||||
<span class="kw">let</span> <span class="ident">ka_timeout</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">client_timer</span>();
|
||||
|
||||
<span class="kw">if</span> <span class="ident">http2</span> {
|
||||
<span class="ident">HttpChannel</span> {
|
||||
<span class="ident">node</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">proto</span>: <span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="ident">h2</span>::<span class="ident">Http2</span>::<span class="ident">new</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">peer</span>,
|
||||
<span class="ident">Bytes</span>::<span class="ident">new</span>(),
|
||||
))),
|
||||
}
|
||||
} <span class="kw">else</span> {
|
||||
<span class="ident">HttpChannel</span> {
|
||||
<span class="ident">node</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">proto</span>: <span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">peer</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">BytesMut</span>::<span class="ident">with_capacity</span>(<span class="number">8192</span>),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">fn</span> <span class="ident">shutdown</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>) {
|
||||
<span class="kw">match</span> <span class="self">self</span>.<span class="ident">proto</span> {
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h1</span>)) <span class="op">=></span> {
|
||||
<span class="kw">let</span> <span class="ident">io</span> <span class="op">=</span> <span class="ident">h1</span>.<span class="ident">io</span>();
|
||||
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="ident">IoStream</span>::<span class="ident">set_linger</span>(<span class="ident">io</span>, <span class="prelude-val">Some</span>(<span class="ident">time</span>::<span class="ident">Duration</span>::<span class="ident">new</span>(<span class="number">0</span>, <span class="number">0</span>)));
|
||||
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="ident">IoStream</span>::<span class="ident">shutdown</span>(<span class="ident">io</span>, <span class="ident">Shutdown</span>::<span class="ident">Both</span>);
|
||||
}
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h2</span>)) <span class="op">=></span> <span class="ident">h2</span>.<span class="ident">shutdown</span>(),
|
||||
<span class="kw">_</span> <span class="op">=></span> (),
|
||||
<span class="ident">HttpChannel</span> {
|
||||
<span class="ident">ka_timeout</span>,
|
||||
<span class="ident">proto</span>: <span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="ident">settings</span>, <span class="ident">io</span>, <span class="ident">BytesMut</span>::<span class="ident">with_capacity</span>(<span class="number">8192</span>)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -435,70 +375,58 @@
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="kw">type</span> <span class="ident">Item</span> <span class="op">=</span> ();
|
||||
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> ();
|
||||
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">HttpDispatchError</span>;
|
||||
|
||||
<span class="kw">fn</span> <span class="ident">poll</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-></span> <span class="ident">Poll</span><span class="op"><</span><span class="self">Self</span>::<span class="ident">Item</span>, <span class="self">Self</span>::<span class="ident">Error</span><span class="op">></span> {
|
||||
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">node</span>.<span class="ident">is_some</span>() {
|
||||
<span class="kw">let</span> <span class="ident">el</span> <span class="op">=</span> <span class="self">self</span> <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="kw">_</span>;
|
||||
<span class="self">self</span>.<span class="ident">node</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">Node</span>::<span class="ident">new</span>(<span class="ident">el</span>));
|
||||
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw">match</span> <span class="self">self</span>.<span class="ident">proto</span> {
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h1</span>)) <span class="op">=></span> {
|
||||
<span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">h1</span>.<span class="ident">settings</span>().<span class="ident">head</span>().<span class="ident">insert</span>(<span class="ident">n</span>))
|
||||
<span class="comment">// keep-alive timer</span>
|
||||
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">ka_timeout</span>.<span class="ident">is_some</span>() {
|
||||
<span class="kw">match</span> <span class="self">self</span>.<span class="ident">ka_timeout</span>.<span class="ident">as_mut</span>().<span class="ident">unwrap</span>().<span class="ident">poll</span>() {
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="kw">_</span>)) <span class="op">=></span> {
|
||||
<span class="macro">trace</span><span class="macro">!</span>(<span class="string">"Slow request timed out, close connection"</span>);
|
||||
<span class="kw">let</span> <span class="ident">proto</span> <span class="op">=</span> <span class="ident">mem</span>::<span class="ident">replace</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>.<span class="ident">proto</span>, <span class="ident">HttpProtocol</span>::<span class="prelude-val">None</span>);
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="ident">settings</span>, <span class="ident">io</span>, <span class="ident">buf</span>) <span class="op">=</span> <span class="ident">proto</span> {
|
||||
<span class="self">self</span>.<span class="ident">proto</span> <span class="op">=</span> <span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1Dispatcher</span>::<span class="ident">for_error</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">StatusCode</span>::<span class="ident">REQUEST_TIMEOUT</span>,
|
||||
<span class="self">self</span>.<span class="ident">ka_timeout</span>.<span class="ident">take</span>(),
|
||||
<span class="ident">buf</span>,
|
||||
));
|
||||
<span class="kw">return</span> <span class="self">self</span>.<span class="ident">poll</span>();
|
||||
}
|
||||
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(()));
|
||||
}
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h2</span>)) <span class="op">=></span> {
|
||||
<span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">h2</span>.<span class="ident">settings</span>().<span class="ident">head</span>().<span class="ident">insert</span>(<span class="ident">n</span>))
|
||||
}
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">settings</span>, <span class="kw">_</span>, <span class="kw">_</span>, <span class="kw">_</span>)) <span class="op">=></span> {
|
||||
<span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">settings</span>.<span class="ident">head</span>().<span class="ident">insert</span>(<span class="ident">n</span>))
|
||||
}
|
||||
<span class="prelude-val">None</span> <span class="op">=></span> <span class="macro">unreachable</span><span class="macro">!</span>(),
|
||||
};
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">NotReady</span>) <span class="op">=></span> (),
|
||||
<span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=></span> <span class="macro">panic</span><span class="macro">!</span>(<span class="string">"Something is really wrong"</span>),
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">is_eof</span> <span class="op">=</span> <span class="bool-val">false</span>;
|
||||
<span class="kw">let</span> <span class="ident">kind</span> <span class="op">=</span> <span class="kw">match</span> <span class="self">self</span>.<span class="ident">proto</span> {
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h1</span>)) <span class="op">=></span> {
|
||||
<span class="kw">let</span> <span class="ident">result</span> <span class="op">=</span> <span class="ident">h1</span>.<span class="ident">poll</span>();
|
||||
<span class="kw">match</span> <span class="ident">result</span> {
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(())) <span class="op">|</span> <span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=></span> {
|
||||
<span class="ident">h1</span>.<span class="ident">settings</span>().<span class="ident">remove_channel</span>();
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">n</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>() {
|
||||
<span class="ident">n</span>.<span class="ident">remove</span>()
|
||||
};
|
||||
}
|
||||
<span class="kw">_</span> <span class="op">=></span> (),
|
||||
}
|
||||
<span class="kw">return</span> <span class="ident">result</span>;
|
||||
}
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h2</span>)) <span class="op">=></span> {
|
||||
<span class="kw">let</span> <span class="ident">result</span> <span class="op">=</span> <span class="ident">h2</span>.<span class="ident">poll</span>();
|
||||
<span class="kw">match</span> <span class="ident">result</span> {
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(())) <span class="op">|</span> <span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=></span> {
|
||||
<span class="ident">h2</span>.<span class="ident">settings</span>().<span class="ident">remove_channel</span>();
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">n</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>() {
|
||||
<span class="ident">n</span>.<span class="ident">remove</span>()
|
||||
};
|
||||
}
|
||||
<span class="kw">_</span> <span class="op">=></span> (),
|
||||
}
|
||||
<span class="kw">return</span> <span class="ident">result</span>;
|
||||
}
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(
|
||||
<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">settings</span>,
|
||||
<span class="kw">_</span>,
|
||||
<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">io</span>,
|
||||
<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">buf</span>,
|
||||
)) <span class="op">=></span> {
|
||||
<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h1</span>) <span class="op">=></span> <span class="kw">return</span> <span class="ident">h1</span>.<span class="ident">poll</span>(),
|
||||
<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h2</span>) <span class="op">=></span> <span class="kw">return</span> <span class="ident">h2</span>.<span class="ident">poll</span>(),
|
||||
<span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="kw">_</span>, <span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">io</span>, <span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">buf</span>) <span class="op">=></span> {
|
||||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">err</span> <span class="op">=</span> <span class="prelude-val">None</span>;
|
||||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">disconnect</span> <span class="op">=</span> <span class="bool-val">false</span>;
|
||||
<span class="kw">match</span> <span class="ident">io</span>.<span class="ident">read_available</span>(<span class="ident">buf</span>) {
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(<span class="bool-val">true</span>)) <span class="op">|</span> <span class="prelude-val">Err</span>(<span class="kw">_</span>) <span class="op">=></span> {
|
||||
<span class="macro">debug</span><span class="macro">!</span>(<span class="string">"Ignored premature client disconnection"</span>);
|
||||
<span class="ident">settings</span>.<span class="ident">remove_channel</span>();
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">n</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">node</span>.<span class="ident">as_mut</span>() {
|
||||
<span class="ident">n</span>.<span class="ident">remove</span>()
|
||||
};
|
||||
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
|
||||
<span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>((<span class="ident">read_some</span>, <span class="ident">stream_closed</span>))) <span class="op">=></span> {
|
||||
<span class="ident">is_eof</span> <span class="op">=</span> <span class="ident">stream_closed</span>;
|
||||
<span class="comment">// Only disconnect if no data was read.</span>
|
||||
<span class="kw">if</span> <span class="ident">is_eof</span> <span class="op">&&</span> <span class="op">!</span><span class="ident">read_some</span> {
|
||||
<span class="ident">disconnect</span> <span class="op">=</span> <span class="bool-val">true</span>;
|
||||
}
|
||||
}
|
||||
<span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=></span> {
|
||||
<span class="ident">err</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">e</span>.<span class="ident">into</span>());
|
||||
}
|
||||
<span class="kw">_</span> <span class="op">=></span> (),
|
||||
}
|
||||
<span class="kw">if</span> <span class="ident">disconnect</span> {
|
||||
<span class="macro">debug</span><span class="macro">!</span>(<span class="string">"Ignored premature client disconnection"</span>);
|
||||
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">Ready</span>(()));
|
||||
} <span class="kw">else</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">e</span>) <span class="op">=</span> <span class="ident">err</span> {
|
||||
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>);
|
||||
}
|
||||
|
||||
<span class="kw">if</span> <span class="ident">buf</span>.<span class="ident">len</span>() <span class="op">>=</span> <span class="number">14</span> {
|
||||
<span class="kw">if</span> <span class="ident">buf</span>[..<span class="number">14</span>] <span class="op">==</span> <span class="ident">HTTP2_PREFACE</span>[..] {
|
||||
@ -510,24 +438,30 @@
|
||||
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">Async</span>::<span class="ident">NotReady</span>);
|
||||
}
|
||||
}
|
||||
<span class="prelude-val">None</span> <span class="op">=></span> <span class="macro">unreachable</span><span class="macro">!</span>(),
|
||||
<span class="ident">HttpProtocol</span>::<span class="prelude-val">None</span> <span class="op">=></span> <span class="macro">unreachable</span><span class="macro">!</span>(),
|
||||
};
|
||||
|
||||
<span class="comment">// upgrade to specific http protocol</span>
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="ident">settings</span>, <span class="ident">addr</span>, <span class="ident">io</span>, <span class="ident">buf</span>)) <span class="op">=</span> <span class="self">self</span>.<span class="ident">proto</span>.<span class="ident">take</span>() {
|
||||
<span class="kw">let</span> <span class="ident">proto</span> <span class="op">=</span> <span class="ident">mem</span>::<span class="ident">replace</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>.<span class="ident">proto</span>, <span class="ident">HttpProtocol</span>::<span class="prelude-val">None</span>);
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">HttpProtocol</span>::<span class="ident">Unknown</span>(<span class="ident">settings</span>, <span class="ident">io</span>, <span class="ident">buf</span>) <span class="op">=</span> <span class="ident">proto</span> {
|
||||
<span class="kw">match</span> <span class="ident">kind</span> {
|
||||
<span class="ident">ProtocolKind</span>::<span class="ident">Http1</span> <span class="op">=></span> {
|
||||
<span class="self">self</span>.<span class="ident">proto</span> <span class="op">=</span>
|
||||
<span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1</span>::<span class="ident">new</span>(<span class="ident">settings</span>, <span class="ident">io</span>, <span class="ident">addr</span>, <span class="ident">buf</span>)));
|
||||
<span class="self">self</span>.<span class="ident">proto</span> <span class="op">=</span> <span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1Dispatcher</span>::<span class="ident">new</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">buf</span>,
|
||||
<span class="ident">is_eof</span>,
|
||||
<span class="self">self</span>.<span class="ident">ka_timeout</span>.<span class="ident">take</span>(),
|
||||
));
|
||||
<span class="kw">return</span> <span class="self">self</span>.<span class="ident">poll</span>();
|
||||
}
|
||||
<span class="ident">ProtocolKind</span>::<span class="ident">Http2</span> <span class="op">=></span> {
|
||||
<span class="self">self</span>.<span class="ident">proto</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="ident">h2</span>::<span class="ident">Http2</span>::<span class="ident">new</span>(
|
||||
<span class="self">self</span>.<span class="ident">proto</span> <span class="op">=</span> <span class="ident">HttpProtocol</span>::<span class="ident">H2</span>(<span class="ident">h2</span>::<span class="ident">Http2</span>::<span class="ident">new</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">addr</span>,
|
||||
<span class="ident">buf</span>.<span class="ident">freeze</span>(),
|
||||
)));
|
||||
<span class="self">self</span>.<span class="ident">ka_timeout</span>.<span class="ident">take</span>(),
|
||||
));
|
||||
<span class="kw">return</span> <span class="self">self</span>.<span class="ident">poll</span>();
|
||||
}
|
||||
}
|
||||
@ -536,79 +470,45 @@
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> {
|
||||
<span class="ident">next</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="kw-2">*</span><span class="kw-2">mut</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">>></span>,
|
||||
<span class="ident">prev</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="kw-2">*</span><span class="kw-2">mut</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">>></span>,
|
||||
<span class="ident">element</span>: <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="ident">T</span>,
|
||||
<span class="attribute">#[<span class="ident">doc</span>(<span class="ident">hidden</span>)]</span>
|
||||
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">H1Channel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>
|
||||
<span class="kw">where</span>
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="ident">proto</span>: <span class="ident">HttpProtocol</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>,
|
||||
}
|
||||
|
||||
<span class="kw">impl</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> {
|
||||
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">el</span>: <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="ident">T</span>) <span class="op">-></span> <span class="self">Self</span> {
|
||||
<span class="ident">Node</span> {
|
||||
<span class="ident">next</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">prev</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">element</span>: <span class="ident">el</span>,
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">fn</span> <span class="ident">insert</span><span class="op"><</span><span class="ident">I</span><span class="op">></span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">next</span>: <span class="kw-2">&</span><span class="kw-2">mut</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">I</span><span class="op">></span>) {
|
||||
<span class="kw">unsafe</span> {
|
||||
<span class="kw">let</span> <span class="ident">next</span>: <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> <span class="op">=</span> <span class="ident">next</span> <span class="kw">as</span> <span class="kw-2">*</span><span class="kw">const</span> <span class="kw">_</span> <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="kw">_</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="kw-2">mut</span> <span class="ident">next2</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">next</span> {
|
||||
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">next2</span>.<span class="ident">as_mut</span>().<span class="ident">unwrap</span>();
|
||||
<span class="ident">n</span>.<span class="ident">prev</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">next</span>);
|
||||
}
|
||||
<span class="self">self</span>.<span class="ident">next</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="ident">next</span>);
|
||||
|
||||
<span class="kw">let</span> <span class="ident">next</span>: <span class="kw-2">&</span><span class="kw-2">mut</span> <span class="ident">Node</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> <span class="op">=</span> <span class="kw-2">&</span><span class="kw-2">mut</span> <span class="kw-2">*</span><span class="ident">next</span>;
|
||||
<span class="ident">next</span>.<span class="ident">prev</span> <span class="op">=</span> <span class="prelude-val">Some</span>(<span class="self">self</span> <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="kw">_</span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">fn</span> <span class="ident">remove</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>) {
|
||||
<span class="kw">unsafe</span> {
|
||||
<span class="self">self</span>.<span class="ident">element</span> <span class="op">=</span> <span class="ident">ptr</span>::<span class="ident">null_mut</span>();
|
||||
<span class="kw">let</span> <span class="ident">next</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">next</span>.<span class="ident">take</span>();
|
||||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">prev</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">prev</span>.<span class="ident">take</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="kw-2">mut</span> <span class="ident">prev</span>) <span class="op">=</span> <span class="ident">prev</span> {
|
||||
<span class="ident">prev</span>.<span class="ident">as_mut</span>().<span class="ident">unwrap</span>().<span class="ident">next</span> <span class="op">=</span> <span class="ident">next</span>;
|
||||
}
|
||||
<span class="kw">impl</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> <span class="ident">H1Channel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>
|
||||
<span class="kw">where</span>
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">settings</span>: <span class="ident">ServiceConfig</span><span class="op"><</span><span class="ident">H</span><span class="op">></span>, <span class="ident">io</span>: <span class="ident">T</span>) <span class="op">-></span> <span class="ident">H1Channel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> {
|
||||
<span class="ident">H1Channel</span> {
|
||||
<span class="ident">proto</span>: <span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="ident">h1</span>::<span class="ident">Http1Dispatcher</span>::<span class="ident">new</span>(
|
||||
<span class="ident">settings</span>,
|
||||
<span class="ident">io</span>,
|
||||
<span class="ident">BytesMut</span>::<span class="ident">with_capacity</span>(<span class="number">8192</span>),
|
||||
<span class="bool-val">false</span>,
|
||||
<span class="prelude-val">None</span>,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">impl</span> <span class="ident">Node</span><span class="op"><</span>()<span class="op">></span> {
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">head</span>() <span class="op">-></span> <span class="self">Self</span> {
|
||||
<span class="ident">Node</span> {
|
||||
<span class="ident">next</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">prev</span>: <span class="prelude-val">None</span>,
|
||||
<span class="ident">element</span>: <span class="ident">ptr</span>::<span class="ident">null_mut</span>(),
|
||||
}
|
||||
}
|
||||
<span class="kw">impl</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> <span class="ident">Future</span> <span class="kw">for</span> <span class="ident">H1Channel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>
|
||||
<span class="kw">where</span>
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="kw">type</span> <span class="ident">Item</span> <span class="op">=</span> ();
|
||||
<span class="kw">type</span> <span class="ident">Error</span> <span class="op">=</span> <span class="ident">HttpDispatchError</span>;
|
||||
|
||||
<span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> <span class="ident">traverse</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span>(<span class="kw-2">&</span><span class="self">self</span>)
|
||||
<span class="kw">where</span>
|
||||
<span class="ident">T</span>: <span class="ident">IoStream</span>,
|
||||
<span class="ident">H</span>: <span class="ident">HttpHandler</span> <span class="op">+</span> <span class="lifetime">'static</span>,
|
||||
{
|
||||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">next</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">next</span>.<span class="ident">as_ref</span>();
|
||||
<span class="kw">loop</span> {
|
||||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">n</span>) <span class="op">=</span> <span class="ident">next</span> {
|
||||
<span class="kw">unsafe</span> {
|
||||
<span class="kw">let</span> <span class="ident">n</span>: <span class="kw-2">&</span><span class="ident">Node</span><span class="op"><</span>()<span class="op">></span> <span class="op">=</span> <span class="kw-2">&</span><span class="kw-2">*</span>(<span class="ident">n</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>() <span class="kw">as</span> <span class="kw-2">*</span><span class="kw">const</span> <span class="kw">_</span>);
|
||||
<span class="ident">next</span> <span class="op">=</span> <span class="ident">n</span>.<span class="ident">next</span>.<span class="ident">as_ref</span>();
|
||||
|
||||
<span class="kw">if</span> <span class="op">!</span><span class="ident">n</span>.<span class="ident">element</span>.<span class="ident">is_null</span>() {
|
||||
<span class="kw">let</span> <span class="ident">ch</span>: <span class="kw-2">&</span><span class="kw-2">mut</span> <span class="ident">HttpChannel</span><span class="op"><</span><span class="ident">T</span>, <span class="ident">H</span><span class="op">></span> <span class="op">=</span>
|
||||
<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="kw-2">*</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="kw-2">*</span>(<span class="ident">n</span>.<span class="ident">element</span> <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="kw">_</span>) <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> () <span class="kw">as</span> <span class="kw-2">*</span><span class="kw-2">mut</span> <span class="kw">_</span>);
|
||||
<span class="ident">ch</span>.<span class="ident">shutdown</span>();
|
||||
}
|
||||
}
|
||||
} <span class="kw">else</span> {
|
||||
<span class="kw">return</span>;
|
||||
}
|
||||
<span class="kw">fn</span> <span class="ident">poll</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>) <span class="op">-></span> <span class="ident">Poll</span><span class="op"><</span><span class="self">Self</span>::<span class="ident">Item</span>, <span class="self">Self</span>::<span class="ident">Error</span><span class="op">></span> {
|
||||
<span class="kw">match</span> <span class="self">self</span>.<span class="ident">proto</span> {
|
||||
<span class="ident">HttpProtocol</span>::<span class="ident">H1</span>(<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">h1</span>) <span class="op">=></span> <span class="ident">h1</span>.<span class="ident">poll</span>(),
|
||||
<span class="kw">_</span> <span class="op">=></span> <span class="macro">unreachable</span><span class="macro">!</span>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -646,6 +546,10 @@
|
||||
<span class="kw">fn</span> <span class="ident">set_linger</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="kw">_</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">time</span>::<span class="ident">Duration</span><span class="op">></span>) <span class="op">-></span> <span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op"><</span>()<span class="op">></span> {
|
||||
<span class="prelude-val">Ok</span>(())
|
||||
}
|
||||
<span class="attribute">#[<span class="ident">inline</span>]</span>
|
||||
<span class="kw">fn</span> <span class="ident">set_keepalive</span>(<span class="kw-2">&</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="kw">_</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">time</span>::<span class="ident">Duration</span><span class="op">></span>) <span class="op">-></span> <span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op"><</span>()<span class="op">></span> {
|
||||
<span class="prelude-val">Ok</span>(())
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">impl</span><span class="op"><</span><span class="ident">T</span><span class="op">></span> <span class="ident">io</span>::<span class="ident">Read</span> <span class="kw">for</span> <span class="ident">WrapperStream</span><span class="op"><</span><span class="ident">T</span><span class="op">></span>
|
||||
|
Reference in New Issue
Block a user