首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有一种方法可以在Warp中作为过滤器的一部分进行验证?

是否有一种方法可以在Warp中作为过滤器的一部分进行验证?
EN

Stack Overflow用户
提问于 2020-03-05 22:19:53
回答 1查看 2.1K关注 0票数 8

我定义了一个路由和一个端点函数。我还注入了一些依赖项。

代码语言:javascript
运行
复制
pub fn route1() -> BoxedFilter<(String, ParamType)> {
    warp::get()
        .and(warp::path::param())
        .and(warp::filters::query::query())
        .and(warp::path::end())
        .boxed()
}

pub async fn handler1(
    query: String,
    param: ParamType,
    dependency: DependencyType,
) -> Result<impl warp::Reply, warp::Rejection> {
}
代码语言:javascript
运行
复制
let api = api::routes::route1()
    .and(warp::any().map(move || dependency))
    .and_then(api::hanlders::hander1);

这一切似乎都很好。

但是,我希望能够在几个端点前面检查查询参数中的有效密钥。在handler1内部,我可以添加:

代码语言:javascript
运行
复制
if !param.key_valid {
    return Ok(warp::reply::with_status(
        warp::reply::json(&""),
        StatusCode::BAD_REQUEST,
    ));
}

我不想把它单独添加到每个处理程序中。

看起来我应该可以通过filter来做这件事,但是我想不出来。我尝试过使用.map(),但是返回多个项会将其转换为元组,并且必须更改下游函数签名。理想情况下,我希望找到一种方法来添加验证或其他过滤器,这些过滤器可以在没有任何下游值的情况下拒绝请求。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-11 02:58:47

这在warp的拒收实例中得到了有效的证明。

拒绝表示筛选器不应该继续处理请求,但是不同的筛选器可以处理它。从"div-by“标头中提取分母,或者用DivideByZero拒绝。

你需要

  1. 使用Filter::and_then接受现有过滤器(在本例中为query())并执行验证。如果验证失败,则返回自定义拒绝。
  2. 使用Filter::recover适当地处理自定义拒绝和任何其他可能的错误。

适用于你的情况:

代码语言:javascript
运行
复制
use serde::Deserialize;
use std::{convert::Infallible, net::IpAddr};
use warp::{filters::BoxedFilter, http::StatusCode, reject::Reject, Filter, Rejection, Reply};

fn route1() -> BoxedFilter<(String, ParamType)> {
    warp::get()
        .and(warp::path::param())
        .and(validated_query())
        .and(warp::path::end())
        .boxed()
}

#[derive(Debug)]
struct Invalid;
impl Reject for Invalid {}

fn validated_query() -> impl Filter<Extract = (ParamType,), Error = Rejection> + Copy {
    warp::filters::query::query().and_then(|param: ParamType| async move {
        if param.valid {
            Ok(param)
        } else {
            Err(warp::reject::custom(Invalid))
        }
    })
}

async fn report_invalid(r: Rejection) -> Result<impl Reply, Infallible> {
    let reply = warp::reply::reply();

    if let Some(Invalid) = r.find() {
        Ok(warp::reply::with_status(reply, StatusCode::BAD_REQUEST))
    } else {
        // Do better error handling here
        Ok(warp::reply::with_status(
            reply,
            StatusCode::INTERNAL_SERVER_ERROR,
        ))
    }
}

async fn handler1(
    _query: String,
    _param: ParamType,
    _dependency: DependencyType,
) -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::reply())
}

struct DependencyType;

#[derive(Deserialize)]
struct ParamType {
    valid: bool,
}

#[tokio::main]
async fn main() {
    let api = route1()
        .and(warp::any().map(move || DependencyType))
        .and_then(handler1)
        .recover(report_invalid);

    let ip: IpAddr = "127.0.0.1".parse().unwrap();
    let port = 8888;
    warp::serve(api).run((ip, port)).await;
}

不相关线条的卷曲输出:

代码语言:javascript
运行
复制
% curl -v '127.0.0.1:8888/dummy/?valid=false'
< HTTP/1.1 400 Bad Request

% curl -v '127.0.0.1:8888/dummy/?valid=true'
< HTTP/1.1 200 OK

Cargo.toml

代码语言:javascript
运行
复制
[dependencies]
warp = "0.2.2"
serde = { version = "1.0.104", features = ["derive"] }
tokio = { version = "0.2.13", features = ["full"] }
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60554783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档