Module hreq::server[][src]

Server that handles http requests.

hreq can act as an http server. It supports path based routing to functions acting as handlers, middleware chains and state handling.

Example

use hreq::prelude::*;
use hreq::server::Next;

async fn start_server() {
   // Server without a state
   let mut server = Server::new();

   // route requests for /hello/<name> where
   // "name" is a path parameter that can
   // be obtained in the request handler.
   server.at("/hello/:name")
       // logging middleware
       .middleware(logging)
       // dispatch to the handler
       .get(hello_there);

   // Listen without TLS
   let (handle, addr) = server.listen(3000).await.unwrap();

   println!("Server listening to: {}", addr);

   handle.keep_alive().await;
}

// Middleware logging request and response
async fn logging(
   req: http::Request<Body>, next: Next
) -> http::Response<Body> {

    println!("Request is: {:?}", req);
    let res = next.run(req).await.unwrap();
    println!("Response is: {:?}", res);

    res
}

// Handler of request producing responses. The String is
// converted to a 200 response with text/plain.
async fn hello_there(req: http::Request<Body>) -> String {
   format!("Hello {}", req.path_param("name").unwrap())
}

Path parameters

hreq does parsing of path parameters as part of routing.

  1. /literal matches exactly.
  2. /:param_name matches a single path segment delimited by / and binds param_name parameter.
  3. /*rest_name matches the rest of the path and binds rest_name parameter.

The bound parameters are available using path_param().

Examples

  • server.at("/user") matches the path /user without resulting in a path parameter.
  • server.at("/user/:userId") matches /user/abc123 with path parameter userId set to abc123.
  • server.at("/user/:userId") does not math /user/abc123/hello.
  • server.at("/user/:userId/*whatever") matches /user/abc123/hello with path parameter userId set to abc123 and whatever set to hello.
use hreq::prelude::*;
use hreq::server::Next;

async fn start_server() {
   let mut server = Server::new();

   server.at("/hello/:name/*the_rest").get(hello_there);

   // Listen without TLS
   let (handle, addr) = server.listen(3000).await.unwrap();

   println!("Server listening to: {}", addr);

   handle.keep_alive().await;
}

async fn hello_there(req: http::Request<Body>) -> String {
   println!("All params {:?}", req.path_params()); // prints ["name", "the_rest"]
   format!("Hello {}: {}",
       req.path_param("name").unwrap(),
       req.path_param("the_rest").unwrap())
}

State

Many servers needs to work over some shared mutable state to function. The server runs in an async runtime (tokio), typically with multiple threads accepting connections. Therefore the state needs to be shareable between threads, in rust terms Sync, as well being clonable with Clone.

In practice this often means using a strategy seen in a lot of Rust code: wrapping the state in Arc<Mutex<State>>.

Example

use hreq::prelude::*;
use std::sync::{Arc, Mutex};

#[derive(Clone)]
struct MyCounter(Arc<Mutex<u64>>);

async fn start_server() {
   // Shared state
   let state = MyCounter(Arc::new(Mutex::new(0)));
   // Server with a state
   let mut server = Server::with_state(state);

   server.at("/do_something")
       // use stateful middleware/handlers
       .with_state()
       .get(my_handler);

   let (handle, addr) = server.listen(3000).await.unwrap();

   handle.keep_alive().await;
}

async fn my_handler(
    counter: MyCounter,
    req: http::Request<Body>
) -> String {
    let mut lock = counter.0.lock().unwrap();
    let req_count = *lock;
    *lock += 1;
    format!("Req number: {}", req_count)
}

Structs

Next

Type passed to middleware to continue the request chain.

Reply

Concrete return type from endpoints and middleware.

Route

A route as obtained by Server::at or Router::at.

Router

Encapsulate chains of Middleware and Handler.

Server

Server of http requests.

ServerHandle

Handle to a running server.

StateRoute

A state route as obtained by with_state.

Static

Serve static files.

TlsConfig

Configuration builder for Server::listen_tls.

Traits

Handler

Trait for a request handler that doesn’t use a state.

Middleware

Trait for middleware that doesn’t use a state.

ResponseBuilderExt

Extends http::response::Builder with ergonomic extras for hreq.

ServerRequestExt

Extends http::Request with ergonomic extras for server requests to hreq.

StateHandler

Trait for a request handler that use a state.

StateMiddleware

Trait for middleware that use a state.