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 hypers::prelude::*; use std::time::Instant; use utoipa::{IntoParams, OpenApi, ToSchema};

[derive(Serialize, Deserialize)]

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

[derive(Serialize, Deserialize, ToSchema)]

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

[derive(Serialize, Deserialize, IntoParams, ToSchema)]

pub struct PathParams { pub id: Option, pub name: Option, pub age: Option, }

[derive(Serialize, Deserialize, IntoParams, ToSchema)]

[intoparams(parameterin = Query)]

pub struct QueryParams { pub id: Option, pub name: Option, pub age: Option, }

[derive(Serialize, Deserialize, ToSchema)]

pub struct FormParams { pub id: u32, pub name: String, pub age: u16, }

[derive(Debug, Serialize, Deserialize, ToSchema)]

pub struct JsonParams { pub id: Option, pub name: Option, pub age: Option, }

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

// Request Headers

[utoipa::path(

get,
path = "/user/parse_header",
tag = "parse request headers",
responses(
    (status = 200, description = "Parse header from request successfully", body = HeaderParams),
    (status = 404, description = "Parse header from request failed")
)

)] pub async fn parseheader(req: Request) -> impl Responder { let headerparams = req.parseheader::()?; /* .... */ Ok::<_, Error>((200, Json(headerparams))) }

// Url Path Params

[utoipa::path(

delete,
path = "/user/parse_param/{id}/{name}/{age}",
tag = "parse request url path params",
params(PathParams) ,
responses(
    (status = 200, description = "Parse Url Path Params successfully",body = PathParams),
    (status = 404, description = "Parse Url Path Params failed")
),
security(
    ("api_key" = [])
)

)] pub async fn parseparam(req: Request) -> impl Responder { let params = req.parseparam::()?; let appstate = req.get::("user"); println!("appstate = {:?}", app_state); /* ..... */ Ok::<_, Error>((200, Json(params))) }

// Url Query Params

[utoipa::path(

get,
path = "/user/parse_query",
tag = "parse request url query params",
params(QueryParams),
responses(
    (status = 200, description = "Parse query successfully", body = QueryParams)
)

)] pub async fn parsequery(req: Request) -> impl Responder { let queryparams = req.parsequery::()?; /* ..... */ Ok::<_, Error>((200, Json(queryparams))) }

// Context-Type : application/x-www-form-urlencoded

[utoipa::path(

patch,
path = "/user/parse_form_patch",
tag = "parse request body",
request_body(
    content = FormParams,
    content_type = "application/x-www-form-urlencoded",
),
responses(
    (status = 200, description = "FormParams created successfully", body = FormParams),
    (status = 409, description = "FormParams already exists")
)

)] pub async fn parseformpatch(mut req: Request) -> impl Responder { let user = req.parse::().await?; /* ..... */ Ok::<_, Error>((200, Json(user))) }

// Context-Type : application/x-www-form-urlencoded pub async fn parseformget(mut req: Request) -> impl Responder { let user = req.parse::().await?; /* ..... */ Ok::<_, Error>((200, Json(user))) }

// Context-Type : application/json

[utoipa::path(

post,
path = "/user/parse_json",
tag = "parse request body",
request_body(
    content = JsonParams,
    content_type = "application/json",
),
responses(
    (status = 201, description = "JsonParams item created successfully", body = JsonParams),
    (status = 409, description = "JsonParams already exists")
)

)] pub async fn parse_json(mut req: Request) -> impl Responder { let user = req.parse::().await?; /* ...... */ Ok::<_, Error>((200, Json(user))) }

// Context-Type : multipart/form-data Form Fields pub async fn multipartform(mut req: Request) -> impl Responder { let formdata = req.parse::().await?; /* .... */ Ok::<_, Error>((200, Json(form_data))) }

// Context-Type : multipart/form-data Files pub async fn multipartfile(mut req: Request) -> impl Responder { let file = req.file("file").await?; let filename = file.name()?; let filename = filename.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),
))

}

// Request Headers

[utoipa::path(

get,
path = "/base/header",
tag = "request headers",
responses(
    (status = 200, description = "header successfully", body = String),
    (status = 404, description = "header failed")
),

)] 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

[utoipa::path(

delete,
path = "/base/param/{name}/{age}",
tag = "url path params",
params(
    ("name" = String, Path, description = "Url Path Params name"),
    ("age" = u16, Path, description = "Url Path Params age"),
),
responses(
    (status = 200, description = "successfully, response = String"),
    (status = 404, description = "failed")
)

)] pub async fn param(req: Request) -> impl Responder { let name = req.param::("name")?; let age = req.param::("age")?; /* ..... */ Some((200, format!("name = {} , age = {}", name, age))) }

// Url Query Params

[utoipa::path(

get,
path = "/base/query",
tag = "url query params",
params(
    ("name" = Vec<String>, Query, description = "Url Query Params name"),
    ("age" = u16, Query, description = "Url Query Params age"),
),
responses(
    (status = 200, description = "successfully, response = String"),
    (status = 404, description = "failed")
)

)] pub async fn query(req: Request) -> impl Responder { let name = req.query::>("name")?; let age = req.query::("age")?; let key = req.get::<&str>("key")?; println!("app_state = {}", key); /* ..... */ Some((200, format!("name = {:?} , age = {}", name, age))) }

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

