````rust use askama::Template; use athene::prelude::*; use athene::{html, json, status}; use serde::{Deserialize, Serialize}; use tracing::info;
use validator::{Validate, ValidationError};
pub struct User {
#[validate(email)]
pub username: String,
#[validate(range(min = 18, max = 20))]
pub age: u16,
#[validate(custom = "validateuserrole")]
pub role: Option
fn validateuserrole(role: &str) -> Result<(),ValidationError> { if role.ne("student"){ return Err(ValidationError::new("invalid role")); } Ok(()) }
// ================================ Controller =================================== pub struct UserController {}
// http://127.0.0.1:7878/api/v1/user
impl UserController {
#[delete("/
#[get("/get_query_1")]
pub async fn get_query_1(&self, username: String, age: u16) -> (u16, Json<User>) {
(200, Json(User { username, age, role: None}))
}
#[get("/get_query_2")]
pub async fn get_query_2(&self, request: Request) -> Result<(u16, Json<User>)> {
let user = request.query::<User>()?;
Ok((200, Json(user)))
}
// Context-Type : application/json
#[post("/post_json")]
#[validator] // The user parameter will be validated
pub async fn post_json(&self, user: Json<User>) -> Result<(u16,Json<User>)> {
Ok((200, user))
}
// Context-Type : application/x-www-form-urlencoded
#[get("/user_form")]
#[post("/user_form")]
#[validator(exclude("user"))] // The user parameter will not be validated
async fn user_form(&self, user: Form<User>) -> impl Responder {
(200, user)
}
// Context-Type : application/json Or application/x-www-form-urlencoded
// Context-Type : application/msgpack Or application/cbor
#[post("/parse_body")]
#[validator] // User will be validated
async fn parse_body(&self, mut req: Request) -> Result<(u16, String)> {
let user = req.parse::<User>().await?;
Ok((
200,
format!("username = {} and age = {}", user.username, user.age),
))
}
// Context-Type : application/multipart-formdata
#[post("/files")]
async fn files(&self, mut req: Request) -> Result<(u16, String)> {
let files = req.files("files").await?;
let fist_file_name = files[0].name().unwrap();
let second_file_name = files[1].name().unwrap();
let third_file_name = files[2].name().unwrap();
Ok((
200,
format!(
"fist {}, second {}, third {}",
fist_file_name, second_file_name, third_file_name
),
))
}
// Context-Type : application/multipart-formdata
#[post("/upload")]
async fn upload(&self, mut req: Request) -> impl Responder {
if let Ok(res) = req.upload("file", "temp").await {
(200, res)
} else {
(200, String::from("Bad Request"))
}
}
}
// ================================ Middleware ====================== struct ApiKeyMiddleware(String);
impl ApiKeyMiddleware { pub fn new(apikey: &str) -> Self { ApiKeyMiddleware(apikey.to_string()) }
async fn next(&self, ctx: Context, chain: &dyn Next) -> Result<Context, Error> {
if let Some(Ok("Bearer secure-key")) = ctx
.state
.request_unchecked()
.headers()
.get("authorization")
.map(|auth_value| auth_value.to_str())
{
info!("Authenticated");
} else {
info!("Not Authenticated");
}
info!(
"Handler {} will be used",
ctx.metadata.name.unwrap_or("unknown")
);
chain.next(ctx).await
}
}
async fn logmiddleware(ctx: Context, next: &'static dyn Next) -> Result
let ctx = next.next(ctx).await?;
info!(
"new response with status: {}",
ctx.state.response_unchecked().status()
);
Ok(ctx)
}
// ================================ Handler ===================================
pub async fn hello(_req: Request) -> (u16, &'static str) { (200, "Hello, World!") }
pub async fn user_params(mut req: Request) -> impl Responder {
let username = req.param("username");
let age = req.param("age");
let age = age.parse::
pub async fn login(mut req: Request) -> impl Responder {
if let Ok(user) = req.body_mut().parse::
pub async fn signup(mut req: Request) -> Result<(u16, Json