Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

bnjjj/tide-validator

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tide-validator


tide-validator is a middleware working with Tide, a web framework in Rust which let you validate your data coming from a request. You'll be able to create custom validators to validate your HTTP parameters, query parameters, cookies and headers.

Features

  • Custom validators: you can chain multiple validators and develop a custom validator is very easy. It's just a closure.
  • Validate everything: with the enum HttpField you can validate different fields like cookies, headers, query parameters and parameters.
  • Your own errors: thanks to generics in Rust you can use your own custom error when the data is invalid. need.

Validators

To create your own validator it's just a closure to create with this form:

// 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

Documentation

The full documentation is available here

Examples

  • simple validation
// 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?;
  • chain multiple validators
// 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?;
  • Use your own custom error
// 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
  • Dynamic validators
// 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));

About

A middleware working with Tide to validate your data coming from a request

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.