Search code examples
rustrust-warp

Dependency Injection in Rust Warp


How do I inject dependencies into my route handlers in Warp? A trivial example is as follows. I have a route that I want to serve a static value that is determined at startup time, but the filter is what passes values into the final handler. How do I pass additional data without creating global variables? This would be useful for dependency injection.

pub fn root_route() -> BoxedFilter<()> {
    warp::get().and(warp::path::end()).boxed()
}

pub async fn root_handler(git_sha: String) -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::json(
        json!({
             "sha": git_sha
        })
            .as_object()
            .unwrap(),
    ))
}


#[tokio::main]
async fn main() {
    let git_sha = "1234567890".to_string();
    let api = root_route().and_then(root_handler);
    warp::serve(api).run(([0,0,0,0], 8080)).await;
}

Solution

  • Here is a simple example. By using the .and() in conjunction with .map(move ||) you can add parameters to the tuple that will be passed into the final handler function.

    use warp::filters::BoxedFilter;
    use warp::Filter;
    #[macro_use]
    extern crate serde_json;
    
    pub fn root_route() -> BoxedFilter<()> {
        warp::get().and(warp::path::end()).boxed()
    }
    
    pub async fn root_handler(git_sha: String) -> Result<impl warp::Reply, warp::Rejection> {
        Ok(warp::reply::json(
            json!({
                 "sha": git_sha
            })
                .as_object()
                .unwrap(),
        ))
    }
    
    pub fn with_sha(git_sha: String) -> impl Filter<Extract = (String,), Error = std::convert::Infallible> + Clone {
        warp::any().map(move || git_sha.clone())
    }
    
    #[tokio::main]
    async fn main() {
        let git_sha = "1234567890".to_string();
        let api = root_route().and(with_sha(git_sha)).and_then(root_handler);
        warp::serve(api).run(([0,0,0,0], 8080)).await;
    }