refactor status reporting

This commit is contained in:
Sam Rijs 2018-01-27 12:50:22 +11:00
parent adab7fdf74
commit 9dbc9c925c

View file

@ -11,12 +11,17 @@ use slog::Logger;
use tokio_service::Service;
use ::assets;
use ::engine::Engine;
use ::engine::{Engine, AnalyzeDependenciesOutcome};
use ::models::repo::RepoPath;
#[derive(Clone, Copy)]
enum StatusFormat {
Json,
Svg
}
enum Route {
StatusJson,
StatusSvg
Status(StatusFormat)
}
#[derive(Clone)]
@ -28,8 +33,8 @@ pub struct Api {
impl Api {
pub fn new(engine: Engine) -> Api {
let mut router = Router::new();
router.add("/repo/:site/:qual/:name/status.json", Route::StatusJson);
router.add("/repo/:site/:qual/:name/status.svg", Route::StatusSvg);
router.add("/repo/:site/:qual/:name/status.json", Route::Status(StatusFormat::Json));
router.add("/repo/:site/:qual/:name/status.svg", Route::Status(StatusFormat::Svg));
Api { engine, router: Arc::new(router) }
}
@ -65,14 +70,9 @@ impl Service for Api {
fn call(&self, req: Request) -> Self::Future {
if let Ok(route_match) = self.router.recognize(req.uri().path()) {
match route_match.handler {
&Route::StatusJson => {
&Route::Status(format) => {
if *req.method() == Method::Get {
return Box::new(self.status_json(req, route_match.params));
}
},
&Route::StatusSvg => {
if *req.method() == Method::Get {
return Box::new(self.status_svg(req, route_match.params));
return Box::new(self.status(req, route_match.params, format));
}
}
}
@ -85,7 +85,9 @@ impl Service for Api {
}
impl Api {
fn status_json<'r>(&self, _req: Request, params: Params) -> impl Future<Item=Response, Error=HyperError> {
fn status<'r>(&self, _req: Request, params: Params, format: StatusFormat) ->
impl Future<Item=Response, Error=HyperError>
{
let engine = self.engine.clone();
let site = params.find("site").expect("route param 'site' not found");
@ -101,7 +103,7 @@ impl Api {
future::Either::A(future::ok(response))
},
Ok(repo_path) => {
future::Either::B(engine.analyze_dependencies(repo_path).then(|analyze_result| {
future::Either::B(engine.analyze_dependencies(repo_path).then(move |analyze_result| {
match analyze_result {
Err(err) => {
let mut response = Response::new();
@ -110,32 +112,7 @@ impl Api {
future::Either::A(future::ok(response))
},
Ok(analysis_outcome) => {
let single = AnalyzeDependenciesResponseSingle {
dependencies: analysis_outcome.deps.main.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
dev_dependencies: analysis_outcome.deps.dev.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
build_dependencies: analysis_outcome.deps.build.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect()
};
let multi = AnalyzeDependenciesResponse {
crates: vec![(analysis_outcome.name.into(), single)].into_iter().collect()
};
let mut response = Response::new()
.with_header(ContentType::json())
.with_body(serde_json::to_string(&multi).unwrap());
let response = Api::status_format_analysis(analysis_outcome, format);
future::Either::B(future::ok(response))
}
}
@ -145,44 +122,46 @@ impl Api {
})
}
fn status_svg<'r>(&self, _req: Request, params: Params) -> impl Future<Item=Response, Error=HyperError> {
let engine = self.engine.clone();
let site = params.find("site").expect("route param 'site' not found");
let qual = params.find("qual").expect("route param 'qual' not found");
let name = params.find("name").expect("route param 'name' not found");
RepoPath::from_parts(site, qual, name).into_future().then(move |repo_path_result| {
match repo_path_result {
Err(err) => {
let mut response = Response::new();
response.set_status(StatusCode::BadRequest);
response.set_body(format!("{:?}", err));
future::Either::A(future::ok(response))
},
Ok(repo_path) => {
future::Either::B(engine.analyze_dependencies(repo_path).then(|analyze_result| {
match analyze_result {
Err(err) => {
let mut response = Response::new();
response.set_status(StatusCode::InternalServerError);
response.set_body(format!("{:?}", err));
future::Either::A(future::ok(response))
},
Ok(analysis_outcome) => {
let mut response = Response::new()
.with_header(ContentType("image/svg+xml;charset=utf-8".parse().unwrap()));
if analysis_outcome.deps.any_outdated() {
response.set_body(assets::BADGE_OUTDATED_SVG.to_vec());
} else {
response.set_body(assets::BADGE_UPTODATE_SVG.to_vec());
}
future::Either::B(future::ok(response))
}
}
}))
fn status_format_analysis(analysis_outcome: AnalyzeDependenciesOutcome, format: StatusFormat) -> Response {
match format {
StatusFormat::Json => {
let single = AnalyzeDependenciesResponseSingle {
dependencies: analysis_outcome.deps.main.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
dev_dependencies: analysis_outcome.deps.dev.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
build_dependencies: analysis_outcome.deps.build.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect()
};
let multi = AnalyzeDependenciesResponse {
crates: vec![(analysis_outcome.name.into(), single)].into_iter().collect()
};
Response::new()
.with_header(ContentType::json())
.with_body(serde_json::to_string(&multi).unwrap())
},
StatusFormat::Svg => {
let mut response = Response::new()
.with_header(ContentType("image/svg+xml;charset=utf-8".parse().unwrap()));
if analysis_outcome.deps.any_outdated() {
response.set_body(assets::BADGE_OUTDATED_SVG.to_vec());
} else {
response.set_body(assets::BADGE_UPTODATE_SVG.to_vec());
}
response
}
})
}
}
}