add barebones error states

This commit is contained in:
Sam Rijs 2018-02-06 21:09:43 +11:00
parent c26c8dbcec
commit da700e8095
6 changed files with 40 additions and 19 deletions

View file

@ -69,7 +69,7 @@ fn main() {
let engine = Engine::new(client.clone(), logger.clone()); let engine = Engine::new(client.clone(), logger.clone());
let server = Server::new(engine); let server = Server::new(logger.clone(), engine);
let serve = http.serve_addr_handle(&addr, &handle, move || Ok(server.clone())) let serve = http.serve_addr_handle(&addr, &handle, move || Ok(server.clone()))
.expect("failed to bind server"); .expect("failed to bind server");

View file

@ -34,12 +34,13 @@ enum Route {
#[derive(Clone)] #[derive(Clone)]
pub struct Server { pub struct Server {
logger: Logger,
engine: Engine, engine: Engine,
router: Arc<Router<Route>> router: Arc<Router<Route>>
} }
impl Server { impl Server {
pub fn new(engine: Engine) -> Server { pub fn new(logger: Logger, engine: Engine) -> Server {
let mut router = Router::new(); let mut router = Router::new();
router.add("/", Route::Index); router.add("/", Route::Index);
@ -51,7 +52,7 @@ impl Server {
router.add("/repo/:site/:qual/:name/status.json", Route::Status(StatusFormat::Json)); router.add("/repo/:site/:qual/:name/status.json", Route::Status(StatusFormat::Json));
router.add("/repo/:site/:qual/:name/status.svg", Route::Status(StatusFormat::Svg)); router.add("/repo/:site/:qual/:name/status.svg", Route::Status(StatusFormat::Svg));
Server { engine, router: Arc::new(router) } Server { logger, engine, router: Arc::new(router) }
} }
} }
@ -62,16 +63,18 @@ impl Service for Server {
type Future = Box<Future<Item=Response, Error=HyperError>>; type Future = Box<Future<Item=Response, Error=HyperError>>;
fn call(&self, req: Request) -> Self::Future { fn call(&self, req: Request) -> Self::Future {
let logger = self.logger.new(o!("http_path" => req.uri().path().to_owned()));
if let Ok(route_match) = self.router.recognize(req.uri().path()) { if let Ok(route_match) = self.router.recognize(req.uri().path()) {
match route_match.handler { match route_match.handler {
&Route::Index => { &Route::Index => {
if *req.method() == Method::Get { if *req.method() == Method::Get {
return Box::new(self.index(req, route_match.params)); return Box::new(self.index(req, route_match.params, logger));
} }
}, },
&Route::Status(format) => { &Route::Status(format) => {
if *req.method() == Method::Get { if *req.method() == Method::Get {
return Box::new(self.status(req, route_match.params, format)); return Box::new(self.status(req, route_match.params, logger, format));
} }
}, },
&Route::Static(file) => { &Route::Static(file) => {
@ -90,15 +93,15 @@ impl Service for Server {
} }
impl Server { impl Server {
fn index(&self, _req: Request, _params: Params) -> fn index(&self, _req: Request, _params: Params, logger: Logger) ->
impl Future<Item=Response, Error=HyperError> impl Future<Item=Response, Error=HyperError>
{ {
self.engine.get_popular_repos().then(|popular_result| { self.engine.get_popular_repos().then(move |popular_result| {
match popular_result { match popular_result {
Err(err) => { Err(err) => {
let mut response = Response::new(); error!(logger, "error: {}", err);
response.set_status(StatusCode::BadRequest); let mut response = views::html::error::render("Could not retrieve popular repositories", "");
response.set_body(format!("Error: {}", err)); response.set_status(StatusCode::InternalServerError);
future::ok(response) future::ok(response)
}, },
Ok(popular) => Ok(popular) =>
@ -107,7 +110,7 @@ impl Server {
}) })
} }
fn status(&self, _req: Request, params: Params, format: StatusFormat) -> fn status(&self, _req: Request, params: Params, logger: Logger, format: StatusFormat) ->
impl Future<Item=Response, Error=HyperError> impl Future<Item=Response, Error=HyperError>
{ {
let server = self.clone(); let server = self.clone();
@ -119,9 +122,9 @@ impl Server {
RepoPath::from_parts(site, qual, name).into_future().then(move |repo_path_result| { RepoPath::from_parts(site, qual, name).into_future().then(move |repo_path_result| {
match repo_path_result { match repo_path_result {
Err(err) => { Err(err) => {
let mut response = Response::new(); error!(logger, "error: {}", err);
let mut response = views::html::error::render("Could not parse repository URL", "");
response.set_status(StatusCode::BadRequest); response.set_status(StatusCode::BadRequest);
response.set_body(format!("Error: {}", err));
future::Either::A(future::ok(response)) future::Either::A(future::ok(response))
}, },
Ok(repo_path) => { Ok(repo_path) => {
@ -129,9 +132,10 @@ impl Server {
match analyze_result { match analyze_result {
Err(err) => { Err(err) => {
if format != StatusFormat::Svg { if format != StatusFormat::Svg {
let mut response = Response::new(); error!(logger, "error: {}", err);
response.set_status(StatusCode::BadRequest); let mut response = views::html::error::render("Failed to analyze repository",
response.set_body(format!("Error: {}", err)); "The repository you requested might be structured in an uncommon way that is not yet supported.");
response.set_status(StatusCode::InternalServerError);
future::Either::A(future::ok(response)) future::Either::A(future::ok(response))
} else { } else {
future::Either::A(future::ok(views::status_svg(None))) future::Either::A(future::ok(views::status_svg(None)))

View file

@ -0,0 +1,16 @@
use hyper::Response;
use maud::html;
pub fn render(title: &str, descr: &str) -> Response {
super::render_html(title, html! {
section class="hero is-light" {
div class="hero-head" (super::render_navbar())
div class="hero-body" {
div class="container" {
p class="title is-1" (title)
p (descr)
}
}
}
})
}

View file

@ -33,7 +33,7 @@ fn popular_table(popular: Vec<Repository>) -> Markup {
} }
pub fn render(popular: Vec<Repository>) -> Response { pub fn render(popular: Vec<Repository>) -> Response {
super::render_html("Keep your dependencies up-to-date - Deps.rs", html! { super::render_html("Keep your dependencies up-to-date", html! {
section class="hero is-light" { section class="hero is-light" {
div class="hero-head" (super::render_navbar()) div class="hero-head" (super::render_navbar())
div class="hero-body" { div class="hero-body" {

View file

@ -5,6 +5,7 @@ use hyper::header::ContentType;
use maud::{Markup, Render, html}; use maud::{Markup, Render, html};
pub mod index; pub mod index;
pub mod error;
pub mod status; pub mod status;
lazy_static! { lazy_static! {
@ -20,7 +21,7 @@ fn render_html<B: Render>(title: &str, body: B) -> Response {
head { head {
meta charset="utf-8"; meta charset="utf-8";
meta name="viewport" content="width=device-width, initial-scale=1"; meta name="viewport" content="width=device-width, initial-scale=1";
title (title) title (format!("{} - Deps.rs", title))
link rel="icon" type="image/png" href="/static/favicon.png"; link rel="icon" type="image/png" href="/static/favicon.png";
link rel="stylesheet" type="text/css" href="/static/style.css"; link rel="stylesheet" type="text/css" href="/static/style.css";
link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Fira+Sans:400,500,600"; link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Fira+Sans:400,500,600";

View file

@ -63,7 +63,7 @@ fn dependency_table(title: &str, deps: BTreeMap<CrateName, AnalyzedDependency>)
pub fn render(analysis_outcome: AnalyzeDependenciesOutcome, repo_path: RepoPath) -> Response { pub fn render(analysis_outcome: AnalyzeDependenciesOutcome, repo_path: RepoPath) -> Response {
let self_path = format!("repo/{}/{}/{}", repo_path.site.as_ref(), repo_path.qual.as_ref(), repo_path.name.as_ref()); let self_path = format!("repo/{}/{}/{}", repo_path.site.as_ref(), repo_path.qual.as_ref(), repo_path.name.as_ref());
let status_base_url = format!("{}/{}", &super::SELF_BASE_URL as &str, self_path); let status_base_url = format!("{}/{}", &super::SELF_BASE_URL as &str, self_path);
let title = format!("{} / {} - Deps.rs", repo_path.qual.as_ref(), repo_path.name.as_ref()); let title = format!("{} / {}", repo_path.qual.as_ref(), repo_path.name.as_ref());
let (hero_class, status_asset) = if analysis_outcome.deps.any_outdated() { let (hero_class, status_asset) = if analysis_outcome.deps.any_outdated() {
("is-warning", assets::BADGE_OUTDATED_SVG.as_ref()) ("is-warning", assets::BADGE_OUTDATED_SVG.as_ref())