257 lines
16 KiB
HTML
257 lines
16 KiB
HTML
|
<!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="API documentation for the Rust `server` mod in crate `hyper`.">
|
|||
|
<meta name="keywords" content="rust, rustlang, rust-lang, server">
|
|||
|
|
|||
|
<title>hyper::server - Rust</title>
|
|||
|
|
|||
|
<link rel="stylesheet" type="text/css" href="../../rustdoc.css">
|
|||
|
<link rel="stylesheet" type="text/css" href="../../main.css">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</head>
|
|||
|
<body class="rustdoc">
|
|||
|
<!--[if lte IE 8]>
|
|||
|
<div class="warning">
|
|||
|
This old browser is unsupported and will most likely display funky
|
|||
|
things.
|
|||
|
</div>
|
|||
|
<![endif]-->
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<nav class="sidebar">
|
|||
|
|
|||
|
<p class='location'><a href='../index.html'>hyper</a></p><script>window.sidebarCurrent = {name: 'server', ty: 'mod', relpath: '../'};</script><script defer src="../sidebar-items.js"></script>
|
|||
|
</nav>
|
|||
|
|
|||
|
<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">
|
|||
|
</div>
|
|||
|
</form>
|
|||
|
</nav>
|
|||
|
|
|||
|
<section id='main' class="content mod">
|
|||
|
<h1 class='fqn'><span class='in-band'>Module <a href='../index.html'>hyper</a>::<wbr><a class='mod' href=''>server</a></span><span class='out-of-band'><span id='render-detail'>
|
|||
|
<a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
|
|||
|
[<span class='inner'>−</span>]
|
|||
|
</a>
|
|||
|
</span><a id='src-7213' class='srclink' href='../../src/hyper/server/mod.rs.html#1-510' title='goto source code'>[src]</a></span></h1>
|
|||
|
<div class='docblock'><p>HTTP Server</p>
|
|||
|
|
|||
|
<h1 id='server' class='section-header'><a href='#server'>Server</a></h1>
|
|||
|
<p>A <code>Server</code> is created to listen on port, parse HTTP requests, and hand
|
|||
|
them off to a <code>Handler</code>. By default, the Server will listen across multiple
|
|||
|
threads, but that can be configured to a single thread if preferred.</p>
|
|||
|
|
|||
|
<h1 id='handling-requests' class='section-header'><a href='#handling-requests'>Handling requests</a></h1>
|
|||
|
<p>You must pass a <code>Handler</code> to the Server that will handle requests. There is
|
|||
|
a default implementation for <code>fn</code>s and closures, allowing you pass one of
|
|||
|
those easily.</p>
|
|||
|
|
|||
|
<pre class='rust rust-example-rendered'>
|
|||
|
<span class='kw'>use</span> <span class='ident'>hyper</span>::<span class='ident'>server</span>::{<span class='ident'>Server</span>, <span class='ident'>Request</span>, <span class='ident'>Response</span>};
|
|||
|
|
|||
|
<span class='kw'>fn</span> <span class='ident'>hello</span>(<span class='ident'>req</span>: <span class='ident'>Request</span>, <span class='ident'>res</span>: <span class='ident'>Response</span>) {
|
|||
|
<span class='comment'>// handle things here</span>
|
|||
|
}
|
|||
|
|
|||
|
<span class='ident'>Server</span>::<span class='ident'>http</span>(<span class='string'>"0.0.0.0:0"</span>).<span class='ident'>unwrap</span>().<span class='ident'>handle</span>(<span class='ident'>hello</span>).<span class='ident'>unwrap</span>();</pre>
|
|||
|
|
|||
|
<p>As with any trait, you can also define a struct and implement <code>Handler</code>
|
|||
|
directly on your own type, and pass that to the <code>Server</code> instead.</p>
|
|||
|
|
|||
|
<pre class='rust rust-example-rendered'>
|
|||
|
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>sync</span>::<span class='ident'>Mutex</span>;
|
|||
|
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>sync</span>::<span class='ident'>mpsc</span>::{<span class='ident'>channel</span>, <span class='ident'>Sender</span>};
|
|||
|
<span class='kw'>use</span> <span class='ident'>hyper</span>::<span class='ident'>server</span>::{<span class='ident'>Handler</span>, <span class='ident'>Server</span>, <span class='ident'>Request</span>, <span class='ident'>Response</span>};
|
|||
|
|
|||
|
<span class='kw'>struct</span> <span class='ident'>SenderHandler</span> {
|
|||
|
<span class='ident'>sender</span>: <span class='ident'>Mutex</span><span class='op'><</span><span class='ident'>Sender</span><span class='op'><</span><span class='kw-2'>&</span><span class='lifetime'>'static</span> <span class='ident'>str</span><span class='op'>>></span>
|
|||
|
}
|
|||
|
|
|||
|
<span class='kw'>impl</span> <span class='ident'>Handler</span> <span class='kw'>for</span> <span class='ident'>SenderHandler</span> {
|
|||
|
<span class='kw'>fn</span> <span class='ident'>handle</span>(<span class='kw-2'>&</span><span class='self'>self</span>, <span class='ident'>req</span>: <span class='ident'>Request</span>, <span class='ident'>res</span>: <span class='ident'>Response</span>) {
|
|||
|
<span class='self'>self</span>.<span class='ident'>sender</span>.<span class='ident'>lock</span>().<span class='ident'>unwrap</span>().<span class='ident'>send</span>(<span class='string'>"start"</span>).<span class='ident'>unwrap</span>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
<span class='kw'>let</span> (<span class='ident'>tx</span>, <span class='ident'>rx</span>) <span class='op'>=</span> <span class='ident'>channel</span>();
|
|||
|
<span class='ident'>Server</span>::<span class='ident'>http</span>(<span class='string'>"0.0.0.0:0"</span>).<span class='ident'>unwrap</span>().<span class='ident'>handle</span>(<span class='ident'>SenderHandler</span> {
|
|||
|
<span class='ident'>sender</span>: <span class='ident'>Mutex</span>::<span class='ident'>new</span>(<span class='ident'>tx</span>)
|
|||
|
}).<span class='ident'>unwrap</span>();</pre>
|
|||
|
|
|||
|
<p>Since the <code>Server</code> will be listening on multiple threads, the <code>Handler</code>
|
|||
|
must implement <code>Sync</code>: any mutable state must be synchronized.</p>
|
|||
|
|
|||
|
<pre class='rust rust-example-rendered'>
|
|||
|
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>sync</span>::<span class='ident'>atomic</span>::{<span class='ident'>AtomicUsize</span>, <span class='ident'>Ordering</span>};
|
|||
|
<span class='kw'>use</span> <span class='ident'>hyper</span>::<span class='ident'>server</span>::{<span class='ident'>Server</span>, <span class='ident'>Request</span>, <span class='ident'>Response</span>};
|
|||
|
|
|||
|
<span class='kw'>let</span> <span class='ident'>counter</span> <span class='op'>=</span> <span class='ident'>AtomicUsize</span>::<span class='ident'>new</span>(<span class='number'>0</span>);
|
|||
|
<span class='ident'>Server</span>::<span class='ident'>http</span>(<span class='string'>"0.0.0.0:0"</span>).<span class='ident'>unwrap</span>().<span class='ident'>handle</span>(<span class='kw'>move</span> <span class='op'>|</span><span class='ident'>req</span>: <span class='ident'>Request</span>, <span class='ident'>res</span>: <span class='ident'>Response</span><span class='op'>|</span> {
|
|||
|
<span class='ident'>counter</span>.<span class='ident'>fetch_add</span>(<span class='number'>1</span>, <span class='ident'>Ordering</span>::<span class='ident'>Relaxed</span>);
|
|||
|
}).<span class='ident'>unwrap</span>();</pre>
|
|||
|
|
|||
|
<h1 id='the-request-and-response-pair' class='section-header'><a href='#the-request-and-response-pair'>The <code>Request</code> and <code>Response</code> pair</a></h1>
|
|||
|
<p>A <code>Handler</code> receives a pair of arguments, a <code>Request</code> and a <code>Response</code>. The
|
|||
|
<code>Request</code> includes access to the <code>method</code>, <code>uri</code>, and <code>headers</code> of the
|
|||
|
incoming HTTP request. It also implements <code>std::io::Read</code>, in order to
|
|||
|
read any body, such as with <code>POST</code> or <code>PUT</code> messages.</p>
|
|||
|
|
|||
|
<p>Likewise, the <code>Response</code> includes ways to set the <code>status</code> and <code>headers</code>,
|
|||
|
and implements <code>std::io::Write</code> to allow writing the response body.</p>
|
|||
|
|
|||
|
<pre class='rust rust-example-rendered'>
|
|||
|
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>io</span>;
|
|||
|
<span class='kw'>use</span> <span class='ident'>hyper</span>::<span class='ident'>server</span>::{<span class='ident'>Server</span>, <span class='ident'>Request</span>, <span class='ident'>Response</span>};
|
|||
|
<span class='kw'>use</span> <span class='ident'>hyper</span>::<span class='ident'>status</span>::<span class='ident'>StatusCode</span>;
|
|||
|
|
|||
|
<span class='ident'>Server</span>::<span class='ident'>http</span>(<span class='string'>"0.0.0.0:0"</span>).<span class='ident'>unwrap</span>().<span class='ident'>handle</span>(<span class='op'>|</span><span class='kw-2'>mut</span> <span class='ident'>req</span>: <span class='ident'>Request</span>, <span class='kw-2'>mut</span> <span class='ident'>res</span>: <span class='ident'>Response</span><span class='op'>|</span> {
|
|||
|
<span class='kw'>match</span> <span class='ident'>req</span>.<span class='ident'>method</span> {
|
|||
|
<span class='ident'>hyper</span>::<span class='ident'>Post</span> <span class='op'>=></span> {
|
|||
|
<span class='ident'>io</span>::<span class='ident'>copy</span>(<span class='kw-2'>&</span><span class='kw-2'>mut</span> <span class='ident'>req</span>, <span class='kw-2'>&</span><span class='kw-2'>mut</span> <span class='ident'>res</span>.<span class='ident'>start</span>().<span class='ident'>unwrap</span>()).<span class='ident'>unwrap</span>();
|
|||
|
},
|
|||
|
_ <span class='op'>=></span> <span class='op'>*</span><span class='ident'>res</span>.<span class='ident'>status_mut</span>() <span class='op'>=</span> <span class='ident'>StatusCode</span>::<span class='ident'>MethodNotAllowed</span>
|
|||
|
}
|
|||
|
}).<span class='ident'>unwrap</span>();</pre>
|
|||
|
|
|||
|
<h2 id='an-aside-write-status' class='section-header'><a href='#an-aside-write-status'>An aside: Write Status</a></h2>
|
|||
|
<p>The <code>Response</code> uses a phantom type parameter to determine its write status.
|
|||
|
What does that mean? In short, it ensures you never write a body before
|
|||
|
adding all headers, and never add a header after writing some of the body.</p>
|
|||
|
|
|||
|
<p>This is often done in most implementations by include a boolean property
|
|||
|
on the response, such as <code>headers_written</code>, checking that each time the
|
|||
|
body has something to write, so as to make sure the headers are sent once,
|
|||
|
and only once. But this has 2 downsides:</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>You are typically never notified that your late header is doing nothing.</li>
|
|||
|
<li>There's a runtime cost to checking on every write.</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>Instead, hyper handles this statically, or at compile-time. A
|
|||
|
<code>Response<Fresh></code> includes a <code>headers_mut()</code> method, allowing you add more
|
|||
|
headers. It also does not implement <code>Write</code>, so you can't accidentally
|
|||
|
write early. Once the "head" of the response is correct, you can "send" it
|
|||
|
out by calling <code>start</code> on the <code>Response<Fresh></code>. This will return a new
|
|||
|
<code>Response<Streaming></code> object, that no longer has <code>headers_mut()</code>, but does
|
|||
|
implement <code>Write</code>.</p>
|
|||
|
</div><h2 id='reexports' class='section-header'><a href="#reexports">Reexports</a></h2>
|
|||
|
<table><tr><td><code>pub use self::<a class='mod'
|
|||
|
href='./request/index.html'>request</a>::<a class='struct' href='../../hyper/server/request/struct.Request.html' title='hyper::server::request::Request'>Request</a>;</code></td></tr><tr><td><code>pub use self::<a class='mod'
|
|||
|
href='./response/index.html'>response</a>::<a class='struct' href='../../hyper/server/response/struct.Response.html' title='hyper::server::response::Response'>Response</a>;</code></td></tr><tr><td><code>pub use net::{<a class='enum' href='../../hyper/net/enum.Fresh.html' title='hyper::net::Fresh'>Fresh</a>, <a class='enum' href='../../hyper/net/enum.Streaming.html' title='hyper::net::Streaming'>Streaming</a>};</code></td></tr></table><h2 id='modules' class='section-header'><a href="#modules">Modules</a></h2>
|
|||
|
<table>
|
|||
|
<tr class=' module-item'>
|
|||
|
<td><a class='mod' href='request/index.html'
|
|||
|
title='hyper::server::request'>request</a></td>
|
|||
|
<td class='docblock short'>
|
|||
|
<p>Server Requests</p>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
<tr class=' module-item'>
|
|||
|
<td><a class='mod' href='response/index.html'
|
|||
|
title='hyper::server::response'>response</a></td>
|
|||
|
<td class='docblock short'>
|
|||
|
<p>Server Responses</p>
|
|||
|
</td>
|
|||
|
</tr></table><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
|
|||
|
<table>
|
|||
|
<tr class=' module-item'>
|
|||
|
<td><a class='struct' href='struct.Listening.html'
|
|||
|
title='hyper::server::Listening'>Listening</a></td>
|
|||
|
<td class='docblock short'>
|
|||
|
<p>A listening server, which can later be closed.</p>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
<tr class=' module-item'>
|
|||
|
<td><a class='struct' href='struct.Server.html'
|
|||
|
title='hyper::server::Server'>Server</a></td>
|
|||
|
<td class='docblock short'>
|
|||
|
<p>A server can listen on a TCP socket.</p>
|
|||
|
</td>
|
|||
|
</tr></table><h2 id='traits' class='section-header'><a href="#traits">Traits</a></h2>
|
|||
|
<table>
|
|||
|
<tr class=' module-item'>
|
|||
|
<td><a class='trait' href='trait.Handler.html'
|
|||
|
title='hyper::server::Handler'>Handler</a></td>
|
|||
|
<td class='docblock short'>
|
|||
|
<p>A handler that can handle incoming requests for a server.</p>
|
|||
|
</td>
|
|||
|
</tr></table></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>?</dt>
|
|||
|
<dd>Show this help dialog</dd>
|
|||
|
<dt>S</dt>
|
|||
|
<dd>Focus the search field</dd>
|
|||
|
<dt>⇤</dt>
|
|||
|
<dd>Move up in search results</dd>
|
|||
|
<dt>⇥</dt>
|
|||
|
<dd>Move down in search results</dd>
|
|||
|
<dt>⏎</dt>
|
|||
|
<dd>Go to active search result</dd>
|
|||
|
<dt>+</dt>
|
|||
|
<dd>Collapse/expand 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>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</aside>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script>
|
|||
|
window.rootPath = "../../";
|
|||
|
window.currentCrate = "hyper";
|
|||
|
window.playgroundUrl = "";
|
|||
|
</script>
|
|||
|
<script src="../../jquery.js"></script>
|
|||
|
<script src="../../main.js"></script>
|
|||
|
|
|||
|
<script defer src="../../search-index.js"></script>
|
|||
|
</body>
|
|||
|
</html>
|