-
-
Notifications
You must be signed in to change notification settings - Fork 719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rejection and anyhow #307
Comments
Hi @Geobert, it should be the other way around, wrapping |
I see, so we can't use |
yea, |
Might want to re-open this. It doesn't seem to be possible on master since #311
This seems to mean it's only possible to use custom rejections with types defined locally in your crate (Lack of blanket impl?). This is what I use as a workaround: #[derive(Debug)]
struct CustomReject(anyhow::Error);
impl warp::reject::Reject for CustomReject {}
pub(crate) fn custom_reject(error: impl Into<anyhow::Error>) -> warp::Rejection {
warp::reject::custom(CustomReject(error.into()))
} |
We are using In a nutshell it works like this:
|
I have tried to follow what @thomaseizinger has suggested. It is a really clean approach.
I have put together sample code to recreate the issue: use warp::Filter;
#[tokio::main]
async fn main() {
pretty_env_logger::init();
let sample_route = warp::path!("repo" / String).and_then(handler::get_something);
let routes = warp::get()
.and(sample_route)
.recover(problem::unpack_problem);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
mod handler {
use warp::{self, Rejection, Reply};
pub async fn get_something(some_arg: String) -> Result<impl Reply, Rejection> {
super::service::get_something(&some_arg)
.await
.map_err(super::problem::from_anyhow)
.map_err(|e| warp::reject::custom(e))
}
}
mod service {
use anyhow::{anyhow, Result};
pub async fn get_something(some_arg: &str) -> Result<String> {
Err(anyhow!("An error occured!"))
}
}
mod problem {
use http_api_problem::HttpApiProblem;
use warp::{
self,
http::{self, StatusCode},
Rejection, Reply,
};
pub fn from_anyhow(e: anyhow::Error) -> HttpApiProblem {
let e = match e.downcast::<HttpApiProblem>() {
Ok(problem) => return problem,
Err(e) => e,
};
HttpApiProblem::new(format!("Internal Server Error\n{:?}", e))
.set_status(warp::http::StatusCode::INTERNAL_SERVER_ERROR)
}
pub async fn unpack_problem(rejection: Rejection) -> Result<impl Reply, Rejection> {
if let Some(problem) = rejection.find::<HttpApiProblem>() {
let code = problem.status.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
let reply = warp::reply::json(problem);
let reply = warp::reply::with_status(reply, code);
let reply = warp::reply::with_header(
reply,
http::header::CONTENT_TYPE,
http_api_problem::PROBLEM_JSON_MEDIA_TYPE,
);
return Ok(reply);
}
Err(rejection)
}
}
Output:
@thomaseizinger I tried going through the repo https://github.com/comit-network/comit-rs and couldn't find how you resolved this. Maybe I didn't look at the right place. Any help is appreciated. Thank you! |
You need to activate the optional |
Thank you @thomaseizinger
It resolved the issue:
|
The rejection system was design at a time where anyhow did not exist yet (around one full year before the first release). I think at that time, it was really useful because there wasn't a really good way of handling several different kinds of errors nicely. Hence I guess it was acceptable to have them all implement However, anyhow completely changed the game. It is super nice for application code to just use Are there any plans on supporting the anyhow usecase better @seanmonstar? Given the feature overlap between the rejection system and anyhow, it might not even be too far fetched to just use anyhow internally? |
Ping @seanmonstar. I see you haven't been quite active recently — would a PR from someone else along the lines of what @thomaseizinger described be acceptable? |
@thomaseizinger If you scroll to the beginning of this issue, you can see @jhpratt there have already been submissions regarding this: #374, #527 and #588 |
Thanks @jxs for pointing this out! I did indeed miss that there was a re-design of the rejection system since it's first appearance. Despite the workaround that I suggested earlier in this thread, I still believe that a different design of the rejection system could make usage of warp a lot more ergonomic. Maybe we can use this issue to get a discussion around this started like @seanmonstar recommended here? Here is what things look like from my experience with warp:
Generally, I can very much understand the intention for "people should think about meaningful rejections". However, I don't think the current design encourages that a whole lot as it primarily increases verbosity. On the upside, being able to |
but you can, you just have to
can't you have multiple rejections across domains that by themselves impl |
Are you referring to
I am afraid I don't follow what you are suggesting :/ |
Hi,
I'm trying to use
anyhow
but as warp::reject::Rejection doesn't impl std::error::Error, they doesn't compose well.Am I missing something or it just can't be done (yet)?
The text was updated successfully, but these errors were encountered: