Используя warp.rs 0.2.2 , давайте рассмотрим базовый c веб-сервис с одним маршрутом для GET /
:
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let getRoot = warp::get().and(warp::path::end()).and_then(routes::getRoot);
warp::serve(getRoot).run(([0, 0, 0, 0], 3030)).await;
Ok(())
}
Моя цель - использовать ?
для обработки ошибок в обработчиках маршрута, поэтому давайте напишем тот, который может ошибаться и возвращаться рано в crate::routes
:
use crate::errors::ServiceError;
use url::Url;
pub async fn getRoot() -> Result<impl warp::Reply, warp::Rejection> {
let _parsed_url = Url::parse(&"https://whydoesn.it/work?").map_err(ServiceError::from)?;
Ok("Hello world !")
}
Эта версия работает. Здесь ошибка, возвращаемая Url::parse()
, представляет собой url::ParseError
Для преобразования между типами ошибок из url::ParseError
в ServiceError
, затем из ServiceError
в warp::Rejection
, я написал несколько помощники по ошибкам в crate::errors
:
#[derive(thiserror::Error, Debug)]
pub enum ServiceError {
#[error(transparent)]
Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error
}
impl warp::reject::Reject for ServiceError {}
impl From<ServiceError> for warp::reject::Rejection {
fn from(e: ServiceError) -> Self {
warp::reject::custom(e)
}
}
impl From<url::ParseError> for ServiceError {
fn from(e: url::ParseError) -> Self {
ServiceError::Other(e.into())
}
}
Теперь вышеприведенное работает, и я пытаюсь сократить второй блок кода, чтобы использовать ?
для прямой обработки ошибок, и автоматически преобразовать из основная ошибка (здесь url::ParseError
) до warp::Rejection
. Вот что я попробовал:
use crate::errors::ServiceError;
use url::Url;
pub async fn getRoot() -> Result<impl warp::Reply, ServiceError> {
let _parsed_url = Url::parse(&"https://whydoesn.it/work?")?;
Ok("Hello world !")
}
url::ParseError
, возвращаемое Url::Parse
, преобразует штраф в ServiceError для возврата, но возврат ServiceError из моего обработчика не работает. Первая ошибка компиляции, которую я получаю:
error[E0277]: the trait bound `errors::ServiceError: warp::reject::sealed::CombineRejection<warp::reject::Rejection>` is not satisfied
--> src/main.rs:102:54
|
102 | let getRoot = warp::get().and(warp::path::end()).and_then(routes::getRoot);
| ^^^^^^^^ the trait `warp::reject::sealed::CombineRejection<warp::reject::Rejection>` is not implemented for `errors::ServiceError`
Есть ли способ сохранить краткую обработку ошибок, используя только ?
и либо:
- make
ServiceError
Implement warp::reject::sealed::CombineRejection<warp::reject::Rejection>
? - обойти это?