HTTP Request URL Parameters Syntax

| Pattern | Kind | Description | | ------------------------------- | ------------------- | ------------------------------------------------------------------------------ | | :name | Normal | Matches a path piece, excludes / | | :name? | Optional | Matches an optional path piece, excludes / | | /:name?/ /:name? | OptionalSegment | Matches an optional path segment, excludes /, prefix or suffix should be / | | + :name+ | OneOrMore | Matches a path piece, includes / | | * :name* | ZeroOrMore | Matches an optional path piece, includes / | | /*/ /* /:name*/ /:name* | ZeroOrMoreSegment | Matches zero or more path segments, prefix or suffix should be /

⚡️ Quick Start

use hypers's full feature

````rust use headers::{authorization::Bearer, Authorization}; use hypers::prelude::*; use std::time::Instant; use tracing::info;

[derive(Serialize, Deserialize)]

pub struct CookieJarParams { pub hypers: String, pub rust: String, }

[derive(Serialize, Deserialize)]

pub struct HeaderParams { pub host: Option, #[serde(rename(deserialize = "user-agent"))] pub user_agent: Option, pub accept: Option, }

[derive(Debug, Default, Serialize, Deserialize, Validate)]

pub struct UserController { pub id: Option, #[validate(email)] pub email: Option, #[validate(range(min = 18, max = 20))] pub age: Option, }

// http://127.0.0.1:7878/api/v1/user

[controller(prefix = "api", version = 1, name = "user")]

impl UserController { // Request Cookies #[get("parsecookies")] pub async fn parsecookies(req: Request) -> impl Responder { let cookiejar = req.parsecookies::()?; Ok::<_, Error>((200, Json(cookie_jar))) }

// Request Headers
#[get("/parse_header")]
pub async fn parse_header(req: Request) -> impl Responder {
    let header_params = req.parse_header::<HeaderParams>()?;
    Ok::<_, Error>((200, Json(header_params)))
}

// Url Path Params
#[delete("parse_param/:id/:name/:age")]
pub async fn parse_param(req: Request, id: u32, name: String, age: u16) -> impl Responder {
    let app_state = req.get::<Self>("user");
    (
        200,
        format!(
            "id = {}, name = {},age = {}\n app_state = {:#?}",
            id, name, age, app_state
        ),
    )
}

// Url Path Params
#[get("parse_param2/:id/:email/:age")]
pub async fn parse_param2(req: Request) -> impl Responder {
    let user = req.parse_param::<UserController>()?;
    user.validate()?; // user will be validate
    Ok::<_, Error>((200, Json(user)))
}

// Url Query Params
#[get("/parse_query")] // user will be validate
pub async fn parse_query(query_params: Query<Self>) -> impl Responder {
    Ok::<_, Error>((200, Json(query_params.0)))
}

// Context-Type : application/x-www-form-urlencoded
#[get("/parse_form_get")]
#[patch("/parse_form_patch")]
#[validator(exclude("user"))] // user will not be validate
pub async fn parse_form_get(user: Form<UserController>) -> impl Responder {
    (200, user)
}

// Context-Type : application/json
#[post("/parse_json")] // user will be validate
pub async fn parse_json(user: Json<UserController>) -> impl Responder {
    (200, user)
}

// Context-Type : multipart/form-data Form Fields
#[post("/multipart_form")]
pub async fn multipart_form(mut req: Request) -> impl Responder {
    let user = req.parse::<Self>().await?;
    user.validate()?; // user will be validate
    Ok::<_, Error>((200, Json(user)))
}

// Context-Type : multipart/form-data Files
#[post("/multipart_file")]
pub async fn multipart_file(mut req: Request) -> impl Responder {
    let file = req.file("file").await?;
    let file_name = file.name()?;
    let file_name = file_name.to_string();

    let img = req.files("imgs").await?;
    let imgs_name = img
        .iter()
        .map(|m| m.name().unwrap().to_string())
        .collect::<Vec<String>>()
        .join(",");

    Some((
        200,
        format!("file_name = {}, imgs_name = {}", file_name, imgs_name),
    ))
}

}

struct BasicController;

// http://127.0.0.1:7878/basic

[controller(name = "basic")]

impl BasicController { // Request Headers #[get("/header")] pub async fn header(req: Request) -> impl Responder { let host = req.header::("host")?; let useragent = req.header::("user-agent")?; Some(( 200, format!("host = {} , useragent = {}", host, user_agent), )) }

// Url Path Params
#[delete("/param/:name/:age")]
pub async fn param(req: Request) -> impl Responder {
    let name = req.param::<String>("name")?;
    let age = req.param::<u16>("age")?;
    Some((200, format!("name = {} , age = {}", name, age)))
}

// Url Query Params
#[get("/query")]
pub async fn query(req: Request) -> impl Responder {
    let name = req.query::<Vec<String>>("name")?;
    let age = req.query::<u16>("age")?;
    let key = req.get::<&str>("key")?;
    Some((
        200,
        format!("name = {:?} , age = {}\n, app_state = {}", name, age, key),
    ))
}

#[get("/set_cookies")]
pub async fn set_cookies(_req: Request) -> impl Responder {
    let mut cookie1 = Cookie::new("hypers", "hypers2023");
    cookie1.set_path("/api/v1/user");

    let mut cookie2 = Cookie::new("rust", "rust2023");
    cookie2.set_path("/api/v1/user");

    let mut cookie_jar = CookieJar::new();
    cookie_jar.add(cookie1);
    cookie_jar.add(cookie2);
    (200, cookie_jar)
}

}

// Websocket ws://127.0.0.1:7878/hello/ws http://www.jsons.cn/websocket/ pub async fn websocket(req: Request, mut ws: WebSocket) -> Result<()> { let name = req.param::("name").unwrapordefault(); while let Ok(msg) = ws.receive().await { if let Some(msg) = msg { match msg { Message::Text(text) => { let text = format!("{},{}", name, text); ws.send(Message::Text(text)).await?; } Message::Close(_) => break, _ => {} } } } Ok(()) }

// Middleware Function pub async fn stattime(req: Request, netx: Next) -> Result { // Before executing the request processing function let starttime = Instant::now();

// Calling subsequent request processing functions
let res = netx.next(req).await?;

// After the execution of the request processing function
let elapsed_time = start_time.elapsed();

println!(
    "The current request processing function takes time :{:?}",
    elapsed_time
);
Ok(res)

}

// Middleware Function pub async fn logger(req: Request, next: Next) -> Result { // Before executing the request processing function let uri = req.uri().path(); info!("uri = {:?}", uri); // Calling subsequent request processing functions let res = next.next(req).await; // After the execution of the request processing function res }

// Middleware Function pub async fn appstate(mut req: Request, next: Next) -> Result { let user = UserController { id: Some(1), email: Some("admin@gmail.com".toowned()), age: Some(21), }; req.set("user", user); req.set("key", "Hello World"); next.next(req).await }

struct ApiKeyMiddleware { api_key: String, }

[derive(Deserialize, Serialize)]

pub struct MiddlewareError { pub code: u32, pub msg: String, pub data: T, }

// Middleware Macro

[middleware]

impl ApiKeyMiddleware { async fn hook(&self, req: Request, next: Next) -> Result { if let Some(bearer) = req.headertypedget::>() { let token = bearer.0.token(); if token == self.api_key { next.next(req).await } else { info!("Invalid token"); let res = MiddlewareError { code: 400, msg: String::from("Invalid token"), data: "Invalid token", }; Err(Error::Response(401, json!(res))) } } else { info!("Not Authenticated"); Err(Error::Response(401, json!("Not Authenticated"))) } } }

// Write router like a tree fn main() -> Result<()> { tracing_subscriber::fmt().compact().init();

// The Root Router
let mut root = Router::new("/");
root.get("/*", StaticDir::new("hypers").listing(true))
    .ws(":name/ws", websocket);

// Add Middleware  ( Middleware can be added to any routing node )
root.hook(logger, vec!["/basic"], None)
    .hook(
        app_state,
        vec!["/api/v1/user/parse_param/:id/:name/:age", "/basic/query"],
        None,
    )
    .hook(stat_time, vec!["/api/v1/user"], None)
    .hook(
        ApiKeyMiddleware {
            api_key: "hypers".to_owned(),
        },
        vec!["/basic"],
        vec!["/api/v1/user"],
    );

// Add sub router to the root router
root.controller(UserController::default());
root.controller(BasicController);

println!("root router = {:#?}", root);

// Registering the root router into the server
let app = hypers::new(root);

app.run("127.0.0.1:7878")

} `````