use astor::{Method, Middleware, Next, Request, Response, Router, Server, Status};
#[tokio::main]
async fn main() {
let users = Router::new()
.middleware(require_auth)
.on(Method::Get, "/users", list_users, ())
.on(Method::Get, "/users/{id}", get_user, ())
.on(Method::Post, "/users", create_user, ())
.on(Method::Put, "/users/{id}", update_user, ownership_check)
.on(Method::Delete, "/users/{id}", delete_user, ownership_check);
let products = Router::new()
.middleware(require_auth)
.on(Method::Get, "/products", list_products, ())
.on(Method::Post, "/products", create_product, log_body);
let public = Router::new()
.on(Method::Get, "/health", health, ());
let app = Router::new()
.merge(public)
.merge(users)
.merge(products);
Server::bind("0.0.0.0:3000")
.serve(app)
.await
.expect("server error");
}
async fn require_auth(req: Request, next: Next) -> Response {
match req.header("authorization") {
Some(_) => next.call(req).await,
None => Response::status(Status::Unauthorized),
}
}
async fn ownership_check(req: Request, next: Next) -> Response {
next.call(req).await
}
async fn log_body(req: Request, next: Next) -> Response {
let len = req.body().len();
let res = next.call(req).await;
let _ = len;
res
}
#[allow(dead_code)]
fn make_prefix_mw(prefix: &'static str) -> impl Middleware {
move |req: Request, next: Next| async move {
let _ = prefix;
next.call(req).await
}
}
async fn health(_req: Request) -> Response {
Response::text("ok")
}
async fn list_users(req: Request) -> Response {
let page = req.query("page").unwrap_or("1");
let limit = req.query("limit").unwrap_or("20");
Response::json(format!(r#"{{"page":{page},"limit":{limit},"users":[]}}"#).into_bytes())
}
async fn get_user(req: Request) -> Response {
let id = req.param("id").unwrap_or("unknown");
Response::json(format!(r#"{{"id":"{id}","name":"alice"}}"#).into_bytes())
}
async fn create_user(req: Request) -> Response {
if req.body().is_empty() {
return Response::status(Status::BadRequest);
}
Response::builder()
.status(Status::Created)
.header("location", "/users/99")
.json(r#"{"id":"99","name":"new_user"}"#.to_owned().into_bytes())
}
async fn update_user(req: Request) -> Response {
let id = req.param("id").unwrap_or("unknown");
Response::json(format!(r#"{{"id":"{id}","name":"updated"}}"#).into_bytes())
}
async fn delete_user(_req: Request) -> Status {
Status::NoContent
}
async fn list_products(_req: Request) -> Response {
Response::json(br#"{"products":[]}"#.to_vec())
}
async fn create_product(req: Request) -> Response {
if req.body().is_empty() {
return Response::status(Status::BadRequest);
}
Response::builder()
.status(Status::Created)
.header("location", "/products/1")
.json(r#"{"id":"1"}"#.to_owned().into_bytes())
}