cargo new book_api
cd book_api
toml
[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rs
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use std::sync::Mutex;
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Book {
id: usize,
title: String,
author: String,
}
struct AppState {
books: Mutex<HashMap<usize, Book>>,
}
#[actix_web::post("/books")]
async fn create_book(state: web::Data<AppState>, book: web::Json<Book>) -> impl Responder {
let mut books = state.books.lock().unwrap();
books.insert(book.id, book.into_inner());
HttpResponse::Created().finish()
}
#[actix_web::get("/books/{id}")]
async fn get_book(state: web::Data<AppState>, web::Path(id): web::Path<usize>) -> impl Responder {
let books = state.books.lock().unwrap();
if let Some(book) = books.get(&id) {
HttpResponse::Ok().json(book)
} else {
HttpResponse::NotFound().finish()
}
}
#[actix_web::put("/books/{id}")]
async fn update_book(state: web::Data<AppState>, id: web::Path<usize>, book: web::Json<Book>) -> impl Responder {
let mut books = state.books.lock().unwrap();
if books.contains_key(&id) {
books.insert(id.into_inner(), book.into_inner());
HttpResponse::Ok().finish()
} else {
HttpResponse::NotFound().finish()
}
}
#[actix_web::delete("/books/{id}")]
async fn delete_book(state: web::Data<AppState>, web::Path(id): web::Path<usize>) -> impl Responder {
let mut books = state.books.lock().unwrap();
if books.remove(&id).is_some() {
HttpResponse::NoContent().finish()
} else {
HttpResponse::NotFound().finish()
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let app_state = web::Data::new(AppState {
books: Mutex::new(HashMap::new()),
});
HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.service(create_book)
.service(get_book)
.service(update_book)
.service(delete_book)
})
.bind("127.0.0.1:9999")?
.run()
.await
}