arara-cgi 1.0.0

A arara dependecie
Documentation
use std::collections::HashMap;
use std::env;
use std::io::{self, Read};

use crate::error::{CgiError, CgiErrorKind};

pub enum Method {
    GET,
    HEAD,
    OPTIONS,
    TRACE,
    PUT,
    DELETE,
    POST,
    PATCH,
    CONNECT,

    OTHER(&'static str)
}

pub struct Request {
    pub method: Method,
    pub path: &'static str,
    pub body: Option<String>,
    pub headers: HashMap<String, String>
}


pub fn new_request() -> Result<Request, CgiError> {
    let method = {
        let method_str = env::var("REQUEST_METHOD");
        if method_str.is_err() {
            return Err(CgiError::new("REQUEST_METHOD enviroment variable was not found", CgiErrorKind::RequestMethodNodFound))
        }
            
        match method_str.unwrap().leak() as &'static str {
            "GET" => Method::GET,
            "HEAD" => Method::HEAD,
            "OPTIONS" => Method::OPTIONS,
            "TRACE" => Method::TRACE,
            "PUT" => Method::PUT,
            "DELETE" => Method::DELETE,
            "POST" => Method::POST,
            "PATCH" => Method::PATCH,
            "CONNECT" => Method::CONNECT,

            other => {
                if other.is_empty() {
                    return Err(CgiError::new("method is empty", CgiErrorKind::EmptyContent))
                } else {
                    Method::OTHER(other)
                }
            }
        }
    };

    let path = env::var("PATH_INFO");
    if path.is_err() {
        return Err(CgiError::new("PATH_INFO enviroment variable was not found", CgiErrorKind::PathInfoNotFound));
    }
    let path = path.unwrap().leak();
    if path.is_empty() {
        return Err(CgiError::new("path is empty", CgiErrorKind::EmptyContent))
    }

    let body_len_str = env::var("CONTENT_LENGTH");
    let body_len: u64;
    match body_len_str {
        Ok(body_len_str) => {
            body_len = body_len_str.parse().unwrap();
        }

        Err(_) => return Err(CgiError::new("CONTENT_LENGTH enviroment variable was not found", CgiErrorKind::ContentLengthNotFound))
    }

    let body = {
        let mut body_buffer = String::new();
        let io_result = io::stdin()
            .take(body_len)
            .read_to_string(&mut body_buffer);

        if io_result.is_err() {
            return Err(CgiError::new("failed to read body input", CgiErrorKind::InputBodyFail))
        }
        drop(io_result);

        if body_buffer.is_empty() {
            None
        } else {
            Some(body_buffer)
        }
    };

    let mut headers = HashMap::new();
    for (key, value) in env::vars() {
        if key.starts_with("HTTP_") && key.len() >= 5 {
            headers.insert(key, value);
        }
    }
    
    Ok(Request {
        method: method,
        path: path,
        body: body,
        headers: headers
    })
}