[−][src]Module hyper::server
HTTP Server
Server
A Server
is created to listen on port, parse HTTP requests, and hand
them off to a Handler
. By default, the Server will listen across multiple
threads, but that can be configured to a single thread if preferred.
Handling requests
You must pass a Handler
to the Server that will handle requests. There is
a default implementation for fn
s and closures, allowing you pass one of
those easily.
use hyper::server::{Server, Request, Response}; fn hello(req: Request, res: Response) { // handle things here } Server::http("0.0.0.0:0").unwrap().handle(hello).unwrap();
As with any trait, you can also define a struct and implement Handler
directly on your own type, and pass that to the Server
instead.
use std::sync::Mutex; use std::sync::mpsc::{channel, Sender}; use hyper::server::{Handler, Server, Request, Response}; struct SenderHandler { sender: Mutex<Sender<&'static str>> } impl Handler for SenderHandler { fn handle(&self, req: Request, res: Response) { self.sender.lock().unwrap().send("start").unwrap(); } } let (tx, rx) = channel(); Server::http("0.0.0.0:0").unwrap().handle(SenderHandler { sender: Mutex::new(tx) }).unwrap();
Since the Server
will be listening on multiple threads, the Handler
must implement Sync
: any mutable state must be synchronized.
use std::sync::atomic::{AtomicUsize, Ordering}; use hyper::server::{Server, Request, Response}; let counter = AtomicUsize::new(0); Server::http("0.0.0.0:0").unwrap().handle(move |req: Request, res: Response| { counter.fetch_add(1, Ordering::Relaxed); }).unwrap();
The Request
and Response
pair
A Handler
receives a pair of arguments, a Request
and a Response
. The
Request
includes access to the method
, uri
, and headers
of the
incoming HTTP request. It also implements std::io::Read
, in order to
read any body, such as with POST
or PUT
messages.
Likewise, the Response
includes ways to set the status
and headers
,
and implements std::io::Write
to allow writing the response body.
use std::io; use hyper::server::{Server, Request, Response}; use hyper::status::StatusCode; Server::http("0.0.0.0:0").unwrap().handle(|mut req: Request, mut res: Response| { match req.method { hyper::Post => { io::copy(&mut req, &mut res.start().unwrap()).unwrap(); }, _ => *res.status_mut() = StatusCode::MethodNotAllowed } }).unwrap();
An aside: Write Status
The Response
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.
This is often done in most implementations by include a boolean property
on the response, such as headers_written
, 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:
- You are typically never notified that your late header is doing nothing.
- There's a runtime cost to checking on every write.
Instead, hyper handles this statically, or at compile-time. A
Response<Fresh>
includes a headers_mut()
method, allowing you add more
headers. It also does not implement Write
, so you can't accidentally
write early. Once the "head" of the response is correct, you can "send" it
out by calling start
on the Response<Fresh>
. This will return a new
Response<Streaming>
object, that no longer has headers_mut()
, but does
implement Write
.
Re-exports
pub use self::request::Request; |
pub use self::response::Response; |
pub use net::Fresh; |
pub use net::Streaming; |
Modules
request |
Server Requests |
response |
Server Responses |
Structs
Listening |
A listening server, which can later be closed. |
Server |
A server can listen on a TCP socket. |
Traits
Handler |
A handler that can handle incoming requests for a server. |