1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use iron::headers::ContentType; use hyper::mime::{Mime, TopLevel, SubLevel}; use iron::modifiers::Header; use iron::{Iron, Request, Response, IronResult}; use iron::status; use mount::Mount; use std::path::Path; use std::thread::{spawn, JoinHandle}; use iron::middleware::Handler; use staticfile::Static; #[allow(unused_imports)] use std::fs::File; #[allow(unused_imports)] use std::io::Read; #[allow(unused_imports)] use std::str::from_utf8; use Dashboard; use WsServer; include!(concat!(env!("OUT_DIR"), "/public.rs")); pub struct Server { dashboard: Dashboard, } lazy_static! { } impl Server { pub fn serve_dashboard(dashboard: Dashboard) -> JoinHandle<()> { let join = Server{ dashboard: dashboard }.start(); WsServer::send_message("start".to_owned()); join } fn get_static_file(req: &mut Request) -> IronResult<Response> { let request_path = format!("./public/{}", req.url.path().join("/")); let file_path = match request_path.as_ref() { "./public/" => "./public/index.html", path => path }; let content_result = Server::get_file_content(&file_path); match content_result { Ok(content) => { let content_type = match Path::new(&file_path).extension().unwrap().to_str().unwrap() { "html" => ContentType::html(), "css" => ContentType(Mime(TopLevel::Text, SubLevel::Css, vec![])), "js" | "json" => ContentType(Mime(TopLevel::Application, SubLevel::Javascript, vec![])), "ico" => ContentType("image/x-icon".parse().unwrap()), _ => ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![])) }; let response = Response::with((status::Ok, content, Header(content_type))); Ok(response) }, Err(_error) => Ok(Response::with(status::NotFound)) } } #[cfg(feature = "serve_static")] fn get_file_content(file_path: &str) -> Result<String, String> { match PUBLIC.get(&file_path) { Err(_) => Server::path_not_found(file_path), file => Ok(file.map( |file_content| from_utf8(&file_content).unwrap().to_owned()).unwrap()) } } #[cfg(feature = "debug_static")] fn get_file_content(file_path: &str) -> Result<String, String> { match PUBLIC.get(&file_path) { Err(_) => Server::path_not_found(file_path), _ => { let mut file = File::open(file_path).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); Ok(contents) } } } fn path_not_found(file_path: &str) -> Result<String, String>{ println!("File not found: {}", file_path); Err("File not found".to_string()) } fn start(&self) -> JoinHandle<()> { let dashboard = DashboardMount{dashboard: self.dashboard.get_init_script().to_owned()}; let server = spawn(move || { let mut mount = Mount::new(); mount .mount("/", Server::get_static_file) .mount("/graphs/", Static::new(Path::new("graphs"))) .mount("/js/rusty-dashed.js", dashboard); Iron::new(mount).http("0.0.0.0:3000").unwrap(); }); server } } struct DashboardMount { pub dashboard: String } impl Handler for DashboardMount { fn handle(&self, _req: &mut Request) -> IronResult<Response>{ Ok(Response::with((status::Ok, self.dashboard.to_owned()))) } }