aurora_db/network/
http_server.rs1#[cfg(feature = "http")]
2mod http_impl {
3 use crate::db::Aurora;
4 use crate::network::http_models::{QueryPayload, document_to_json, json_to_insert_data};
5 use crate::types::FieldType;
6 use actix_web::{App, HttpRequest, HttpResponse, HttpServer, Responder, web};
7 use serde::Deserialize;
8 use serde_json::Value as JsonValue;
9 use std::sync::Arc;
10
11 #[derive(Deserialize)]
12 struct CollectionPayload {
13 name: String,
14 fields: Vec<(String, FieldType, bool)>,
15 }
16
17 async fn get_all_docs(db: web::Data<Arc<Aurora>>, path: web::Path<String>) -> impl Responder {
18 let collection_name = path.into_inner();
19 match db.get_all_collection(&collection_name).await {
20 Ok(docs) => {
21 let json_docs: Vec<JsonValue> = docs.iter().map(document_to_json).collect();
22 HttpResponse::Ok().json(json_docs)
23 }
24 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
25 }
26 }
27
28 async fn create_collection(
29 db: web::Data<Arc<Aurora>>,
30 payload: web::Json<CollectionPayload>,
31 ) -> impl Responder {
32 let fields: Vec<(String, FieldType, bool)> = payload
33 .fields
34 .iter()
35 .map(|(name, ft, unique)| (name.clone(), ft.clone(), *unique))
36 .collect();
37
38 match db.new_collection(&payload.name, fields) {
39 Ok(_) => HttpResponse::Created().finish(),
40 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
41 }
42 }
43
44 async fn insert_document(
45 db: web::Data<Arc<Aurora>>,
46 path: web::Path<String>,
47 data: web::Json<JsonValue>,
48 ) -> impl Responder {
49 let collection_name = path.into_inner();
50 let doc_to_insert = data.into_inner();
51
52 match json_to_insert_data(doc_to_insert) {
53 Ok(insert_data) => match db.insert_map(&collection_name, insert_data) {
54 Ok(id) => match db.get_document(&collection_name, &id) {
55 Ok(Some(doc)) => HttpResponse::Created().json(document_to_json(&doc)),
56 Ok(None) => {
57 HttpResponse::NotFound().body("Failed to retrieve document after creation")
58 }
59 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
60 },
61 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
62 },
63 Err(e) => HttpResponse::BadRequest().body(e.to_string()),
64 }
65 }
66
67 async fn delete_document(
68 db: web::Data<Arc<Aurora>>,
69 path: web::Path<(String, String)>,
70 ) -> impl Responder {
71 let (collection_name, doc_id) = path.into_inner();
72 let key = format!("{}:{}", collection_name, doc_id);
73 match db.delete(&key).await {
74 Ok(_) => HttpResponse::NoContent().finish(),
75 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
76 }
77 }
78
79 async fn query_collection(
80 db: web::Data<Arc<Aurora>>,
81 path: web::Path<String>,
82 payload: web::Json<QueryPayload>,
83 ) -> impl Responder {
84 let collection_name = path.into_inner();
85 match db.execute_dynamic_query(&collection_name, &payload).await {
86 Ok(docs) => {
87 let json_docs: Vec<JsonValue> = docs.iter().map(document_to_json).collect();
88 HttpResponse::Ok().json(json_docs)
89 }
90 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
91 }
92 }
93
94 async fn not_found(req: HttpRequest) -> impl Responder {
95 let (path, method) = (req.path().to_string(), req.method().to_string());
96 let msg = format!("404 Not Found: No route for {} {}", method, path);
97 println!("{}", msg);
98 HttpResponse::NotFound().body(msg)
99 }
100
101 pub async fn run_http_server(db: Arc<Aurora>, addr: &str) -> std::io::Result<()> {
102 let db_data = web::Data::new(db);
103 println!("🚀 Starting HTTP server at http://{}", addr);
104
105 HttpServer::new(move || {
106 App::new()
107 .app_data(db_data.clone())
108 .route("/collections", web::post().to(create_collection))
109 .service(
110 web::scope("/collections")
111 .route("/{name}", web::get().to(get_all_docs))
112 .route("/{name}/docs", web::post().to(insert_document))
113 .route("/{name}/docs/{id}", web::delete().to(delete_document))
114 .route("/{name}/query", web::post().to(query_collection)),
115 )
116 .default_service(web::to(not_found))
117 })
118 .bind(addr)?
119 .run()
120 .await
121 }
122}
123
124#[cfg(feature = "http")]
125pub use http_impl::run_http_server;