- Create a Rust project to work on during this chapter with cargo new chapter-nine
- Navigate into the newly created chapter-nine folder. For the rest of this chapter, we will assume that your command line is currently in this directory
- Open the Cargo.toml file that has been generated for you
-
Under [dependencies], add the following lines:
futures = "0.1.18"
hyper = "0.11.21"
- If you want, you can go to futures' (https://crates.io/crates/futures) and hyper's (https://crates.io/crates/hyper) crates.io pages to check for the newest version and use that one instead
- Inside the folder src, create a new folder called bin
- Delete the generated lib.rs file, as we are not creating a library
- In the folder src/bin, create a file called hello_world_server.rs
- Add the following code and run it with cargo run --bin hello_world_server:
1 extern crate futures; 2 extern crate hyper; 3 4 use futures::future::Future; 5 use hyper::header::{ContentLength, ContentType}; 6 use hyper::server::{const_service, service_fn, Http, Request, Response, Service}; 7 use std::net::SocketAddr; 8 9 const MESSAGE: &str = "Hello World!"; 10 11 fn main() { 12 // [::1] is the loopback address for IPv6, 3000 is a port 13 let addr = "[::1]:3000".parse().expect("Failed to parse address"); 14 run_with_service_function(&addr).expect("Failed to run web server"); 15 }
Run a server by creating a service with service_fn:
17 fn run_with_service_function(addr: &SocketAddr) -> Result<(),
hyper::Error> { 18 // Hyper is based on Services, which are construct that 19 // handle how to respond to requests. 20 // const_service and service_fn are convenience functions 21 // that build a service out of a closure 22 let hello_world = const_service(service_fn(|_| { 23 println!("Got a connection!"); 24 // Return a Response with a body of type hyper::Body 25 Ok(Response::::new() 26 // Add header specifying content type as plain text 27 .with_header(ContentType::plaintext()) 28 // Add header specifying the length of the message in
bytes 29 .with_header(ContentLength(MESSAGE.len() as u64)) 30 // Add body with our message 31 .with_body(MESSAGE)) 32 })); 33 34 let server = Http::new().bind(addr, hello_world)?; 35 server.run() 36 }
Run a server by manually creating a struct that implements Service:
38 // The following function does the same, but uses an explicitely
created 39 // struct HelloWorld that implements the Service trait 40 fn run_with_service_struct(addr: &SocketAddr) -> Result<(),
hyper::Error> { 41 let server = Http::new().bind(addr, || Ok(HelloWorld))?; 42 server.run() 43 } 44 45 struct HelloWorld; 46 impl Service for HelloWorld { 47 // Implementing a server requires specifying all involved
types 48 type Request = Request; 49 type Response = Response; 50 type Error = hyper::Error; 51 // The future that wraps your eventual Response 52 type Future = Box<Future>; 53 54 fn call(&self, _: Request) -> Self::Future { 55 // In contrast to service_fn, we need to explicitely return
a future 56 Box::new(futures::future::ok( 57 Response::new() 58 .with_header(ContentType::plaintext()) 59 .with_header(ContentLength(MESSAGE.len() as u64)) 60 .with_body(MESSAGE), 61 )) 62 } 63 }