sockjs 0.3.0

SockJS server for Actix
Documentation
use time;
use actix_web::HttpRequest;
use actix_web::http::Cookie;
use actix_web::dev::HttpResponseBuilder;
use http::header::HeaderMap;
use http::header::{EXPIRES, ORIGIN, CACHE_CONTROL,
                   ACCESS_CONTROL_ALLOW_ORIGIN,
                   ACCESS_CONTROL_ALLOW_HEADERS,
                   ACCESS_CONTROL_ALLOW_METHODS,
                   ACCESS_CONTROL_ALLOW_CREDENTIALS,
                   ACCESS_CONTROL_MAX_AGE,
                   ACCESS_CONTROL_REQUEST_HEADERS};

const CACHE_CONTROL_VAL: &str =
    "no-store, no-cache, no-transform, must-revalidate, max-age=0";

#[derive(Serialize)]
pub(crate) struct Info {
    entropy: u32,
    websocket: bool,
    cookie_needed: bool,
    origins: Vec<&'static str>,
}

impl Info {

    pub fn new(entropy: u32, websocket: bool, cookie_needed: bool) -> Info {
        Info {
            entropy,
            websocket,
            cookie_needed,
            origins: vec!["*:*"],
        }
    }
}


pub(crate) trait SockjsHeaders {

    fn sockjs_allow_methods(&mut self) -> &mut Self;

    fn sockjs_no_cache(&mut self) -> &mut Self;

    fn sockjs_cache_headers(&mut self) -> &mut Self;

    fn sockjs_cors_headers(&mut self, headers: &HeaderMap) -> &mut Self;

    fn sockjs_session_cookie<S>(&mut self, req: &HttpRequest<S>) -> &mut Self;

}


impl SockjsHeaders for HttpResponseBuilder {

    fn sockjs_session_cookie<S>(&mut self, req: &HttpRequest<S>) -> &mut Self {
        let builder = if let Some(cookie) = req.cookie("JSESSIONID") {
            Cookie::build("JSESSIONID", cookie.value().to_owned())
        } else {
            Cookie::build("JSESSIONID", "dummy")
        };
        self.cookie(builder.path("/").finish());
        self
    }

    fn sockjs_allow_methods(&mut self) -> &mut Self {
        self.header(ACCESS_CONTROL_ALLOW_METHODS, "OPTIONS, GET")
    }

    fn sockjs_no_cache(&mut self) -> &mut Self {
        self.header(CACHE_CONTROL, CACHE_CONTROL_VAL)
    }

    fn sockjs_cors_headers(&mut self, headers: &HeaderMap) -> &mut Self {
        if let Some(origin) = headers.get(ORIGIN) {
            self.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin.as_ref());
            if origin != "*" {
                self.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            }
        } else {
            self.header(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        }

        if let Some(ac) = headers.get(ACCESS_CONTROL_REQUEST_HEADERS) {
            self.header(ACCESS_CONTROL_ALLOW_HEADERS, ac.as_ref());
        }

        self
    }

    fn sockjs_cache_headers(&mut self) -> &mut Self {
        const TD365_SECONDS: &str = "31536000";
        const TD365_SECONDS_CC: &str  = "max-age=31536000, public";

        let d = time::now() + time::Duration::days(365);

        self.header(CACHE_CONTROL, TD365_SECONDS_CC);
        self.header(ACCESS_CONTROL_MAX_AGE, TD365_SECONDS);
        self.header(EXPIRES, time::strftime("%a, %d %b %Y %H:%M:%S", &d).unwrap().as_str());

        self
    }
}