ice_core 0.3.9

High performance Web engine
Documentation
use std;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ops::Deref;
use std::rc::Rc;
use std::cell::RefCell;
use hyper;
use ice_server;
use session_storage;
use glue::serialize;
use glue::common;

pub struct Request {
    pub uri: CString,
    pub remote_addr: CString,
    pub method: CString,
    pub url_params: HashMap<String, String>,
    pub headers: Rc<hyper::header::Headers>,
    pub cookies: HashMap<String, CString>,
    pub custom_properties: Arc<common::CustomProperties>,
    pub body: Box<Deref<Target = RefCell<Vec<u8>>>>,
    pub context: Arc<ice_server::Context>,
    pub session: Option<Arc<Mutex<session_storage::Session>>>,
    pub cache: RequestCache
}

#[derive(Default)]
pub struct RequestCache {
    stats: Option<CString>,
    session_items: HashMap<String, CString>,
    headers: HashMap<String, CString>,
    url_params_raw: Option<Vec<u8>>,
    headers_raw: Option<Vec<u8>>,
    cookies_raw: Option<Vec<u8>>,
    session_items_raw: Option<Vec<u8>>
}

impl Request {
    pub fn into_boxed(self) -> Box<Request> {
        Box::new(self)
    }
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_stats(req: *mut Request) -> *const c_char {
    let req = &mut *req;

    req.cache.stats = Some(CString::new(req.context.stats.serialize().to_string()).unwrap());
    let ret = req.cache.stats.as_ref().unwrap().as_ptr();

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_uri(req: *mut Request) -> *const c_char {
    let req = &*req;

    let ret = req.uri.as_ptr();

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_method(req: *mut Request) -> *const c_char {
    let req = &*req;

    let ret = req.method.as_ptr();

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_remote_addr(req: *mut Request) -> *const c_char {
    let req = &*req;

    let ret = req.remote_addr.as_ptr();

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_url_params(req: *mut Request) -> *const u8 {
    let req = &mut *req;
    
    if req.cache.url_params_raw.is_none() {
        req.cache.url_params_raw = Some(
            serialize::std_map(req.url_params.iter(), req.url_params.len())
        );
    }

    req.cache.url_params_raw.as_ref().unwrap().as_ptr()
}

#[no_mangle]
pub unsafe fn ice_glue_request_set_custom_stat(req: *mut Request, k: *const c_char, v: *const c_char) {
    let req = &*req;

    let k = CStr::from_ptr(k).to_str().unwrap();
    let v = CStr::from_ptr(v).to_str().unwrap();

    req.context.stats.set_custom(k.to_string(), v.to_string());
}


#[no_mangle]
pub unsafe fn ice_glue_request_get_body(req: *mut Request, len_out: *mut u32) -> *const u8 {
    let req = &*req;
    let body = req.body.borrow();

    let ret = body.as_slice().as_ptr();
    *len_out = body.len() as u32;

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_header(req: *mut Request, k: *const c_char) -> *const c_char {
    let req = &mut *req;
    let k = CStr::from_ptr(k).to_str().unwrap();

    let ret = match req.headers.get_raw(k) {
        Some(v) => match v.one() {
            Some(v) => match std::str::from_utf8(v) {
                Ok(v) => Some(CString::new(v).unwrap()),
                Err(_) => None
            },
            None => None
        },
        None => None
    };
    let ret = match ret {
        Some(v) => {
            req.cache.headers.insert(k.to_string(), v);
            req.cache.headers.get(k).as_ref().unwrap().as_ptr()
        },
        None => std::ptr::null()
    };

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_headers(req: *mut Request) -> *const u8 {
    let req = &mut *req;

    if req.cache.headers_raw.is_none() {
        req.cache.headers_raw = Some(
            serialize::std_map(req.headers.iter().map(|v| {
                (v.name(), v.value_string())
            }), req.headers.len())
        );
    }

    req.cache.headers_raw.as_ref().unwrap().as_ptr()
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_cookie(req: *mut Request, k: *const c_char) -> *const c_char {
    let req = &*req;
    let k = CStr::from_ptr(k).to_str().unwrap();

    let ret = match req.cookies.get(k) {
        Some(ref v) => v.as_ptr(),
        None => std::ptr::null()
    };

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_cookies(req: *mut Request) -> *const u8 {
    let req = &mut *req;

    if req.cache.cookies_raw.is_none() {
        req.cache.cookies_raw = Some(
            serialize::std_map(req.cookies.iter().map(|(k, v)| {
                (k, match std::str::from_utf8(v.as_bytes()) {
                    Ok(v) => v,
                    Err(_) => ""
                })
            }), req.cookies.len())
        );
    }

    req.cache.cookies_raw.as_ref().unwrap().as_ptr()
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_session_item(req: *mut Request, k: *const c_char) -> *const c_char {
    let req = &mut *req;

    let k = CStr::from_ptr(k).to_str().unwrap();
    let ret;

    {
        let v = match req.session {
            Some(ref session) => {
                match session.lock().unwrap().data.get(k) {
                    Some(v) => {
                        Some(CString::new(v.as_str()).unwrap())
                    },
                    None => None
                }
            },
            None => None
        };

        let mut session_items = &mut req.cache.session_items;
        ret = match v {
            Some(v) => {
                session_items.insert(k.to_string(), v);
                session_items.get(k).as_ref().unwrap().as_ptr()
            },
            None => std::ptr::null()
        };
    }

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_get_session_items(req: *mut Request) -> *const u8 {
    let req = &mut *req;

    match req.session {
        Some(ref session) => {
            let session = session.lock().unwrap();
            req.cache.session_items_raw = Some(
                serialize::std_map(session.data.iter(), session.data.len())
            );
            req.cache.session_items_raw.as_ref().unwrap().as_ptr()
        },
        None => std::ptr::null()
    }
}

#[no_mangle]
pub unsafe fn ice_glue_request_set_session_item(req: *mut Request, k: *const c_char, value: *const c_char) {
    let req = &*req;
    let k = CStr::from_ptr(k).to_str().unwrap();

    match req.session {
        Some(ref session) => {
            match value.is_null() {
                true => {
                    session.lock().unwrap().data.remove(k);
                },
                false => {
                    let value = CStr::from_ptr(value).to_str().unwrap();
                    session.lock().unwrap().data.insert(k.to_string(), value.to_string());
                }
            }
        },
        None => {}
    }
}

#[no_mangle]
pub unsafe fn ice_glue_request_render_template_to_owned(req: *mut Request, name: *const c_char, data: *const c_char) -> *mut c_char {
    let req = &*req;

    let ret = match req.context.templates.render_json(
        CStr::from_ptr(name).to_str().unwrap(),
        CStr::from_ptr(data).to_str().unwrap()
    ) {
        Some(v) => CString::new(v).unwrap().into_raw(),
        None => std::ptr::null_mut()
    };

    ret
}

#[no_mangle]
pub unsafe fn ice_glue_request_borrow_context(req: *mut Request) -> *const ice_server::Context {
    let req = &*req;
    &*req.context
}

#[no_mangle]
pub unsafe fn ice_glue_request_borrow_custom_properties(req: *mut Request) -> *const common::CustomProperties {
    let req = &*req;
    &*req.custom_properties
}