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
mod krakend;

use krakend::{Backend, Endpoint, ExtraConfig};
use openapiv3::{OpenAPI, PathItem};

/// Builds a krakend endpoints[] from an openapi.json
/// * `openapi_json` - The String representation of an openapi v3 JSON
/// * `hosts` - The host[] in krakend endpoint conf
/// ```
/// std::env::set_var("RUST_BACKTRACE", "1");
/// let openapi_json: String = std::fs::read_to_string("./openapi.json").unwrap().parse().unwrap();
/// assert!(!openapi_json.is_empty());
/// let hosts = vec!["http://127.0.0.1:8529".to_owned()];
/// let endpoints = krakend_conf::convert_endpoints(openapi_json, hosts);
/// assert!(!endpoints.is_empty());
/// let eps = serde_json::to_string(&endpoints);
/// let res = std::fs::write("krakend_endpoints.json", eps.unwrap().as_bytes());
/// println!("{:#?}", res);
/// ```
pub fn convert_endpoints(openapi_json: String, hosts: Vec<String>) -> Vec<Endpoint> {
    let openapi: OpenAPI = serde_json::from_str(&openapi_json).expect("Could not deserialize input");

    let srv = openapi.servers.first().unwrap();
    let base_path = srv.url.clone();
    let title = openapi.info.title;

    let mut endpoints = Vec::new();
    for path in openapi.paths {
        let pit = serde_yaml::to_string(&path.1).unwrap();
        let dpath: PathItem = serde_yaml::from_str(&pit).unwrap();
        let pth = format!("/{}{}", title, path.0);
        let backend_pth = format!("{}{}", base_path, path.0.clone());

        if let Some(_op) = dpath.get {
            let method = "GET".to_owned();
            let e = create_endpoint(pth.clone(), backend_pth.clone(), hosts.clone(), method);
            endpoints.push(e);
        }
        if let Some(_op) = dpath.post {
            let method = "POST".to_owned();
            let e = create_endpoint(pth.clone(), backend_pth.clone(), hosts.clone(), method);
            endpoints.push(e);
        }
        if let Some(_op) = dpath.put {
            let method = "PUT".to_owned();
            let e = create_endpoint(pth.clone(), backend_pth.clone(), hosts.clone(), method);
            endpoints.push(e);
        }
        if let Some(_op) = dpath.patch {
            let method = "PATCH".to_owned();
            let e = create_endpoint(pth.clone(), backend_pth.clone(), hosts.clone(), method);
            endpoints.push(e);
        }
        if let Some(_op) = dpath.delete {
            let method = "DELETE".to_owned();
            let e = create_endpoint(pth.clone(), backend_pth.clone(), hosts.clone(), method);
            endpoints.push(e);
        }
    }
    endpoints
}

/// Create a crate::krakend::Endpoint from
/// * `pth` - A url path where krakend will listen at
/// * `backend_pth` - Where to route the requests if all goes well
/// * `hosts` - The host[] in krakend endpoint conf
/// * `method` - HTTP method of this endpoint
pub fn create_endpoint(
    pth: String,
    backend_pth: String,
    hosts: Vec<String>,
    method: String,
) -> Endpoint {
    let is_collection;
    let mut enc = "no-op";
    if !pth.contains('{') && method.eq("GET") {
        // probably a collection
        is_collection = true;
        enc = "json";
    } else {
        is_collection = false;
    };
    let mut e = Endpoint::default();
    e.endpoint = pth;
    e.method = method;
    e.output_encoding = enc.to_owned();
    e.concurrent_calls = 1i64;
    e.headers_to_pass = vec!["Content-Type".to_owned(), "Content-Length".to_owned()];
    let b = Backend {
        url_pattern: backend_pth,
        encoding: enc.to_owned(),
        sd: "static".to_owned(),
        extra_config: ExtraConfig::default(),
        host: hosts,
        disable_host_sanitize: false,
        is_collection,
    };
    e.backend = vec![b];
    e
}