hit-box / hitbox

A high-performance caching framework suitable for single-machine and for distributed applications in Rust
MIT License
73 stars 6 forks source link

Custom rules for URL declaration #38

Closed AndreyErmilov closed 1 year ago

AndreyErmilov commented 2 years ago

Find ready-to-use crate to match and validate routes. Route format (for example): '/clusters/{cluster_id:i32}/comments/'

novikovfred commented 2 years ago

I think https://github.com/http-rs/route-recognizer is what we were looking for, except path params types. Iron router is based on this crate. This is an example of using it.

use route_recognizer::{Router, Params};

fn main() {
    let mut router = Router::new();

    router.add("/thomas/:thomas_id", "Thomas".to_string());
    router.add("/wycats", "Yehuda".to_string());
    // recognize clean
    let matched_clean = router.recognize("/wycats").unwrap();
    assert_eq!(matched_clean.handler().as_str(), "Yehuda");
    assert_eq!(matched_clean.params(), &Params::new());

    // recognize with path params
    let matched_path = router.recognize("/thomas/12").unwrap();
    assert_eq!(matched_path.handler().as_str(), "Thomas");
    let mut params = Params::new();
    params.insert(String::from("thomas_id"), String::from("12"));
    assert_eq!(matched_path.params(), &params);
}

So, is it okay to use syntax like this? /thomas/:thomas_id

novikovfred commented 2 years ago

The same example based on actix-router

use actix_router::{Router};

fn main() {
    let mut router = Router::<String>::build();
    router.path("/thomas/{thomas_id}/comments", "Thomas".to_string());
    router.path("/wycats", "Yehuda".to_string());

    let actix = router.finish();

    let mut path = actix_router::Path::new("/thomas/12/comments");
    let matched_path = actix.recognize(&mut path).unwrap();
    assert_eq!(matched_path.0, "Thomas");

    let mut path = actix_router::Path::new("/wycats");
    let matched_clean = actix.recognize(&mut path).unwrap();
    assert_eq!(matched_clean.0, "Yehuda");
}

Didn't find any possibility to set path param type.

novikovfred commented 2 years ago

UPD: in actix we can use regex

use actix_router::{Router};

fn main() {
    let mut router = Router::<String>::build();
    router.path("/thomas/{thomas_id:[0-9]+}/comments", "Thomas1".to_string());
    router.path("/thomas/{thomas_id:[a-zA-Z]+}/comments", "Thomas2".to_string());
    router.path("/wycats", "Yehuda".to_string());
    let actix = router.finish();

    let mut path = actix_router::Path::new("/thomas/12/comments");
    let matched_path = actix.recognize(&mut path).unwrap();
    assert_eq!(matched_path.0, "Thomas1");
    let thomas_id = path.get("thomas_id").unwrap();
    println!("{}", thomas_id);

    let mut path_2 = actix_router::Path::new("/thomas/abf/comments");
    let matched_path_2 = actix.recognize(&mut path_2).unwrap();
    assert_eq!(matched_path_2.0, "Thomas2");
    let thomas_id = path_2.get("thomas_id").unwrap();
    println!("{}", thomas_id);

    let mut path_3 = actix_router::Path::new("/thomas/ab2f/comments");
    let matched_path_3 = actix.recognize(&mut path_3);
    assert_eq!(matched_path_3, None);
}
AndreyErmilov commented 2 years ago

@novikovfred LGTM! I think we can use it 👍

singulared commented 2 years ago

I think we don't need typing in routes. We can interpret all params as strings and nothing changes.