| 
							
							
							
						 |  |  | @@ -1,30 +1,384 @@ | 
		
	
		
			
				|  |  |  |  | % Server Guide | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # The `Handler` | 
		
	
		
			
				|  |  |  |  | # Hello, World | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```ignore,no_run | 
		
	
		
			
				|  |  |  |  | Let's start off by creating a simple server to just serve a text response | 
		
	
		
			
				|  |  |  |  | of "Hello, World!" to every request. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```no_run | 
		
	
		
			
				|  |  |  |  | extern crate hyper; | 
		
	
		
			
				|  |  |  |  | use hyper::server::{Handler, Request, Response, Decoder, Encoder, Next, HttpStream as Http}; | 
		
	
		
			
				|  |  |  |  | use hyper::{Decoder, Encoder, HttpStream as Http, Next}; | 
		
	
		
			
				|  |  |  |  | use hyper::server::{Server, Handler, Request, Response}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | struct Hello; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | impl Handler<Http> for Hello { | 
		
	
		
			
				|  |  |  |  |     fn on_request(&mut self, req: Request<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  | struct Text(&'static [u8]); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | impl Handler<Http> for Text { | 
		
	
		
			
				|  |  |  |  |     fn on_request(&mut self, _req: Request<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_request_readable(&mut self, decoder: &mut Decoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_request_readable(&mut self, _decoder: &mut Decoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_response(&mut self, res: &mut Response) -> Next { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         use hyper::header::ContentLength; | 
		
	
		
			
				|  |  |  |  |         res.headers_mut().set(ContentLength(self.0.len() as u64)); | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_response_writable(&mut self, encoder: &mut Encoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         encoder.write(self.0).unwrap(); // for now | 
		
	
		
			
				|  |  |  |  |         Next::end() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn main() { | 
		
	
		
			
				|  |  |  |  |     let addr = "127.0.0.1:0".parse().unwrap(); | 
		
	
		
			
				|  |  |  |  |     let (listening, server) = Server::http(&addr).unwrap() | 
		
	
		
			
				|  |  |  |  |         .handle(|_| Text(b"Hello, World")).unwrap(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     println!("Listening on http://{}", listening); | 
		
	
		
			
				|  |  |  |  |     server.run() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | There is quite a few concepts here, so let's tackle them one by one. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Handler | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | The [`Handler`][Handler] is how you define what should happen during the lifetime | 
		
	
		
			
				|  |  |  |  | of an HTTP message. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Next | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Every event in the [`Handler`][Handler] returns a [`Next`][Next]. This signals | 
		
	
		
			
				|  |  |  |  | to hyper what the `Handler` would wishes to do next, and hyper will call the | 
		
	
		
			
				|  |  |  |  | appropriate method of the `Handler` when the action is ready again. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | So, in our "Hello World" server, you'll notice that when a request comes in, we | 
		
	
		
			
				|  |  |  |  | have no interest in the `Request` or its body. We immediately just wish to write | 
		
	
		
			
				|  |  |  |  | "Hello, World!", and be done. So, in `on_request`, we return `Next::write()`, | 
		
	
		
			
				|  |  |  |  | which tells hyper we wish to write the response. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | After `on_response` is called, we ask for `Next::write()` again, because we | 
		
	
		
			
				|  |  |  |  | still need to write the response body. hyper knows that the next time the | 
		
	
		
			
				|  |  |  |  | transport is ready to be written, since it already called `on_response`, it | 
		
	
		
			
				|  |  |  |  | will call `on_response_writable`, which is where we can write the text body. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Once we're all done with the response, we can tell hyper to finish by returning | 
		
	
		
			
				|  |  |  |  | `Next::end()`. hyper will try to finish flushing all the output, and if the | 
		
	
		
			
				|  |  |  |  | conditions are met, it may try to use the underlying transport for another | 
		
	
		
			
				|  |  |  |  | request. This is also known as "keep-alive". | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Server | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | In the `main` function, a [`Server`][Server] is created that will utilize our | 
		
	
		
			
				|  |  |  |  | `Hello` handler. We use the default options, though you may wish to peruse | 
		
	
		
			
				|  |  |  |  | them, especially the `max_sockets` option, as it is conservative by default. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | We pass a constructor closure to `Server.handle`, which constructs a `Handler` | 
		
	
		
			
				|  |  |  |  | to be used for each incoming request. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # Non-blocking IO | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Don't Panic | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | There is actually a very bad practice in the "Hello, World"  example. The usage | 
		
	
		
			
				|  |  |  |  | of `decoder.write(x).unwrap()` will panic if the write operation fails. A panic | 
		
	
		
			
				|  |  |  |  | will take down the whole thread, which means the event loop and all other | 
		
	
		
			
				|  |  |  |  | in-progress requests. So don't do it. It's bad. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | What makes it worse, is that the write operation is much more likely to fail | 
		
	
		
			
				|  |  |  |  | when using non-blocking IO. If the write would block the thread, instead of | 
		
	
		
			
				|  |  |  |  | doing so, it will return an `io::Error` with the `kind` of `WouldBlock`. These | 
		
	
		
			
				|  |  |  |  | are expected errors. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## WouldBlock | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Instead, we should inspect when there is a read or write error to see if the | 
		
	
		
			
				|  |  |  |  | `kind` was a `WouldBlock` error. Since `WouldBlock` is so common when using | 
		
	
		
			
				|  |  |  |  | non-blocking IO, the `Encoder` and `Decoder` provide `try_` methods that will | 
		
	
		
			
				|  |  |  |  | special case `WouldBlock`, allowing you to treat all `Err` cases as actual | 
		
	
		
			
				|  |  |  |  | errors. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Additionally, it's possible there was a partial write of the response body, so | 
		
	
		
			
				|  |  |  |  | we should probably change the example to keep track of it's progress. Can you | 
		
	
		
			
				|  |  |  |  | see how we should change the example to better handle these conditions? | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | This will just show the updated `on_response_writable` method, the rest stays | 
		
	
		
			
				|  |  |  |  | the same: | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```no_run | 
		
	
		
			
				|  |  |  |  | # extern crate hyper; | 
		
	
		
			
				|  |  |  |  | # use hyper::{Encoder, HttpStream as Http, Next}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # struct Text(&'static [u8]); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # impl Text { | 
		
	
		
			
				|  |  |  |  |     fn on_response_writable(&mut self, encoder: &mut Encoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |         match encoder.try_write(self.0) { | 
		
	
		
			
				|  |  |  |  |             Ok(Some(n)) => { | 
		
	
		
			
				|  |  |  |  |                 if n == self.0.len() { | 
		
	
		
			
				|  |  |  |  |                     // all done! | 
		
	
		
			
				|  |  |  |  |                     Next::end() | 
		
	
		
			
				|  |  |  |  |                 } else { | 
		
	
		
			
				|  |  |  |  |                     // a partial write! | 
		
	
		
			
				|  |  |  |  |                     // with a static array, we can just move our pointer | 
		
	
		
			
				|  |  |  |  |                     // another option could be to store a separate index field | 
		
	
		
			
				|  |  |  |  |                     self.0 = &self.0[n..]; | 
		
	
		
			
				|  |  |  |  |                     // there's still more to write, so ask to write again | 
		
	
		
			
				|  |  |  |  |                     Next::write() | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             Ok(None) => { | 
		
	
		
			
				|  |  |  |  |                 // would block, ask to write again | 
		
	
		
			
				|  |  |  |  |                 Next::write() | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             Err(e) => { | 
		
	
		
			
				|  |  |  |  |                 println!("oh noes, we cannot say hello! {}", e); | 
		
	
		
			
				|  |  |  |  |                 // remove (kill) this transport | 
		
	
		
			
				|  |  |  |  |                 Next::remove() | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | # } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # fn main() {} | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # Routing | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | What if we wanted to serve different messages depending on the URL of the | 
		
	
		
			
				|  |  |  |  | request? Say, we wanted to respond with "Hello, World!" to `/hello`, but | 
		
	
		
			
				|  |  |  |  | "Good-bye" with `/bye`. Let's adjust our example to do that. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```no_run | 
		
	
		
			
				|  |  |  |  | extern crate hyper; | 
		
	
		
			
				|  |  |  |  | use hyper::{Decoder, Encoder, HttpStream as Http, Next, StatusCode}; | 
		
	
		
			
				|  |  |  |  | use hyper::server::{Server, Handler, Request, Response}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | struct Text(StatusCode, &'static [u8]); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | impl Handler<Http> for Text { | 
		
	
		
			
				|  |  |  |  |     fn on_request(&mut self, req: Request<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |         use hyper::RequestUri; | 
		
	
		
			
				|  |  |  |  |         let path = match *req.uri() { | 
		
	
		
			
				|  |  |  |  |             RequestUri::AbsolutePath(ref p) => p, | 
		
	
		
			
				|  |  |  |  |             RequestUri::AbsoluteUri(ref url) => url.path(), | 
		
	
		
			
				|  |  |  |  |             // other 2 forms are for CONNECT and OPTIONS methods | 
		
	
		
			
				|  |  |  |  |             _ => "" | 
		
	
		
			
				|  |  |  |  |         }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         match path { | 
		
	
		
			
				|  |  |  |  |             "/hello" => { | 
		
	
		
			
				|  |  |  |  |                 self.1 = b"Hello, World!"; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             "/bye" => { | 
		
	
		
			
				|  |  |  |  |                 self.1 = b"Good-bye"; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             _ => { | 
		
	
		
			
				|  |  |  |  |                 self.0 = StatusCode::NotFound; | 
		
	
		
			
				|  |  |  |  |                 self.1 = b"Not Found"; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #    fn on_request_readable(&mut self, _decoder: &mut Decoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  | #        Next::write() | 
		
	
		
			
				|  |  |  |  | #    } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_response(&mut self, res: &mut Response) -> Next { | 
		
	
		
			
				|  |  |  |  |         use hyper::header::ContentLength; | 
		
	
		
			
				|  |  |  |  |         // we send an HTTP Status Code, 200 OK, or 404 Not Found | 
		
	
		
			
				|  |  |  |  |         res.set_status(self.0); | 
		
	
		
			
				|  |  |  |  |         res.headers_mut().set(ContentLength(self.1.len() as u64)); | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #    fn on_response_writable(&mut self, encoder: &mut Encoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  | #        match encoder.try_write(self.1) { | 
		
	
		
			
				|  |  |  |  | #            Ok(Some(n)) => { | 
		
	
		
			
				|  |  |  |  | #                if n == self.1.len() { | 
		
	
		
			
				|  |  |  |  | #                    Next::end() | 
		
	
		
			
				|  |  |  |  | #                } else { | 
		
	
		
			
				|  |  |  |  | #                    self.1 = &self.1[n..]; | 
		
	
		
			
				|  |  |  |  | #                    Next::write() | 
		
	
		
			
				|  |  |  |  | #                } | 
		
	
		
			
				|  |  |  |  | #            }, | 
		
	
		
			
				|  |  |  |  | #            Ok(None) => { | 
		
	
		
			
				|  |  |  |  | #                Next::write() | 
		
	
		
			
				|  |  |  |  | #            }, | 
		
	
		
			
				|  |  |  |  | #            Err(e) => { | 
		
	
		
			
				|  |  |  |  | #                println!("oh noes, we cannot say hello! {}", e); | 
		
	
		
			
				|  |  |  |  | #                Next::remove() | 
		
	
		
			
				|  |  |  |  | #            } | 
		
	
		
			
				|  |  |  |  | #        } | 
		
	
		
			
				|  |  |  |  | #    } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn main() { | 
		
	
		
			
				|  |  |  |  |     let addr = "127.0.0.1:0".parse().unwrap(); | 
		
	
		
			
				|  |  |  |  |     let (listening, server) = Server::http(&addr).unwrap() | 
		
	
		
			
				|  |  |  |  |         .handle(|_| Text(StatusCode::Ok, b"")).unwrap(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     println!("Listening on http://{}", listening); | 
		
	
		
			
				|  |  |  |  |     server.run() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # Waiting | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | More often than not, a server needs to something "expensive" before it can | 
		
	
		
			
				|  |  |  |  | provide a response to a request. This may be talking to a database, reading | 
		
	
		
			
				|  |  |  |  | a file, processing an image, sending its own HTTP request to another server, | 
		
	
		
			
				|  |  |  |  | or anything else that would impede the event loop thread. These sorts of actions | 
		
	
		
			
				|  |  |  |  | should be done off the event loop thread, when complete, should notify hyper | 
		
	
		
			
				|  |  |  |  | that it can now proceed. This is done by combining `Next::wait()` and the | 
		
	
		
			
				|  |  |  |  | [`Control`][Control]. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Control | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | The `Control` is provided to the `Handler` constructor; it is the argument we | 
		
	
		
			
				|  |  |  |  | have so far been ignoring. It's not needed if we don't ever need to wait a | 
		
	
		
			
				|  |  |  |  | transport. The `Control` is usually sent to a queue, or another thread, or | 
		
	
		
			
				|  |  |  |  | wherever makes sense to be able to use it when the "blocking" operations are | 
		
	
		
			
				|  |  |  |  | complete. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | To focus on hyper instead of obscure blocking operations, we'll use this useless | 
		
	
		
			
				|  |  |  |  | sleeping thread to show it works. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```no_run | 
		
	
		
			
				|  |  |  |  | extern crate hyper; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | use std::sync::mpsc; | 
		
	
		
			
				|  |  |  |  | use std::thread; | 
		
	
		
			
				|  |  |  |  | use std::time::Duration; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | use hyper::{Control, Next}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn calculate_ultimate_question(rx: mpsc::Receiver<(Control, mpsc::Sender<&'static [u8]>)>) { | 
		
	
		
			
				|  |  |  |  |     thread::spawn(move || { | 
		
	
		
			
				|  |  |  |  |         while let Ok((ctrl, tx)) = rx.recv() { | 
		
	
		
			
				|  |  |  |  |             thread::sleep(Duration::from_millis(500)); | 
		
	
		
			
				|  |  |  |  |             tx.send(b"42").unwrap(); | 
		
	
		
			
				|  |  |  |  |             ctrl.ready(Next::write()).unwrap(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     }); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # fn main() {} | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Our worker will spawn a thread that waits on messages. When receiving a message, | 
		
	
		
			
				|  |  |  |  | after a short nap, it will send back the "result" of the work, and wake up the | 
		
	
		
			
				|  |  |  |  | waiting transport with a `Next::write()` desire. | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ## Wait | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Finally, let's tie in our worker thread into our `Text` handler: | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ```no_run | 
		
	
		
			
				|  |  |  |  | extern crate hyper; | 
		
	
		
			
				|  |  |  |  | use hyper::{Control, Decoder, Encoder, HttpStream as Http, Next, StatusCode}; | 
		
	
		
			
				|  |  |  |  | use hyper::server::{Server, Handler, Request, Response}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | use std::sync::mpsc; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | struct Text { | 
		
	
		
			
				|  |  |  |  |     status: StatusCode, | 
		
	
		
			
				|  |  |  |  |     text: &'static [u8], | 
		
	
		
			
				|  |  |  |  |     control: Option<Control>, | 
		
	
		
			
				|  |  |  |  |     worker_tx: mpsc::Sender<(Control, mpsc::Sender<&'static [u8]>)>, | 
		
	
		
			
				|  |  |  |  |     worker_rx: Option<mpsc::Receiver<&'static [u8]>>, | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | impl Handler<Http> for Text { | 
		
	
		
			
				|  |  |  |  |     fn on_request(&mut self, req: Request<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  |         use hyper::RequestUri; | 
		
	
		
			
				|  |  |  |  |         let path = match *req.uri() { | 
		
	
		
			
				|  |  |  |  |             RequestUri::AbsolutePath(ref p) => p, | 
		
	
		
			
				|  |  |  |  |             RequestUri::AbsoluteUri(ref url) => url.path(), | 
		
	
		
			
				|  |  |  |  |             _ => "" | 
		
	
		
			
				|  |  |  |  |         }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         match path { | 
		
	
		
			
				|  |  |  |  |             "/hello" => { | 
		
	
		
			
				|  |  |  |  |                 self.text = b"Hello, World!"; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             "/bye" => { | 
		
	
		
			
				|  |  |  |  |                 self.text = b"Good-bye"; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             "/question" => { | 
		
	
		
			
				|  |  |  |  |                 let (tx, rx) = mpsc::channel(); | 
		
	
		
			
				|  |  |  |  |                 // queue work on our worker | 
		
	
		
			
				|  |  |  |  |                 self.worker_tx.send((self.control.take().unwrap(), tx)); | 
		
	
		
			
				|  |  |  |  |                 // tell hyper we need to wait until we can continue | 
		
	
		
			
				|  |  |  |  |                 return Next::wait(); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             _ => { | 
		
	
		
			
				|  |  |  |  |                 self.status = StatusCode::NotFound; | 
		
	
		
			
				|  |  |  |  |                 self.text = b"Not Found"; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #    fn on_request_readable(&mut self, _decoder: &mut Decoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  | #        Next::write() | 
		
	
		
			
				|  |  |  |  | #    } | 
		
	
		
			
				|  |  |  |  | # | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     fn on_response(&mut self, res: &mut Response) -> Next { | 
		
	
		
			
				|  |  |  |  |         use hyper::header::ContentLength; | 
		
	
		
			
				|  |  |  |  |         res.set_status(self.status); | 
		
	
		
			
				|  |  |  |  |         if let Some(rx) = self.worker_rx.take() { | 
		
	
		
			
				|  |  |  |  |             self.text = rx.recv().unwrap(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         res.headers_mut().set(ContentLength(self.text.len() as u64)); | 
		
	
		
			
				|  |  |  |  |         Next::write() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | # | 
		
	
		
			
				|  |  |  |  | #    fn on_response_writable(&mut self, encoder: &mut Encoder<Http>) -> Next { | 
		
	
		
			
				|  |  |  |  | #        unimplemented!() | 
		
	
		
			
				|  |  |  |  | #    } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | # fn calculate_ultimate_question(rx: mpsc::Receiver<(Control, mpsc::Sender<&'static [u8]>)>) { | 
		
	
		
			
				|  |  |  |  | #    use std::sync::mpsc; | 
		
	
		
			
				|  |  |  |  | #    use std::thread; | 
		
	
		
			
				|  |  |  |  | #    use std::time::Duration; | 
		
	
		
			
				|  |  |  |  | #    thread::spawn(move || { | 
		
	
		
			
				|  |  |  |  | #        while let Ok((ctrl, tx)) = rx.recv() { | 
		
	
		
			
				|  |  |  |  | #            thread::sleep(Duration::from_millis(500)); | 
		
	
		
			
				|  |  |  |  | #            tx.send(b"42").unwrap(); | 
		
	
		
			
				|  |  |  |  | #            ctrl.ready(Next::write()).unwrap(); | 
		
	
		
			
				|  |  |  |  | #        } | 
		
	
		
			
				|  |  |  |  | #    }); | 
		
	
		
			
				|  |  |  |  | # } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn main() { | 
		
	
		
			
				|  |  |  |  |     let (tx, rx) = mpsc::channel(); | 
		
	
		
			
				|  |  |  |  |     calculate_ultimate_question(rx); | 
		
	
		
			
				|  |  |  |  |     let addr = "127.0.0.1:0".parse().unwrap(); | 
		
	
		
			
				|  |  |  |  |     let (listening, server) = Server::http(&addr).unwrap() | 
		
	
		
			
				|  |  |  |  |         .handle(move |ctrl| Text { | 
		
	
		
			
				|  |  |  |  |             status: StatusCode::Ok, | 
		
	
		
			
				|  |  |  |  |             text: b"", | 
		
	
		
			
				|  |  |  |  |             control: Some(ctrl), | 
		
	
		
			
				|  |  |  |  |             worker_tx: tx.clone(), | 
		
	
		
			
				|  |  |  |  |             worker_rx: None, | 
		
	
		
			
				|  |  |  |  |         }).unwrap(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     println!("Listening on http://{}", listening); | 
		
	
		
			
				|  |  |  |  |     server.run() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | [Control]: ../hyper/struct.Control.html | 
		
	
		
			
				|  |  |  |  | [Handler]: ../hyper/server/trait.Handler.html | 
		
	
		
			
				|  |  |  |  | [Next]: ../hyper/struct.Next.html | 
		
	
		
			
				|  |  |  |  | [Server]: ../hyper/server/struct.Server.html | 
		
	
	
		
			
				
					
					| 
							
							
							
						 |  |  |   |