rust - 有没有更简单的方法来创建自定义过滤器方法来调用 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)
-> ->事情handle
在哪里。and_then
map_err
boxed
现在我为每个 arity 处理程序使用一组特征。这是 2-arity 处理程序:
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
语法糖将简单的处理程序自动转换为未来(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)
}
}
在我们的例子中,我给出的错误示例返回一个url::ParseError
. 让我们添加一种将其映射到 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
你想要在处理程序函数中处理的任何新错误类型)
推荐阅读
- android - 有没有办法通过意图或广播接收器从 android 中的谷歌地图应用程序获取 ETA?
- android - Android Flavours:仅将特定于风味的代码应用于源集
- apache - 如何绑定具有crt文件的SSL证书
- ios - 在 project-swift.h 中找不到协议声明
- java - 如何将输出固定在不同的行上以创建 5x5 矩阵?
- javascript - 打字稿 - 在离子中以随机间隔调用函数
- jquery - 如何使用过渡创建文本预加载器
- java - 为按钮的可见性设置计时器
- c - 有没有办法在 C 中编译和执行动态生成的代码?
- java - 安装最新版本的 Sonarqube - 版本:7.9.1 LTS