< 返回版块

tu6ge 发表于 2024-05-17 08:44

Tags:validator,人体工程学

是的,我要向大家推荐一个项目,一个 rust 验证器项目,在开始之前,请允许我先讲下 axum 项目,是这个项目给了我启发,使我恍然大悟,原来 rust 还可以这么写,原来静态类型的语言也可以这么灵活。写过 rust lib 库的同学可能有体会,就是自己写的函数,参数要么是标准库里的基础类型,要么是自己的类型,如果别人使用的话,没法使用他们自己构造的类型,有些时候感觉很受限制。但是了解了 axum 项目后,才发现是我的思路没有打开。

先给大家看一个例子:

let app = Router::new()
        // `POST /` goes to `root`
        .route("/", post(root))
        // `POST /users` goes to `create_user`
        .route("/users", post(create_user));

async fn root() -> &'static str {
    "Hello, World!"
}

async fn create_user(
    Json(payload): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
    todo!()
}

我们可以在代码中发现,root 和 create_user 是签名完全不同的两个函数,但是他们却可以同时作用于 route 方法的第二个参数,刚看到这个代码的时候,真的让人眼前一亮,仿佛发现了新大陆一样。

也许表单验证也应该像这个一样,每个字段有自己的验证要求,而且它们能够有机的组合在一起,一起验证,一起处理返回的消息

开源是个好东西,可以学习别人的项目是如何实现的,根据他们的经验,归纳总结,吸收思路注入到自己的项目中,然后回馈社区。

经过了一两个月的打磨,一款新的表单验证器的雏形已经出来了:

let validator = Validator::new()
        .rule("name", Required.and(StartWith("hello")))
        .rule("age", custom(age_limit))
        .message([
            ("name.required", "name is required"),
            ("name.start_with", "name should be starts with `hello`"),
        ]);

let person = Person {
        name: "li",
        age: 18,
    };

fn age_limit(n: &mut u8) -> Result<(), Message> {
    if *n >= 25 && *n <= 45 {
        return Ok(());
    }
    Err("age should be between 25 and 45".into())
}

这里要感谢一下 asuper0 (github.com) 同学的热情参与。

验证器跟上面的 web 框架还是有些不同的,验证器其实是由很多不同的规则组合在一起,来处理一个结构体中各个字段是否合规范。关于这些规则,其实有一些是很常用的,比如 Required(必填),Trim, Range(范围),Email 等等,这些可以作为实现了某一个 trait 的不同 struct,当然也必须要有自定义的方式,那就是封装成一个函数。

于是,就有了如下这些组合方式

用法 说明
Required one rule
Required.and(StartsWith("foo")) multi rules
Required.and(StartsWith('a')).bail() multi rules and bail
custom(my_handler) custom handler rule
Required.custom(my_handler) rule and handler rule
Not(StartsWith("foo")) negative rule
Required.and(Not(StartsWith("foo"))) negative rule

所有的这些组合,都实现了 IntoRuleList<M> 这个 trait,所以,它们可以作为同一个函数的同一个参数

完整项目地址: https://github.com/tu6ge/valitron


Ext Link: https://github.com/tu6ge/valitron

评论区

写评论

还没有评论

1 共 0 条评论, 1 页