use serde::{Serialize, Deserialize}; use hyper::{Request, Body, Method, Uri}; use http::request; pub mod parse; #[derive(Default, Deserialize, Debug, Clone)] pub struct ProxyConfig { pub bind_addr: Option, // 127.0.0.1:9292 pub upstream_addr: Option, // 127.0.0.1:9200 pub index: Vec } #[derive(Deserialize, Debug, Clone)] pub struct IndexConfig { pub name: String, } impl ProxyConfig { pub fn allow_index(&self, name: &str) -> bool { for index in &self.index { if index.name == name { return true } } false } } #[derive(Debug)] pub enum ParsedRequest { Malformed(String), ParseError(String), NotAllowed(String), NotSupported(String), NotFound(String), Allowed(Request), } pub fn parse_request(req: Request, config: &ProxyConfig) -> ParsedRequest { let (parts, body) = req.into_parts(); // split path into at most 3 chunks let mut req_path = parts.uri.path(); if req_path.starts_with("/") { req_path = &req_path[1..]; } let path_chunks: Vec<&str> = req_path.split("/").collect(); if path_chunks.len() > 3 { return ParsedRequest::NotSupported("only request paths with up to three segments allowed".to_string()) } println!("{:?}", path_chunks); // this is sort of like a router match (&parts.method, path_chunks.as_slice()) { (&Method::GET, [""]) | (&Method::HEAD, [""]) => { parse_request_basic("", &parts, config) }, (&Method::POST, ["_search", "scroll"]) | (&Method::DELETE, ["_search", "scroll"]) => { parse_request_scroll(None, &parts, body, config) }, (&Method::POST, ["_search", "scroll", key]) | (&Method::DELETE, ["_search", "scroll", key]) => { parse_request_scroll(Some(key), &parts, body, config) }, (&Method::GET, [index, "_search"]) | (&Method::POST, [index, "_search"]) => { parse_request_search(index, &parts, body, config) }, //(Method::GET, [index, "_count"]) => { // parse_request_count(index, "_count", None, &parts, body, config) //}, (&Method::GET, [index, "_doc", key]) | (&Method::GET, [index, "_source", key]) => { parse_request_read(index, path_chunks[1], key, &parts, body, config) }, _ => ParsedRequest::NotSupported("unknown endpoint".to_string()), } } pub fn parse_request_basic(endpoint: &str, parts: &request::Parts, config: &ProxyConfig) -> ParsedRequest { // XXX: partial let upstream_uri = Uri::builder() .scheme("http") .authority(config.upstream_addr.as_ref().unwrap_or(&"localhost:9200".to_string()).as_str()) .path_and_query(format!("/{}", endpoint).as_str()) .build() .unwrap(); println!("{:?}", upstream_uri); let upstream_req = Request::builder() .uri(upstream_uri) .method(&parts.method) .body(Body::empty()) .unwrap(); ParsedRequest::Allowed(upstream_req) } pub fn parse_request_scroll(key: Option<&str>, parts: &request::Parts, body: Body, config: &ProxyConfig) -> ParsedRequest { ParsedRequest::NotSupported("not yet implemented".to_string()) } pub fn parse_request_search(index: &str, parts: &request::Parts, body: Body, config: &ProxyConfig) -> ParsedRequest { ParsedRequest::NotSupported("not yet implemented".to_string()) } pub fn parse_request_read(index: &str, endpoint: &str, key: &str, parts: &request::Parts, body: Body, config: &ProxyConfig) -> ParsedRequest { ParsedRequest::NotSupported("not yet implemented".to_string()) }