twisty 0.3.1

Example WebSocket Echo client implemented with twist
//! twisty config
use slog::{DrainExt, Level, LevelFilter, Logger, duplicate};
use slog_stream::async_stream;
use slog_term::{self, ColorDecorator, Format, FormatMode, timestamp_utc};
use std::env;
use std::fs::{self, OpenOptions};
use url::Url;

/// Default dot dir.
pub const DOT_DIR: &'static str = ".twisty";

/// `twisty` Configuration
#[derive(Clone, Debug)]
pub struct Config {
    /// The host to connect to.
    host: String,
    /// The port for the connection.
    port: u16,
    /// Is TLS enabled?
    tls_enabled: bool,
    /// The value to use in the hanshake host header.
    host_header: String,
    /// The value to use in the handshake origin header.
    origin_header: String,
    /// The URL path.
    path: String,
    /// The URL query string.
    query: String,
    /// The path to the PFX file for TLS.
    pfx_file_path: String,
    /// The slog file/stderr `Logger`
    dual: Logger,
}

impl Config {
    /// Generate a new twisty config given a `Url`.
    pub fn new(url: Url) -> Result<Config, ()> {
        let stderr_term = slog_term::streamer().stderr().async().compact().build();
        let stderr_drain = LevelFilter::new(stderr_term, Level::Error);

        let mut logpath = env::temp_dir();
        logpath.push(DOT_DIR);
        if fs::create_dir_all(&logpath).is_err() {
            logpath.pop();
        }
        logpath.push("twisty.log");

        let mut file_drain = None;
        if let Ok(log_file) = OpenOptions::new().create(true).append(true).open(logpath) {
            let fmt = Format::new(FormatMode::Compact,
                                  ColorDecorator::new_colored(),
                                  Box::new(timestamp_utc));
            file_drain = Some(async_stream(log_file, fmt));
        }

        let dual = if let Some(file_drain) = file_drain {
            Logger::root(duplicate(file_drain, stderr_drain).fuse(),
                         o!(
                "executable" => env!("CARGO_PKG_NAME"),
                "version" => env!("CARGO_PKG_VERSION")
            ))
        } else {
            Logger::root(stderr_drain.fuse(),
                         o!(
                "executable" => env!("CARGO_PKG_NAME"),
                "version" => env!("CARGO_PKG_VERSION")
            ))
        };

        let scheme = url.scheme();

        if !(scheme == "ws" || scheme == "wss") {
            err!("invalid websocket scheme: {}", scheme);
            return Err(());
        }

        let host = if let Some(host_str) = url.host_str() {
            host_str.into()
        } else {
            "127.0.0.1".into()
        };

        let port = if let Some(port) = url.port() {
            port
        } else if scheme == "ws" {
            80
        } else if scheme == "wss" {
            443
        } else {
            return Err(());
        };

        let path = url.path().to_string();
        let query = if let Some(query) = url.query() {
            query.to_string()
        } else {
            String::new()
        };

        Ok(Config {
               host: host,
               port: port,
               tls_enabled: scheme == "wss",
               host_header: String::from("jasonozias.com"),
               origin_header: String::from("http://jasonozias.com"),
               path: path,
               query: query,
               pfx_file_path: String::from(".env/jasonozias.com.pfx"),
               dual: dual,
           })
    }

    /// Get the `host` value.
    pub fn host(&self) -> &str {
        &self.host
    }

    /// Get the `port` value.
    pub fn port(&self) -> u16 {
        self.port
    }

    /// Get the `tls_enabled` value.
    pub fn tls_enabled(&self) -> bool {
        self.tls_enabled
    }

    /// Get the `host_header` value.
    pub fn host_header(&self) -> &str {
        &self.host_header
    }

    /// Set the `host_header` value.
    pub fn set_host_header(&mut self, host_header: String) -> &mut Config {
        self.host_header = host_header;
        self
    }

    /// Get the `origin_header` value.
    pub fn origin_header(&self) -> &str {
        &self.origin_header
    }

    /// Set the `origin_header` value.
    pub fn set_origin_header(&mut self, origin_header: String) -> &mut Config {
        self.origin_header = origin_header;
        self
    }

    /// Get the `path` value.
    pub fn path(&self) -> &str {
        &self.path
    }

    /// Get the `query` value.
    pub fn query(&self) -> &str {
        &self.query
    }

    /// Get the `pfx_file_path` value.
    #[allow(dead_code)]
    pub fn pfx_file_path(&self) -> &str {
        &self.pfx_file_path
    }

    /// Set the `pfx_file_path` value.
    pub fn set_pfx_file_path(&mut self, pfx_file_path: String) -> &mut Config {
        self.pfx_file_path = pfx_file_path;
        self
    }

    /// Get the stdout slog `Logger`.
    pub fn dual(&self) -> Logger {
        self.dual.clone()
    }
}