问题描述
使用 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>
吗? - 解决这个问题吗?
推荐答案
从我的发现中,有两种解决方案.
From my findings, there are two solutions.
-
放弃
?
,转而支持您自己的宏,该宏可以构造并在出现错误时返回响应.
Abandon
?
in favor of your own macro that constructs and returns a response if there is an error.
使用cjbassi的 PR#458 代替由:
Use PR #458 by cjbassi instead of the mainline release by:
- 对错误类型实施
warp :: reply :: Reply
,以便将其转换为正确的面向用户的错误消息. - 将
warp ="0.2"
替换为warp = {git ="https://github.com/cjbassi/warp.git",分支="error";}
在您的Cargo.toml文件中 - 使用
.map_async
代替.and_then
作为处理程序
- Implementing
warp::reply::Reply
on your error type so that it converts into the correct user facing error message. - Replace
warp = "0.2"
withwarp = { git = "https://github.com/cjbassi/warp.git", branch = "error"}
in your Cargo.toml file - use
.map_async
instead of.and_then
for handlers
这篇关于如何同时使用拒绝和问号运算符处理Warp中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!