diff --git a/src/api.rs b/src/api.rs index 08a9ac9..7b91c36 100644 --- a/src/api.rs +++ b/src/api.rs @@ -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 { + fn status<'r>(&self, _req: Request, params: Params, format: StatusFormat) -> + impl Future + { 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 { - 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 } - }) + } } } \ No newline at end of file