I'm trying to structure a non-trivial warp REST application into modules while handling errors and rejections elegantly. It's not working out the way I expect. Consider this simple application:
main.rs
use warp_sample::routes;
#[tokio::main]
async fn main() {
warp::serve(routes::convert_route()).run(([127, 0, 0, 1], 8080)).await;
}
routes.rs
use warp::{Filter, Rejection, Reply};
use crate::handlers;
pub fn convert_route() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path("convert")
.and(warp::path::param::<String>())
.map(|v: String| {
handlers::convert_str(&v).or_else(|e| e)
})
}
handlers.rs
use warp::{Reply, Rejection};
pub fn convert_str(s: &str) -> Result<impl Reply, Rejection>{
match s.parse::<i32>() {
Ok(s) => Ok(warp::reply()),
Err(_) => Err(warp::reject())
}
}
This does not compile because in routes.rs I am trying to return a Rejection struct in the closure which does not match return type of impl Reply
.
How do I get this to work? I have tried to change the return type of convert_route
but that does not work with warp::serve
.
For bonus marks, can you show me how to include a plain text respond in the handler when successful and a different status code when there is an error?
This does not work for the bonus, but it shows you what I am thinking.
pub fn convert_str(s: &str) -> Result<impl Reply, Rejection>{
match s.parse::<i32>() {
Ok(s) => Ok(warp::body(s)),
Err(_) => Err(warp::Rejection {
reason: Reason::BadRequest,
})
}
}