use crate::error::*; use crate::usimp; use crate::usimp::*; use crate::websocket; use hyper::{body, header, Body, Method, Request, Response, StatusCode}; use serde_json::{Map, Value}; use std::str::FromStr; use uuid::Uuid; async fn endpoint_handler( req: &mut Request, endpoint: String, ) -> Result, Error> { if req.method() == Method::OPTIONS { return Ok(None); } else if req.method() != Method::POST { return Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )); } let to_domain; if let Some(val) = req .headers() .get(header::HeaderName::from_str("To-Domain").unwrap()) { to_domain = val.to_str().unwrap().to_string() } else { return Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )); } if let Some(val) = req.headers().get(header::CONTENT_TYPE) { let parts: Vec = val .to_str()? .split(';') .map(|v| v.trim().to_ascii_lowercase()) .collect(); let p: Vec<&str> = parts.iter().map(|v| v.as_str()).collect(); match p[0..1] { ["application/json"] => {} _ => { return Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )) } } } else { return Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )); } let data = serde_json::from_slice(&body::to_bytes(req.body_mut()).await?)?; let input = InputEnvelope { endpoint, to_domain: Uuid::from_str(to_domain.as_str())?, from_domain: match req .headers() .get(header::HeaderName::from_str("From-Domain").unwrap()) { Some(val) => Some(Uuid::from_str(val.to_str()?)?), None => None, }, request_nr: None, token: match req.headers().get(header::AUTHORIZATION) { Some(val) => { let val = val.to_str()?; if val.starts_with("usimp ") { Some(val[6..].to_string()) } else { return Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )); } } None => None, }, data, }; Ok(Some(usimp::endpoint(&input, None).await?)) } pub async fn handler(mut req: Request) -> Result, hyper::Error> { let mut res = Response::builder(); let parts: Vec<&str> = req.uri().path().split('/').skip(1).collect(); println!("{} {}", req.method(), req.uri()); let val: Result, Error> = match &parts[..] { [""] => Ok(res .status(StatusCode::OK) .body(Body::from("Hello World")) .unwrap()), ["_usimp"] | ["_usimp", ..] => { res = res .header(header::SERVER, "Locutus") .header(header::CACHE_CONTROL, "no-store") .header(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*") .header(header::ACCESS_CONTROL_MAX_AGE, 3600); let output = match &parts[1..] { ["websocket"] => { res = res.header(header::ACCESS_CONTROL_ALLOW_METHODS, "GET"); let (r, val) = websocket::handler(req, res).await; res = r; match val { Some(val) => Ok(Some(val)), None => return Ok(res.body(Body::empty()).unwrap()), } } [endpoint] => { res = res .header(header::ACCESS_CONTROL_ALLOW_METHODS, "POST, OPTIONS") .header( header::ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type, From-Domain, To-Domain, Authorization", ); let endpoint = endpoint.to_string(); endpoint_handler(&mut req, endpoint).await } _ => Err(Error::new( ErrorKind::UsimpError, ErrorClass::ClientProtocolError, None, )), }; let output = match output { Ok(Some(val)) => Some(val), Ok(None) => None, Err(error) => Some(OutputEnvelope::from(error)), }; if let Some(output) = output { let mut data = Value::Object(Map::new()); match output.error { Some(error) => { res = match error.class { ErrorClass::ClientProtocolError => res.status(StatusCode::BAD_REQUEST), ErrorClass::ServerError => { res.status(StatusCode::INTERNAL_SERVER_ERROR) } _ => res.status(StatusCode::OK), }; data["status"] = Value::from("error"); data["error"] = Value::from(error); } None => { data["status"] = Value::from("success"); } } data["request_nr"] = match output.request_nr { Some(nr) => Value::from(nr), None => Value::Null, }; data["data"] = output.data; return Ok(res .body(Body::from(serde_json::to_string(&data).unwrap() + "\r\n")) .unwrap()); } else { res = res.status(StatusCode::NO_CONTENT); } return Ok(res.body(Body::empty()).unwrap()); } _ => Ok(res .status(StatusCode::NOT_FOUND) .body(Body::empty()) .unwrap()), }; match val { Ok(val) => Ok(val), Err(_error) => { todo!("help") } } }