use async_trait::async_trait; use http::request::Parts; use hyper::{Method, StatusCode}; use log::error; use crate::{ db::Endpoint, matchers::api::ApiMatcher, server::{custom_resp, json_to_vec}, services::matcher::Route, }; pub struct AddHost {} #[async_trait] impl Route for AddHost { fn matcher(&self, _: &ApiMatcher, req: &hyper::Request) -> bool { req.uri().path().starts_with("/endpoint/") && req.method() == Method::POST } async fn call( &self, m: &ApiMatcher, parts: Parts, ) -> Result { let database = m.database.clone(); let address = m._address.unwrap(); let body = m.body.clone().unwrap(); let endpoint_id: u32 = parts.uri.path().replace("/endpoint/", "").parse().unwrap(); if !body["hosts"].is_array() { error!("Hosts parameter is not an array.",); return Ok(custom_resp( StatusCode::BAD_REQUEST, "Hosts parameter is not an array.".to_string(), ) .await); } let endpoint = match Endpoint::get_by_id(*database.lock().await, endpoint_id) .await .unwrap() { Some(x) => x, None => { error!("No endpoint found by id {endpoint_id} from {address}",); return Ok(custom_resp( StatusCode::NOT_FOUND, "No endpoint by that ID.".to_string(), ) .await); } }; let hosts = json_to_vec(body["hosts"].clone()).await.unwrap(); endpoint.host(*database.lock().await, hosts).await.unwrap(); Ok(custom_resp(StatusCode::OK, "Success".to_string()).await) } } pub struct RegisterEndpoint {} #[async_trait] impl Route for RegisterEndpoint { fn matcher(&self, _: &ApiMatcher, req: &hyper::Request) -> bool { req.uri().path() == "/register" && req.method() == Method::POST } async fn call( &self, m: &ApiMatcher, _: Parts, ) -> Result { let address = m._address.unwrap(); let database = m.database.clone(); let body = m.body.clone().unwrap(); let mut endpoint = Endpoint::new( None, address, body["port"].as_u16().unwrap_or(8080), body["callback"].as_str().unwrap_or("/").to_string(), ) .await; if !body["hosts"].is_array() { error!("Hosts parameter is not an array.",); return Ok(custom_resp( StatusCode::BAD_REQUEST, "Hosts parameter is not an array.".to_string(), ) .await); }; let hosts = json_to_vec(body["hosts"].clone()).await.unwrap(); endpoint .register(*database.lock().await, hosts) .await .unwrap(); let endpoint_id = endpoint.id.unwrap().to_string(); let response = custom_resp(StatusCode::OK, endpoint_id).await; Ok(response) } } pub struct RemoveHost {} #[async_trait] impl Route for RemoveHost { fn matcher(&self, _: &ApiMatcher, req: &hyper::Request) -> bool { req.uri().path().starts_with("/endpoint/") && req.method() == Method::DELETE } async fn call( &self, m: &ApiMatcher, parts: Parts, ) -> Result { let database = m.database.clone(); let address = m._address.unwrap(); let endpoint_id: u32 = parts.uri.path().replace("/endpoint/", "").parse().unwrap(); let endpoint = match Endpoint::get_by_id(*database.lock().await, endpoint_id) .await .unwrap() { Some(x) => x, None => { error!("No endpoint found by id {endpoint_id} from {address}",); return Ok(custom_resp( StatusCode::NOT_FOUND, "No endpoint by that ID.".to_string(), ) .await); } }; endpoint.delete(*database.lock().await).await.unwrap(); Ok(custom_resp(StatusCode::OK, "Success".to_string()).await) } }