example

This version is built on hyper v0.14 and crate async_trait is used

1、 Usage MacroController

use athene's validate and file feature

````rust use athene::prelude::*; use serde::{Deserialize, Serialize}; use validator::Validate;

static INDEX_HTML: &str = r#" Upload Test

Upload Test

"#;

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

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

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

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

impl UserController {

// http://127.0.0.1:7878/api/v1/user/xxx
#[get("/*/**")]
pub async fn match_any_route(&self, req: Request) -> impl Responder {
    let uri_path = req.uri().path().to_string();
    let method = req.method().to_string();
    (201, format!("uri : {}, method: {}", uri_path, method))
}

// http://127.0.0.1:7878/api/v1/user/web/18
#[delete("/{username}/{age}")] // username and age will not be validated
pub async fn delete_by_param(&self, username: String, age: Option<u16>) -> impl Responder {
    (
        202,
        format!("username is : {}, and age is : {:?}", username, age),
    )
}

// http://127.0.0.1:7878/api/v1/user/get_query_1/?username=admin&age=29
#[get("/get_query_1")] // username and age will not be validated
pub async fn get_query_1(&self, username: String, age: u16) -> impl Responder {
    (203, Json(Self { username, age }))
}

// http://127.0.0.1:7878/api/v1/user/get_query_2/?username=admin@qq&age=19
#[get("/get_query_2")] // user will be validated
pub async fn get_query_2(&self, user: Query<Self>) -> impl Responder {
    (203, Json(user.0))
}

// http://127.0.0.1:7878/api/v1/user/parse_json_body
// Context-Type : application/json
#[post("/parse_json_body")]
#[get("/parse_json_body")] // user will be validated
async fn parse_json_body(&self, user: Json<Self>) -> impl Responder {
    Ok::<_, Error>((206, user))
}

// http://127.0.0.1:7878/api/v1/user/parse_form_body
// Context-Type : application/x-www-form-urlencoded
#[post("/parse_form_body")]
#[get("/parse_form_body")] // user will be validated
async fn parse_form_body(&self, user: Form<Self>) -> impl Responder {
    Ok::<_, Error>((206, user))
}

// http://127.0.0.1:7878/api/v1/user/parse_body_vec
#[post("/parse_body_vec")]
#[get("/parse_body_vec")]
async fn parse_body_vec(&self,mut req: Request) -> impl Responder {
    let vector = req.parse_body::<Vec<u8>>().await?;
    Ok::<_, Error>((StatusCode::OK, vector))
}

// http://127.0.0.1:7878/api/v1/user/parse_body_string
#[post("/parse_body_string")]
#[get("/parse_body_string")]
async fn parse_body_string(&self,mut req: Request) -> impl Responder {
    let vector = req.parse_body::<String>().await?;
    Ok::<_, Error>((StatusCode::OK, vector))
}

// http://127.0.0.1:7878/api/v1/user/file
#[post("/file")]
pub async fn file(&self, mut req: Request) -> impl Responder {
    let file = req.file("file").await?;
    let file_name = file
        .name()
        .ok_or_else(|| Error::Other("file not found".to_string()))?;
    Ok::<_, Error>((200, file_name.to_string()))
}

// http://127.0.0.1:7878/api/v1/user/files
#[post("/files")]
pub async fn files(&self, mut req: Request) -> impl Responder {
    let files = req.files("files").await?;
    let fist_file_name = files[0]
        .name()
        .ok_or_else(|| Error::Other("file not found".to_string()))?;
    let second_file_name = files[1]
        .name()
        .ok_or_else(|| Error::Other("file not found".to_string()))?;
    Ok::<_, Error>((
        200,
        format!(
            "fist_file_name: {}, second_file_name: {}",
            fist_file_name, second_file_name
        ),
    ))
}

// http://127.0.0.1:7878/api/v1/user/upload
#[post("/upload")]
pub async fn upload(&self, mut req: Request) -> impl Responder {
    let res = req.upload("file", "temp").await?;
    if res > 0 {
        Ok::<_, Error>((200, "File uploaded successfully"))
    } else {
        Ok::<_, Error>((400, "File upload failed"))
    }
}

// http://127.0.0.1:7878/api/v1/user/uploads
#[post("/uploads")]
pub async fn uploads(&self, mut req: Request) -> impl Responder {
    let msg = req.uploads("files", "temp").await?;
    Ok::<_, Error>((200, msg))
}

// http://127.0.0.1:7878/api/v1/user/download
// Content-Disposition: application/octet-stream
#[get("/download")]
pub async fn download(&self, _req: Request) -> impl Responder {
    let mut res = Response::new();
    res.write_file("temp/ws.rs", DispositionType::Attachment)?;
    Ok::<_, Error>((200, "Download successful"))
}

}

[tokio::main]

pub async fn main() -> Result<()> {

let app = athene::new().router(|r| {
    r.get("/api/v1/user/upload", |_: Request| async {
        Html(INDEX_HTML)
    })
    .controller(UserController::default())
});

app.listen("127.0.0.1:7878").await

} ````

2、Usage BasicController

