Module hyper::server
[−]
[src]
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 fns 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.
Reexports
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. |