diff --git a/Cargo.lock b/Cargo.lock index 5f8fb71..cc83e19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,6 +427,7 @@ dependencies = [ name = "endstat" version = "0.1.0" dependencies = [ + "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index eebe9a5..e39a9d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ serde = { version = "1.0.90", features = ["derive"] } ron = "0.5" actix-web = "0.7" tokio = "0.1" +actix = "0.7" diff --git a/src/main.rs b/src/main.rs index 5aba61a..40d5621 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,23 @@ +extern crate actix; +extern crate actix_web; +extern crate reqwest; +extern crate ron; +extern crate serde; + +use actix::System; +use actix_web::{ + http::{Method, StatusCode}, + server, App, HttpResponse, State, +}; use reqwest::{Client, Url, UrlError}; use ron::de::from_str; use serde::Deserialize; -use std::error::Error; -use std::fs::read_to_string; -use std::time::{Duration, Instant}; -use tokio::prelude::*; -use tokio::timer::Interval; +use std::{ + error::Error, + fs::read_to_string, + sync::{Arc, Mutex}, + time::{Duration, Instant}, +}; #[derive(Deserialize, Debug, Clone)] struct EndpointConf { @@ -38,29 +50,61 @@ struct Status { error: Option, } +struct FetchResults { + last_update: Instant, + refresh_time: u64, + config: Config, + statuses: Vec, +} + +type StatusState = Arc>; + +fn index(state: State) -> HttpResponse { + let mut state = state.lock().unwrap(); + let mut result = String::new(); + if Instant::now().duration_since(state.last_update) > Duration::from_secs(state.refresh_time) { + result = format!( + "it has been {:} seconds since last update, updating", + Instant::now().duration_since(state.last_update).as_secs() + ); + state.last_update = Instant::now(); + state.statuses = update_status(&state.config); + } + + let result = format!("{}\n{:?}", result, state.statuses); + HttpResponse::with_body(StatusCode::OK, result) +} + fn main() -> Result<(), Box> { let config = from_str::(&read_to_string("./endstat_conf.ron")?)?; - let mut statuses = update_status(config.clone()); - let update_loop = Interval::new(Instant::now(), Duration::from_secs(config.refresh_time)) - .for_each(move |_instant| { - statuses = update_status(config.clone()); - Ok(()) - }) - .map_err(|e| panic!("interval errored; err={:?}", e)); + println!("running server"); + let sys = System::new("status"); - tokio::run(update_loop); + let a: Arc> = Arc::from(Mutex::from(FetchResults { + last_update: Instant::now(), + refresh_time: config.refresh_time, + config: config.clone(), + statuses: update_status(&config), + })); + server::new(move || { + App::with_state(a.clone()).resource("/", |r| r.method(Method::GET).with(index)) + }) + .bind("0.0.0.0:8080")? + .start(); + + sys.run(); Ok(()) } -fn update_status(config: Config) -> Vec { +fn update_status(config: &Config) -> Vec { let client = Client::new(); let mut results: Vec = vec![]; - for website_conf in config.websites { - for endpoint in website_conf.endpoints { - let (label, path, port, code, body) = get_endpoint_info(endpoint); + for website_conf in &config.websites { + for endpoint in &website_conf.endpoints { + let (label, path, port, code, body) = get_endpoint_info(endpoint.clone()); let url = get_url(&website_conf.base, &path, port).expect("reading config"); if let Ok(mut res) = client.get(&url).send() { let res_body = res.text().expect("could not get body of request");