From cffd2de0503a756b2b038a55f847811589c2421a Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Sun, 6 Jun 2021 14:09:12 +0200 Subject: [PATCH] heinz --- Cargo.lock | 2 ++ Cargo.toml | 4 ++- src/main.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7de1e15..b2c2dfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -806,6 +806,8 @@ name = "karlheinz" version = "0.1.0" dependencies = [ "actix-web", + "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 75dbea3..c2af181 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-web = "3" \ No newline at end of file +actix-web = "3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0.64" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8f03fa4..0299b58 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,48 +1,119 @@ use std::sync::Mutex; -use actix_web::{App, get, HttpResponse, HttpServer, post, Responder, web}; +use actix_web::{App, Either, get, HttpResponse, HttpServer, post, Responder, web}; +use actix_web::http::{HeaderName, HeaderValue}; +use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +macro_rules! impl_responder { + (for $name: ident) => { + impl actix_web::Responder for $name { + type Error = actix_web::Error; + type Future = std::future::Ready>; + + fn respond_to(self, _req: &actix_web::HttpRequest) -> Self::Future { + let body = serde_json::to_string(&self).unwrap(); + + std::future::ready(Ok(actix_web::HttpResponse::Ok() + .content_type("application/json") + .body(body))) + } + } + }; +} +impl_responder!(for Person); +impl_responder!(for Post); + +#[derive(Serialize, Deserialize, Clone)] struct Person { name: String, age: i32, } +#[derive(Serialize, Deserialize, Clone)] +struct Post { + #[serde(default)] + id: usize, + author: String, + title: String, + content: String, +} + struct AppState { - hugos_name: Mutex, + posts: Mutex>, + hugo: Mutex, request_amount: Mutex, } +#[get("/post/{id}")] +async fn get_post( + web::Path(id): web::Path, + data: web::Data, +) -> Either { + let posts = data.posts.lock().unwrap(); + + match posts.get(id) { + None => Either::A(HttpResponse::NotFound()), + Some(post) => Either::B(post.clone()), + } +} + +#[post("/post")] +async fn post_post(mut post: web::Json, data: web::Data) -> impl Responder { + let mut posts = data.posts.lock().unwrap(); + post.id = posts.len(); + posts.push(post.clone()); + post +} + #[get("/hugo")] async fn hugo(data: web::Data) -> impl Responder { - let hugo_name = &data.hugos_name.lock().unwrap(); + let hugo_person = data.hugo.lock().unwrap(); let mut counter = data.request_amount.lock().unwrap(); *counter += 1; - HttpResponse::Ok().body(format!("{} as been requested {} times", hugo_name, counter)) + HttpResponse::Ok() + .header( + HeaderName::from_static("request-amount"), + HeaderValue::from(*counter), + ) + .content_type("application/json") + .body(serde_json::to_string(&*hugo_person).unwrap()) } #[post("/hugo")] -async fn hugo_post(req_body: String, data: web::Data) -> impl Responder { - let mut hugo_name = data.hugos_name.lock().unwrap(); - *hugo_name = req_body; +async fn hugo_post(new_hugo: web::Json, data: web::Data) -> impl Responder { + let mut hugo_person = data.hugo.lock().unwrap(); - HttpResponse::Ok().body(&*hugo_name) + *hugo_person = new_hugo.clone(); + new_hugo } #[actix_web::main] async fn main() -> std::io::Result<()> { + let posts = vec![Post { + id: 0, + author: "Hugo Boss".to_string(), + title: "I like winning".to_string(), + content: "I really like winning. That's why I always win at everything".to_string(), + }]; + let data = web::Data::new(AppState { + posts: Mutex::new(posts), request_amount: Mutex::new(0), - hugos_name: Mutex::new("Hugo Boss".to_string()), + hugo: Mutex::new(Person { + name: "Hugo Boss".to_string(), + age: 40, + }), }); - HttpServer::new(move || + HttpServer::new(move || { App::new() .app_data(data.clone()) .service(hugo_post) .service(hugo) - ) + .service(get_post) + .service(post_post) + }) .bind("127.0.0.1:8080")? .run() .await