Compare commits

..

No commits in common. "ddab660945b12ab6676c20ae8829633427b4b4ca" and "01757eb4da609a2ba035e104d209a0a03e28e74d" have entirely different histories.

5 changed files with 28 additions and 52 deletions

View file

@ -35,7 +35,6 @@
endpoints:[ endpoints:[
(label: "The code doesn't match!", endpoint: "http://example.com/", code: 204), (label: "The code doesn't match!", endpoint: "http://example.com/", code: 204),
(label: "The body doesn't match!", endpoint: "http://example.com/", body: "asdf"), (label: "The body doesn't match!", endpoint: "http://example.com/", body: "asdf"),
(label: "Slow reponse time", endpoint: "http://slowwly.robertomurray.co.uk/delay/2000/url/"),
(label: "Here's an error:", endpoint: "https://some-invalid-website.arpa") (label: "Here's an error:", endpoint: "https://some-invalid-website.arpa")
] ]
), ),

View file

@ -68,11 +68,10 @@
<div class="info"> <div class="info">
<h3>{{ status.endpoint }}</h3> <h3>{{ status.endpoint }}</h3>
<div class="spacer"></div> <div class="spacer"></div>
{% if status.status != 2 %}<p>{{ status.rtt }}</p>{% endif %} <a href="{{ status.location }}" target="_blank">{{ status.location }}</a>
</div> </div>
<a href="{{ status.location }}" target="_blank">{{ status.location }}</a>
{% if status.error %}<p class="error-msg">{{ status.error }}</p>{% endif %} {% if status.error %}<p class="error-msg">{{ status.error }}</p>{% endif %}
</main> </main>
</section> </section>
{% endfor -%} {% endfor -%}
{% endfor -%} {% endfor -%}

View file

@ -12,27 +12,24 @@ pub struct EndpointStatus {
pub status: u8, pub status: u8,
pub location: String, pub location: String,
pub endpoint: String, pub endpoint: String,
pub rtt: Option<String>,
pub error: Option<String>, pub error: Option<String>,
} }
impl EndpointStatus { impl EndpointStatus {
pub fn ok(location: String, endpoint: String, rtt: String) -> Self { pub fn ok(location: String, endpoint: String) -> Self {
EndpointStatus { EndpointStatus {
status: 0, status: 0,
location, location,
endpoint, endpoint,
rtt: Some(rtt),
error: None, error: None,
} }
} }
pub fn warn(location: String, endpoint: String, rtt: String, error: Option<String>) -> Self { pub fn warn(location: String, endpoint: String, error: Option<String>) -> Self {
EndpointStatus { EndpointStatus {
status: 1, status: 1,
location, location,
endpoint, endpoint,
rtt: Some(rtt),
error, error,
} }
} }
@ -42,7 +39,6 @@ impl EndpointStatus {
status: 2, status: 2,
location, location,
endpoint, endpoint,
rtt: None,
error, error,
} }
} }

View file

@ -1,5 +1,3 @@
#![forbid(unsafe_code)]
extern crate actix; extern crate actix;
extern crate actix_web; extern crate actix_web;
extern crate chrono; extern crate chrono;

View file

@ -3,7 +3,7 @@ use crate::{
handlers::{EndpointStatus, StatusGroup}, handlers::{EndpointStatus, StatusGroup},
State, State,
}; };
use chrono::Utc; use chrono::prelude::Utc;
use reqwest::{Client, RedirectPolicy, Url, UrlError}; use reqwest::{Client, RedirectPolicy, Url, UrlError};
use ring::{ use ring::{
digest::{digest, SHA256}, digest::{digest, SHA256},
@ -51,15 +51,7 @@ fn get_result(
) -> EndpointStatus { ) -> EndpointStatus {
let (label, path, port, code, body) = get_endpoint_info(endpoint.clone()); let (label, path, port, code, body) = get_endpoint_info(endpoint.clone());
let url = get_url(&website_conf.base, &path, port).expect("reading config"); let url = get_url(&website_conf.base, &path, port).expect("reading config");
let ping_start = Utc::now();
let ping_result = client.get(&url).send(); let ping_result = client.get(&url).send();
let rtt = Utc::now() - ping_start;
let rtt_string = if rtt.num_seconds() > 0 {
format!("{}s", rtt.num_milliseconds() as f64 / 1000.)
} else {
format!("{}ms", rtt.num_milliseconds())
};
match ping_result { match ping_result {
Ok(mut res) => { Ok(mut res) => {
@ -67,42 +59,45 @@ fn get_result(
let mut error = None; let mut error = None;
if res.status() != code { if res.status() != code {
error = append_err_msg( error = Some(format!(
error, "Status code mismatch: {} != {}.",
format!( res.status().as_u16(),
"Status code mismatch: {} != {}.", code
res.status().as_u16(), ));
code
),
);
} }
if let Some(expected_hash) = &endpoint.body_hash { if let Some(expected_hash) = &endpoint.body_hash {
let expected = from_hex(expected_hash).unwrap(); let expected = from_hex(expected_hash).unwrap();
let actual = digest(&SHA256, String::from(res_body).as_bytes()); let actual = digest(&SHA256, String::from(res_body).as_bytes());
if &expected != &actual.as_ref() { if &expected != &actual.as_ref() {
error = append_err_msg(error, String::from("Body hash mismatch.")); error = Some(if let Some(msg) = error {
format!("{} Body hash mismatch.", msg)
} else {
String::from("Body hash mismatch.")
});
} }
} else if !body.is_empty() && res_body != body { } else if !body.is_empty() && res_body != body {
error = append_err_msg( error = Some(if let Some(msg) = error {
error, format!(
format!("Body mismatch: {} != {}.", res_body.len(), body.len()), "{} Body mismatch: {} != {}.",
); msg,
} res_body.len(),
body.len()
if rtt.num_seconds() >= 2 { )
error = append_err_msg(error, format!("RTT too long: {}", rtt_string)); } else {
format!("Body mismatch: {} != {}.", res_body.len(), body.len())
});
} }
if error.is_some() { if error.is_some() {
EndpointStatus::warn(url, label, rtt_string, error) EndpointStatus::warn(url, label, error)
} else { } else {
EndpointStatus::ok(url, label, rtt_string) EndpointStatus::ok(url, label)
} }
} }
Err(e) => { Err(e) => {
if let Some(true) = endpoint.should_err { if let Some(true) = endpoint.should_err {
EndpointStatus::ok(url, label, rtt_string) EndpointStatus::ok(url, label)
} else { } else {
EndpointStatus::error(url, label, Some(format!("{}", e))) EndpointStatus::error(url, label, Some(format!("{}", e)))
} }
@ -121,14 +116,3 @@ fn get_url(base: &Option<String>, path: &String, port: Option<u16>) -> Result<St
} }
Ok(url.into_string()) Ok(url.into_string())
} }
fn append_err_msg(optional: Option<String>, to_append: String) -> Option<String> {
// Turns out Rust doesn't recognize that only one of the FnOnce occurs, so
// as a result both closures want ownership of to_append
// Some(optional.map_or_else(|| to_append, |msg| format!("{} {}", msg, to_append)))
Some(match optional {
Some(e) => format!("{} {}", e, to_append),
None => to_append,
})
}