Warp.rs:warp :: Reject和使用'?'进行错误处理 [英] Warp.rs: warp::Rejection and error handling using '?'
问题描述
使用 warp.rs 0.2.2 ,让我们考虑基本的Web服务,其中一个路由用于GET /
:
Using warp.rs 0.2.2, let's consider a basic web service with one route for 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
早期返回的代码:
My goal is to use ?
for error handling in the route handlers, so let's write one that can error and return early in 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
This version works.
Here the error that's returned by Url::parse()
is a url::ParseError
要在错误类型之间进行转换,从url::ParseError
到ServiceError
,然后从ServiceError
到warp::Rejection
,我在crate::errors
中编写了一些错误帮助程序:
To convert between error types, from url::ParseError
to ServiceError
, then from ServiceError
to warp::Rejection
, I've written some error helpers in 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
.
这是我尝试过的:
Now, the above works, and I'm trying to shorten the second code block to use ?
for error handling directly, and convert automatically from the underlying error (here url::ParseError
) to a warp::Rejection
.
Here's what I've tried:
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::Parse
返回的url::ParseError
可以很好地转换为ServiceError以返回,但是从我的处理程序中返回ServiceError不起作用.
我得到的第一个编译错误是:
The url::ParseError
returned by Url::Parse
will convert fine into a ServiceError to return, but returning a ServiceError from my handler doesn't work.
The first compilation error I get is:
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`
有没有一种方法可以仅使用?
和以下任一方法来保持简短的错误处理:
Is there a way I can keep the short error handling using ?
only and either:
- 使
ServiceError
实现warp::reject::sealed::CombineRejection<warp::reject::Rejection>
吗? - 解决这个问题吗?
- make
ServiceError
implementwarp::reject::sealed::CombineRejection<warp::reject::Rejection>
? - work around that ?
推荐答案
我已经仔细研究了一段时间.根据我的发现,有两种解决方案.
I have been looking into exactly this for a while now. From my findings there are two solutions.
1:使用一个宏,如果存在错误,该宏将构造并从中返回响应.本质上是放弃?为您自己的宏.
1: Use a macro that if there is an error constructs and returns a response from it. In essence abandon ? for your own macro.
2:使用cjbassi当前的PR#458代替以下版本的主线发布:
2: Use the current PR #458 by cjbassi instead of the mainline release by:
- 实施warp :: reply ::答复您的错误类型,以便将其转换为正确的面向用户的错误消息.
- 替换'warp ='0.2''在Cargo.toml文件中使用'warp = {git ="https://github.com/cjbassi/warp.git",branch ="error"}'
- 使用.map_async代替.and_then作为处理程序
这篇关于Warp.rs:warp :: Reject和使用'?'进行错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!