summaryrefslogtreecommitdiffstats
path: root/src/lib.rs
blob: 5fd54c912382b76c8b519ed01aa45a8415a7f9e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

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<String>,      // 127.0.0.1:9292
    pub upstream_addr: Option<String>,  // 127.0.0.1:9200
    pub index: Vec<IndexConfig>
}

#[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<Body>),
}

pub fn parse_request(req: Request<Body>, 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())
}