Module tower::steer

source · []
Available on crate feature steer only.
Expand description

This module provides functionality to aid managing routing requests between Services.

Example

Steer can for example be used to create a router, akin to what you might find in web frameworks.

Here, GET / will be sent to the root service, while all other requests go to not_found.

use http::{Request, Response, StatusCode, Method};

// Service that responds to `GET /`
let root = service_fn(|req: Request<String>| async move {
    let res = Response::new("Hello, World!".to_string());
    Ok::<_, Infallible>(res)
});
// We have to box the service so its type gets erased and we can put it in a `Vec` with other
// services
let root = BoxService::new(root);

// Service that responds with `404 Not Found` to all requests
let not_found = service_fn(|req: Request<String>| async move {
    let res = Response::builder()
        .status(StatusCode::NOT_FOUND)
        .body(String::new())
        .expect("response is valid");
    Ok::<_, Infallible>(res)
});
// Box that as well
let not_found = BoxService::new(not_found);

let mut svc = Steer::new(
    // All services we route between
    vec![root, not_found],
    // How we pick which service to send the request to
    |req: &Request<String>, _services: &[_]| {
        if req.method() == Method::GET && req.uri().path() == "/" {
            0 // Index of `root`
        } else {
            1 // Index of `not_found`
        }
    },
);

// This request will get sent to `root`
let req = Request::get("/").body(String::new()).unwrap();
let res = svc.ready().await?.call(req).await?;
assert_eq!(res.into_body(), "Hello, World!");

// This request will get sent to `not_found`
let req = Request::get("/does/not/exist").body(String::new()).unwrap();
let res = svc.ready().await?.call(req).await?;
assert_eq!(res.status(), StatusCode::NOT_FOUND);
assert_eq!(res.into_body(), "");

Structs

Steer manages a list of Services which all handle the same type of request.

Traits

This is how callers of Steer tell it which Service a Req corresponds to.