Useage
use askama::Template;
use athene::{Error, IResponse, Middleware, Next, Request, Response, Result};
use route::fifth::fifth_router;
use serde::Serialize;
use std::pin::Pin;
use tera::{Context, Tera};
pub async fn askama_template(_: Request) -> Result {
#[derive(Serialize, Hash, Eq, PartialEq, Clone, Template)]
#[template(path = "favorite.html")]
pub struct Favorite<'a> {
title: &'a str,
time: i32,
}
let love = Favorite {
title: "rust_lang",
time: 1314,
};
let mut res = Response::default();
let love = love.render()?;
res.html(love)?;
Ok(res)
}
pub async fn tera_template(_: Request) -> Result {
#[derive(Serialize)]
struct Awesome<'a> {
url: &'a str,
name: &'a str,
}
let tera = Tera::new("templates/*")?;
let mut ctx = Context::new();
ctx.insert("title", "Welcome to rust-lang world!");
ctx.insert(
"product",
&vec![
Awesome {
url: "https://github.com/rust-lang",
name: "rust-lang",
},
Awesome {
url: "https://github.com/lapce/lapce",
name: "lapce",
},
],
);
let mut res = Response::default();
let love = tera.render("index.html", &ctx)?;
res.html(love)?;
Ok(res)
}
#[derive(Debug)]
pub struct Logger;
#[async_trait::async_trait]
impl Middleware for Logger {
async fn handle(self: Pin<&Self>, request: Request, next: Next<'_>) -> Result {
if !request.uri().path().starts_with("/auth") {
let res = next.next(request).await?;
return Ok(res);
} else {
use athene::IntoResponse;
"Logger middleware is used".response()
}
}
}
pub(crate) mod route {
pub(crate) mod first {
pub(crate) fn first_router() -> athene::Router {
use athene::{IRequest, IResponse, Request, Response, StatusCode};
let mut router = athene::new();
router.get("/moved", |_| async {
Response::redirect(StatusCode::MOVED_PERMANENTLY, "/api/rust")
});
router.get("/permanent", |_| async {
Response::redirect(StatusCode::PERMANENT_REDIRECT, "/api/code")
});
router.get("/temporary", |_| async {
Response::redirect(StatusCode::TEMPORARY_REDIRECT, "/api/world")
});
router.get("/welcome", |req: Request| async move {
#[derive(serde::Serialize, serde::Deserialize)]
struct User {
name: String,
age: i32,
}
let user = req.query::<User>().unwrap();
let mut res = Response::default();
res.json(&user)?;
anyhow::Ok(res)
});
router
}
}
pub(crate) mod second {
use athene::DispositionType;
pub(crate) fn second_router() -> athene::Router {
use crate::{askama_template, route::first::first_router, tera_template};
use athene::{IRequest, IResponse, Request, Response};
let mut router = first_router();
router.post("/upload", |req: Request| async {
let mut req = req;
let info = req.upload("file", "temp").await?;
anyhow::Ok(info)
});
router.post("/uploads", |req: Request| async move {
let mut req = req;
let info = req.uploads("files", "temp").await?;
anyhow::Ok(info)
});
router.get("/download", |_| async move {
let mut res = Response::default();
res.write_file("templates/author.txt", DispositionType::Attachment)?;
anyhow::Ok(res)
});
router.get("/location", |_| async { Response::location("/") });
router.get("/askama_template", askama_template);
router.get("/tera_template", tera_template);
router
}
}
pub(crate) mod third {
pub(crate) fn third_router() -> athene::Router {
use super::second::second_router;
use athene::{IRequest, Request, StatusCode};
let mut router = second_router();
router.group("/closure", |base| {
base.get("/str", |_req| async { "closure str" });
base.post("/string", |_| async { String::from("closure string") });
base.put("/vec/", |_| async { [1, 3, 5, 7, 9].to_vec() });
base.delete("/status", |_| async { StatusCode::NO_CONTENT });
base.options("/empty", |_| async {});
base.head("/empty/bracket", |_| async { () });
base.put("/remote_addr", |req: Request| async move {
let addr = req.remote_addr().unwrap();
let addr = addr.to_string();
addr
});
base.patch("/remote_ip", |req: Request| async move {
let ip = req.ip().unwrap();
let ip = ip.to_string();
ip
});
base.post("/status/value", |_| async {
(StatusCode::NOT_FOUND, "welcome to my world")
});
});
router
}
}
pub(crate) mod fifth {
pub(crate) fn fifth_router() -> athene::Router {
use super::third::third_router;
use athene::{IRequest, IResponse, Request, Response};
use serde::{Deserialize, Serialize};
let mut router = third_router();
router.group("/api", |base| {
base.get("/hello/{name}", |req: Request| async move {
let name: String = req.param("name").unwrap();
let mut res = Response::default();
res.text(name)?;
anyhow::Ok(res)
});
base.get("/world", |_| async { "world" });
base.get("/code", |_| async { "code handler" });
base.get("/rust", |_| async { "welcome to rust_lang world" });
base.group("/user", |user| {
user.post("/login", |req: Request| async move {
#[derive(Serialize, Deserialize)]
struct User {
name: String,
age: i32,
}
let mut req = req;
let user = req.parse::<User>().await?;
let mut res = Response::default();
res.json(&user)?;
anyhow::Ok(res)
});
user.post("/form_encode", |req: Request| async move {
#[derive(Deserialize, Serialize)]
struct Rust {
version: String,
edition: String,
}
let mut req = req;
let rust = req.parse::<Rust>().await?;
let mut res = Response::default();
res.json(&rust)?;
anyhow::Ok(res)
});
});
});
use crate::Logger;
router.middleware(Logger).group("/auth", |base| {
base.get("/success", |req: athene::Request| async move {
format!("{} {}", req.uri().path(), req.method())
});
base.post("/failed", |_| async { "failed" });
});
router
}
}
}
#[tokio::main]
pub async fn main() -> std::result::Result<(), Error> {
let router = fifth_router();
router.listen("127.0.0.1:8081").await
}
templates/index.html
<title>{{title}}</title>
<ul>
{% for one in product -%}
<li><a href="{{ one.url | safe }}">{{ one.name }}</a></li>
{%- endfor %}
</ul>
templates/favorite.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rust is one of my favorite programming languages</title>
</head>
<body>
<h4>{{title}}</h4>
<p>{{time}}</p>
</body>
</html>