#service-request #dispatch #routes #tower #convert #ready #steer

tower_type_steer

Steer (aka route, aka dispatch) request to service based on their types

1 unstable release

0.1.0 Oct 5, 2024

#622 in Encoding

Download history 145/week @ 2024-10-05 3/week @ 2024-10-12

148 downloads per month

MIT license

8KB
130 lines

Dispatch request to service by trying to convert to the service's request type.

use futures::future::ready;
use serde::Deserialize;
use tower::{service_fn, Service, ServiceBuilder, ServiceExt};
use tower_type_steer::Converter;

#[derive(Deserialize, Clone)]
struct Foo {
    x: i8,
    y: i8,
}

#[derive(Deserialize, Clone)]
struct Bar {
    z: i8,
}

fn main() {
    //  impl Service<Foo>
    let foo_service = service_fn(|foo: Foo| ready(foo.x.checked_add(foo.y).ok_or("Overflow")));
    //  impl Service<Bar>
    let bar_service = service_fn(|bar: Bar| ready(Ok::<_, &'static str>(bar.z)));
    let error_service = service_fn(|_: &str| ready(Err::<i8, _>("No matching json")));
    let mut s = ServiceBuilder::new()
        .layer(tower_type_steer::serde_conv::json().wrap(foo_service))
        .layer(tower_type_steer::serde_conv::json().wrap(bar_service))
        .service(error_service);
    let res: Result<_, &str> = futures::executor::block_on(async move {
        let s = s.ready().await?;
        let res = [
            // Ok(5) (foo_service)
            s.call(r#"{"x": 3, "y": 2}"#).await,
            // Err("Overflow") (foo_service)
            s.call(r#"{"x": 120, "y": 120}"#).await,
            // Err("Ok(2)") (bar_service)
            s.call(r#"{"z": 2}"#).await,
            // Err("No matching json") (error_service)
            s.call(r#"{}"#).await,
        ];
        Ok(res)
    });
    println!("{res:?}");
}

Dependencies

~0.6–1MB
~20K SLoC