// println!(
//     "The response after the execution of the current request processing function : {:?}",
//     res.body()
// );
Ok(res)

}

pub async fn logger(req: Request, next: Next) -> Result { // Before executing the request processing function let uri = req.uri().path(); println!("uri = {:?}", uri);

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

// After the execution of the request processing function
res

}

pub async fn appstate(mut req: Request, next: Next) -> Result { let user = JsonParams { id: Some(1), name: Some("admin".toowned()), age: Some(21), }; req.set("user", user); req.set("key", "Hello World"); next.next(req).await }

[derive(OpenApi)]

[openapi(

info(title = "Base Api", description = "Base Api description"),
paths(header, param, query),
tags(
    (name = "base", description = " base router")
)

)] struct ApiDoc1;

[derive(OpenApi)]

[openapi(

info(title = "User Api", description = "User Api description"),
paths(parse_header, parse_param, parse_query, parse_form_patch, parse_json),
components(schemas(HeaderParams, PathParams, QueryParams, FormParams, JsonParams)),
tags(
    (name = "user", description = " user router ")
)

)] struct ApiDoc2;

// Write router like a tree fn main() -> Result<()> { // The Root Router let mut root = Router::new("/"); root.get("/*", StaticDir::new("src").listing(true));

// Add Middleware  ( Middleware can be added to any routing node )
root.hook(logger, vec!["/param/:name/:age"], None);

// The Sub Router
let mut base = Router::new("base");
// Add Middleware  ( Middleware can be added to any routing node )
base.hook(app_state, vec!["/"], None);
base.ws(":name/ws", websocket)
    .get("/header", header)
    .delete("param/:name/:age", param)
    .get("query", query)
    .get("set_cookies", |_| async {
        let mut cookie1 = Cookie::new("hypers", "hypers2023");
        cookie1.set_path("/user");

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

        let mut cookie_jar = CookieJar::new();
        cookie_jar.add(cookie1);
        cookie_jar.add(cookie2);
        (200, cookie_jar)
    })
    .get("/html", |_| async {
        Text::Html("<html><body>hello</body></html>")
    })
    .openapi(ApiDoc1::openapi());

// The Sub Router
let mut user = Router::new("user");
// Add Middleware  ( Middleware can be added to any routing node )
user.hook(stat_time, vec!["/user"], None);
user.get("parse_cookies", parse_cookies)
    .get("/parse_header", parse_header)
    .delete("parse_param/:id/:name/:age", parse_param)
    .get("parse_query", parse_query)
    .patch("parse_form_patch", parse_form_patch)
    .get("parse_form_get", parse_form_get)
    .post("parse_json", parse_json)
    .post("/multipart_form", multipart_form)
    .post("multipart_file", multipart_file)
    .openapi(ApiDoc2::openapi());

let mut api1 = Router::new("api1");
api1.get("hello1", api1::hello1)
    .openapi(api1::ApiDoc1::openapi());

// Add api1 router to the base router
base.push(api1);

let mut api2 = Router::new("api2");
api2.get("hello2", api2::hello2)
    .openapi(api2::ApiDoc2::openapi());

// Add api2 router to the user router
user.push(api2);

// Add sub router to the root router
root.push(base);
root.push(user);

// Accessing in a browser  http://127.0.0.1:7878/swagger-ui/
root.swagger("swagger-ui");

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

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

// Start Server
// Not Use SSL/TLS
#[cfg(not(any(feature = "rustls", feature = "native_tls")))]
{
    app.run("127.0.0.1:7878")
}

// Use SSL/TLS
#[cfg(feature = "rustls")]
{
    let tls = RustlsConfig::new()
        .cert(include_bytes!("./certs/cert.pem").to_vec())
        .key(include_bytes!("./certs/key.pem").to_vec());
    app.run("127.0.0.1:7878", tls)
}

// Use SSL/TLS
#[cfg(feature = "native_tls")]
{
    let tls = NativeTls::from_pkcs12(include_bytes!("./certs/identity.p12"), "mypass")?;
    app.run("127.0.0.1:7878", tls)
}

}

mod api1 { use super::*; #[utoipa::path( get, path = "/base/api1/hello1", responses( (status = 200, body = String) ) )] pub async fn hello1(_req: Request) -> impl Responder { Response::default() .header("content-type", "text/plain") .write("/base/api1/hello1") } #[derive(OpenApi)] #[openapi(paths(hello1))] pub struct ApiDoc1; }

mod api2 { use super::*; #[utoipa::path( get, path = "/user/api2/hello2", responses( (status = 200, body = String) ) )] pub async fn hello2(_req: Request) -> impl Responder { Response::default() .header("content-type", "text/plain") .write("/user/api2/hello2") } #[derive(OpenApi)] #[openapi(paths(hello2))] pub struct ApiDoc2; } `````