dockers 0.1.6

A rust docker library
Documentation
pub mod info;
pub mod errors;

use curl::easy::{Easy, List};
use std::env::var;

pub use self::errors::DockerApiError;

#[derive(Debug, Clone)]
pub struct Response {
    pub status_code: usize,
    pub body: String,
}

pub enum Method {
    GET,
    POST,
    DELETE,
}

fn request(
    api_endpint: &str,
    method: Method,
    body_w: Option<&str>,
) -> Response {
    let unix_socket_url =
        var("DOCKERS_SOCKET_URL").unwrap_or("/var/run/docker.sock".to_owned());

    let mut e = Easy::new();
    let mut status_code: usize = 0;
    let mut body = Vec::new();
    let body_w = body_w.unwrap_or_default();

    e.unix_socket(&unix_socket_url).unwrap();

    e.url(&format!("http{}", api_endpint)).unwrap();
    let mut headers = List::new();

    headers.append("Content-Type: application/json").unwrap();

    e.http_headers(headers).unwrap();

    let _ = match method {
        Method::GET => e.get(true).unwrap(),
        Method::POST => {
            e.post(true).unwrap();
            e.post_fields_copy(body_w.as_bytes()).unwrap()
        }
        Method::DELETE => {
            e.custom_request("DELETE").unwrap();
        }
    };

    {
        let mut transfer = e.transfer();

        transfer
            .header_function(|h| {
                let header = String::from_utf8(h.to_vec())
                    .expect("Header to string failed");
                print!("header: {}", header);
                if status_code == 0 {
                    let parts: Vec<&str> = header.splitn(3, " ").collect();
                    if parts.len() > 1 {
                        status_code = parts[1]
                            .parse()
                            .expect("Cannot parse this string into usize");
                    }
                }
                true
            })
            .unwrap();

        transfer
            .write_function(|d| {
                body.extend_from_slice(d);

                Ok(d.len())
            })
            .unwrap();

        transfer.perform().unwrap();
    }

    let body = if body.is_empty() {
        "".to_owned()
    } else {
        String::from_utf8(body[..body.len() - 1].to_vec())
            .expect("Cannot parse vec to string")
    };

    println!("{}", body);

    Response {
        status_code: status_code.clone(),
        body,
    }
}

pub fn invalid_api_resp(res: Response) -> DockerApiError {
    DockerApiError::InvalidApiResponseError(res.status_code, res.body)
}

pub fn get_response_from_api_static(
    api_endpoint: &str,
    method: Method,
    query_params: Option<&str>,
    body: Option<&str>,
) -> Result<Response, DockerApiError> {
    let api_endpoint =
        format!("{}{}", api_endpoint, query_params.unwrap_or_default());

    Ok(request(&api_endpoint, method, body))
}

pub trait Client {
    fn get_response_from_api(
        &self,
        api_endpoint: &str,
        method: Method,
        query_params: Option<&str>,
        body: Option<&str>,
    ) -> Result<Response, DockerApiError> {
        let res: Result<Response, DockerApiError> =
            get_response_from_api_static(
                api_endpoint,
                method,
                query_params,
                body,
            );

        res
    }
}