Getting Started with a Server

Let’s start by making a “Hello, World!” server, and expand from there.

First, we need our dependencies. Let’s tell Cargo about our dependencies by having this in the Cargo.toml.

[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }

Now lets start on our main.rs, and add some imports:

# extern crate hyper;
use std::convert::Infallible;
use std::net::SocketAddr;
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
# fn main() {}

Creating a Service

A Service lets you define how to respond to incoming requests. While it is possible to implement the trait directly, there are a few patterns that are common when using Hyper. We’ve included some helpers for when these patterns fit our needs.

In this example, we don’t have any state to carry around, so we really just need a simple async function:

# extern crate hyper;
# use std::convert::Infallible;
# use hyper::{Body, Request, Response};
# fn main() {}
async fn hello_world(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new("Hello, World".into()))
}

As soon as we get a request, nothing is stopping us from knowing the response immediately! That function will be used when starting our server.

That new Response will by default have a 200 OK status code, and the Body is able to tell that it is made from a static string, and is able to add a Content-Length header for us automatically.

Starting the Server

Lastly, we need to hook up our hello_world service into a running hyper Server.

We’ll dive in to the specifics of some of these things in another guide.

# extern crate hyper;
# extern crate tokio;
# mod no_run {
# use std::convert::Infallible;
# use std::net::SocketAddr;
# use hyper::{Body, Request, Response, Server};
# use hyper::service::{make_service_fn, service_fn};
# async fn hello_world(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
#     Ok(Response::new("Hello, World".into()))
# }
#[tokio::main]
async fn main() {
    // We'll bind to 127.0.0.1:3000
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    // A `Service` is needed for every connection, so this
    // creates one from our `hello_world` function.
    let make_svc = make_service_fn(|_conn| async {
        // service_fn converts our function into a `Service`
        Ok::<_, Infallible>(service_fn(hello_world))
    });

    let server = Server::bind(&addr).serve(make_svc);

    // Run this server for... forever!
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}
# }
# fn main() {}

To see all the snippets put together, check out the full example!