````rust use athene::prelude::*; use serde::{Deserialize, Serialize};

[derive(Default, Serialize, Deserialize)]

pub struct AtheneController { pub label: String, pub keyword: String, }

impl Controller for AtheneController { const BASE_PATH: &'static str = "/api/v1/athene";

fn method(&self) -> Vec<ControllerMethod<Self>>
where
    Self: Sized,
{
    ControllerBuilder::new()
        .post("/add", Self::add)
        .delete("/{label}/{keyword}", Self::delete)
        .put("/update", Self::update)
        .get("/get", Self::get)
        .build()
}

}

impl AtheneController {

// http://127.0.0.1:7878/api/v1/athene/add
pub async fn add(&self, mut req: Request) -> impl Responder {
    let obj = req.parse::<Self>().await?;
    Ok::<_, Error>((200, Json(obj)))
}

// http://127.0.0.1:7878/api/v1/athene/
pub async fn delete(&self, mut req: Request) -> impl Responder {
    let lable = req.param::<String>("label")?;
    let keyword = req.param::<String>("keyword")?;

    Ok::<_, Error>((300, format!("lable = {},keyword = {}", lable, keyword)))
}

// http://127.0.0.1:7878/api/v1/athene/update
// Context-Type : application/json  Or application/x-www-form-urlencoded
async fn update(&self, mut req: Request) -> impl Responder {
    let obj = req.parse::<Self>().await?;
    Ok::<_, Error>((200, Json(obj)))
}

// http://127.0.0.1:7878/api/v1/athene/get
async fn get(&self, req: Request) -> impl Responder {
    #[derive(Deserialize, Serialize)]
    struct QueryParam<'a> {
        label: &'a str,
        keyword: &'a str,
    }

    let arg = req.query::<QueryParam>()?;
    let res = Response::new();
    Ok::<_, Error>(res.json(&arg))
}

}

[tokio::main]

async fn main() -> Result<(), Error> {

let app = athene::new()
    .router(|r| r.controller(AtheneController::default()));

app.listen("127.0.0.1:7878").await

} ````

3、Usage Middleware and RouterGroup

````rust use athene::prelude::*; use headers::{authorization::Bearer, Authorization}; use serde::{Deserialize, Serialize}; use tracing::info;

[derive(Serialize, Deserialize)]

pub struct User { pub username: String, pub age: u16, }

// 127.0.0.1:7878/user/admin/18 pub async fn user_params(mut req: Request) -> impl Responder { let username = req.param("username")?; let age = req.param::("age")?; Ok::<_, Error>((300, Json(User { username, age }))) }

// 127.0.0.1:7878/user/login pub async fn login(mut req: Request) -> impl Responder { if let Ok(user) = req.parse::().await { ( 201, format!("username: {} , age: {} ", user.username, user.age), ) } else { (400, String::from("Bad user format")) } }

// 127.0.0.1:7878/user/signup pub async fn signup(mut req: Request) -> impl Responder { let user = req.parse::().await?; Ok::<_, Error>((211, Json(user))) }

// 127.0.0.1:7878/user/bodytovecu8 pub async fn bodytovecu8(mut req: Request) -> impl Responder { let body = req.parse_body::>().await?; Ok::<_, Error>((500, body)) }

// 127.0.0.1:7878/user/bodytostring pub async fn bodytostring(mut req: Request) -> impl Responder { let body = req.parse_body::().await?; Ok::<_, Error>((404, body)) }

pub fn userrouter(r: Router) -> Router { r.group("///user/**/") .get("/{username}/{age}", userparams) .post("/login", login) .post("/signup", signup) .put("/bodytovecu8", bodytovecu8) .post("/bodytostring", bodytostring) }

// ============================ Middleware Fuction ============================ pub async fn logmiddleware(ctx: Context, next: &'static dyn Next) -> Result { info!( "new request on path: {}", ctx.state.requestunchecked().uri().path() );

let ctx = next.next(ctx).await?;

info!(
    "new response with status: {}",
    ctx.state.response_unchecked().status()
);
Ok(ctx)

}

// ================================ Middleware ====================== struct ApiKeyMiddleware { api_key: String, }

[middleware]

impl ApiKeyMiddleware { async fn next(&self, ctx: Context, chain: &dyn Next) -> Result { if let Some(bearer) = ctx .state .requestunchecked() .header::>() { let token = bearer.0.token(); if token == self.apikey { info!( "Handler {} will be used", ctx.metadata.name.unwrap_or("unknown") ); chain.next(ctx).await } else { info!("Invalid token"); Ok(ctx) } } else { info!("Not Authenticated, "); Ok(ctx) } } }

[tokio::main]

pub async fn main() -> Result<()> { tracing_subscriber::fmt().compact().init();

let app = athene::new()
    .router(user_router)
    .middleware(|m| {
        m.apply(log_middleware, vec!["/"], None).apply(
            ApiKeyMiddleware {
                api_key: "athene".to_string(),
            },
            vec!["/user/login", "/user/sign_up"],
            vec!["/user/body_to_vec_u8","/user/body_to_string"],
        )
    });

app.listen("127.0.0.1:7878").await

} ````