Module steer

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 std::task::{Context, Poll};
# use tower_service::Service;
# use futures_util::future::{ready, Ready, poll_fn};
# use tower::steer::Steer;
# use tower::service_fn;
# use tower::util::BoxService;
# use tower::ServiceExt;
# use std::convert::Infallible;
use http::{Request, Response, StatusCode, Method};

# #[tokio::main]
# async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Service that responds to `GET /`
let root = service_fn(|req: Request<String>| async move {
    # assert_eq!(req.uri().path(), "/");
    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(), "");
#
# Ok(())
# }

Structs

Traits