3个不稳定版本
0.8.0 | 2020年5月2日 |
---|---|
0.1.1 | 2020年4月19日 |
0.1.0 | 2020年4月19日 |
#1230 in HTTP服务器
31KB
337 行
tide-validator
tide-validator 是一个与 Tide 框架一起工作的中间件,它允许您验证来自请求的数据。您将能够创建自定义验证器来验证您的HTTP参数、查询参数、cookie和头信息。
特性
- 自定义验证器:您可以链式调用多个验证器,并非常容易地开发自定义验证器。它只是一个闭包。
- 验证一切:使用枚举
HttpField
,您可以验证不同的字段,如cookie、头信息、查询参数和参数。 - 您自己的错误:多亏了Rust中的泛型,当数据无效时,您可以使用自己的自定义错误。
验证器
要创建您自己的验证器,只需使用以下形式的闭包即可
// The first closure's parameter is the parameter/queryparameter/cookie/header name.
// The second parameter is the value of this HTTP element.
// None means the field doesn't exist in the request (useful to force specific fields to be required).
Fn(&str, Option<&str>) -> Result<(), T> + Send + Sync + 'static where T: Serialize + Send + Sync + 'static
文档
完整文档在此处可用 这里
示例
- 简单验证
// Our own validator is a simple closure to check if the field is a number
fn is_number(field_name: &str, field_value: Option<&str>) -> Result<(), String> {
if let Some(field_value) = field_value {
if field_value.parse::<i64>().is_err() {
return Err(format!("field '{}' = '{}' is not a valid number", field_name, field_value));
}
}
Ok(())
}
//... in main function
let mut app = tide::new();
let mut validator_middleware = ValidatorMiddleware::new();
// 'age' is the parameter name inside the route '/test/:age'
validator_middleware.add_validator(HttpField::Param("age"), is_number);
// You can assign different middleware for each routes therefore different validators for each routes
app.at("/test/:age")
.middleware(validator_middleware)
.get(|_: tide::Request<()>| async move {
let cat = Cat {
name: "Gribouille".into(),
};
tide::Response::new(StatusCode::Ok).body_json(&cat).unwrap()
});
app.listen("127.0.0.1:8080").await?;
- 链式多个验证器
// This validator force element to be required
fn is_required(field_name: &str, field_value: Option<&str>) -> Result<(), String> {
if field_value.is_none() {
Err(format!("'{}' is required", field_name))
} else {
Ok(())
}
}
// ... your main function
let mut app = tide::new();
let mut validator_middleware = ValidatorMiddleware::new();
// Here 'age' is a query parameter, the validator stay the same as in previous example
validator_middleware.add_validator(HttpField::QueryParam("age"), is_number);
// You can also add multiple validators on a single query parameter to check different things
validator_middleware.add_validator(HttpField::QueryParam("age"), is_required);
// You can assign different middleware for each routes therefore different validators for each routes
app.at("/test")
.middleware(validator_middleware)
.get(|_: tide::Request<()>| async move {
let cat = Cat {
name: "Mozart".into(),
};
tide::Response::new(StatusCode::Ok).body_json(&cat).unwrap()
},
);
app.listen("127.0.0.1:8080").await?;
- 使用您自己的自定义错误
// Your custom error which your api will send if an error occurs
#[derive(Debug, Serialize)]
struct CustomError {
status_code: usize,
message: String,
}
// Your validator can also return your own error type
fn is_number(field_name: &str, field_value: Option<&str>) -> Result<(), CustomError> {
if let Some(field_value) = field_value {
if field_value.parse::<i64>().is_err() {
return Err(CustomError {
status_code: 400,
message: format!(
"field '{}' = '{}' is not a valid number",
field_name, field_value
),
});
}
}
Ok(())
}
// ... your main function
- 动态验证器
// Validator inside a function as a closure to be dynamic with max_length
fn is_length_under(
max_length: usize,
) -> Box<dyn Fn(&str, Option<&str>) -> Result<(), CustomError> + Send + Sync + 'static> {
Box::new(
move |field_name: &str, field_value: Option<&str>| -> Result<(), CustomError> {
if let Some(field_value) = field_value {
if field_value.len() > max_length {
let my_error = CustomError {
status_code: 400,
message: format!(
"element '{} which is equals to '{}' have not the maximum length of {}",
field_name, field_value, max_length
),
};
return Err(my_error);
}
}
Ok(())
},
)
}
// Simply call it on a cookie `session` for example:
validator_middleware.add_validator(HttpField::Cookie("session"), is_length_under(20));
依赖项
~13–28MB
~422K SLoC