使用warp.rs 0.2.2,让我们考虑一个基本的 Web 服务,它有一个路由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
to ServiceError
,然后从ServiceError
to 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`
有没有一种方法可以保持简短的错误处理?
只使用和:
ServiceError
实施warp::reject::sealed::CombineRejection<warp::reject::Rejection>
?_- 解决这个问题?