而不是编写类似的内容
let hello = get()
.and(path!(String))
.and_then(|string| handlers::hello(string).map_err(warp::reject::custom))
.boxed()
我希望能够写:
let hello = get()
.and(path!(String))
.handle(handlers::hello)
其中CCD_ 1做and_then
->map_err
->boxed
的事情。
现在,我为每个arity处理程序使用一组特性。这是2位处理程序:
pub trait Handle2<A, B, Fut, R, F>
where
R: Reject,
F: Fn(A, B) -> Fut,
Fut: Future<Output = Result<String, R>>,
{
fn handle(self, f: F) -> BoxedFilter<(String,)>;
}
impl<A, B, Fut, R, F, T, Futr> Handle2<A, B, Fut, R, F> for T
where
R: Reject,
F: Fn(A, B) -> Fut + Clone + Sync + Send + 'static,
Fut: Future<Output = Result<String, R>> + Send,
Futr: Future<Output = Result<(A, B), Rejection>> + Send,
T: Filter<Extract = (A, B), Error = Rejection, Future = Futr> + Sync + Send + 'static,
{
fn handle(self, f: F) -> BoxedFilter<(String,)> {
self.and_then(move |a, b| f(a, b).map_err(warp::reject::custom))
.boxed()
}
}
在Rust中可以做到这一点真是太棒了,但有没有更简单的方法来实现这一点?
有.
在您的main((中声明了这样的路由:
let routes = get().and(path("hello")).and_then(routes::getRoot);
您可以使用async
语法sugar将一个简单的处理程序自动转换为未来的处理程序(0.3/std(。这使得它实现了将其用作warp::Filter
:的所有必要特性
// routes/mod.rs
pub async fn getRoot() -> Result<impl warp::Reply, warp::Rejection> {
Ok("Hello world !")
}
到目前为止相当简单!现在,您希望仍然缺少的一件事是使用warp::reject::custom
进行正确的错误处理。
首先,让我们的处理程序返回一个错误:
// routes/mod.rs
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 !")
}
注意到map_err(ServiceError::from)
和返回类型warp::Rejection
了吗?我们需要将特定错误转换为自定义错误枚举(这就是ServiceError,我们很快就会定义它(,然后提供一种将ServiceError自动转换为warp::Rejection的方法。
让我们通过创建一种方法来处理来自所有路由处理程序函数的错误:
// ./errors.rs
/// An internal error enum for representing all the possible failure states
#[derive(thiserror::Error, Debug)]
pub enum ServiceError {
#[error("unacceptable !")]
SomeSpecificWayOfFailing,
#[error(transparent)]
Other(#[from] Box<dyn std::error::Error + Sync + Send>), // catchAll error type
}
impl warp::reject::Reject for ServiceError {}
impl From<ServiceError> for warp::reject::Rejection {
fn from(e: ServiceError) -> Self {
warp::reject::custom(e)
}
}
在我们的例子中,我给出的错误示例返回一个handle
0。让我们添加一种将其映射到ServiceError的方法:
// ./errors.rs
impl From<url::ParseError> for ServiceError {
fn from(e: url::ParseError) -> Self {
ServiceError::Other(e.into()) // you can refine that and turn it into a more specific enum variant of ServiceError here
}
}
你应该做好一切准备。现在,添加一个新的路由/处理程序应该和添加一个异步函数一样简单(再加上为您想在处理程序函数中处理的任何新错误类型添加impl ServiceError::from
(