有没有一种更简单的方法可以创建一个自定义Filter方法来调用Warp处理程序



而不是编写类似的内容

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)
}
}

在我们的例子中,我给出的错误示例返回一个handle0。让我们添加一种将其映射到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(

最新更新