diff --git a/Cargo.lock b/Cargo.lock index 1006bff..6e65ac9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1249,7 +1249,6 @@ dependencies = [ "hyper 0.11.27", "hyper-tls", "indexmap", - "lazy_static 1.4.0", "lru-cache", "maud", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 580a662..c2ff028 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,9 @@ futures = "0.1.18" hyper = "0.11.15" hyper-tls = "0.1.2" indexmap = { version = "1.0.0", features = ["serde-1"] } -lazy_static = "1.0.0" lru-cache = "0.1.1" maud = "0.22" +once_cell = "1.4" relative-path = { version = "0.3.7", features = ["serde"] } route-recognizer = "0.1.12" rustsec = "0.6.0" @@ -36,7 +36,6 @@ tokio-core = "0.1.12" tokio-service = "0.1.0" toml = "0.4.5" try_future = "0.1.1" -once_cell = "1.4" [build-dependencies] diff --git a/src/main.rs b/src/main.rs index c09076f..0f93a0e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,8 @@ -#![deny(bare_trait_objects)] -#![allow(unused)] +#![deny(rust_2018_idioms)] #[macro_use] extern crate failure; #[macro_use] -extern crate lazy_static; -#[macro_use] extern crate serde_derive; #[macro_use] extern crate slog; diff --git a/src/server/mod.rs b/src/server/mod.rs index e9ccc7d..f9b9f65 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,9 +1,10 @@ use std::env; use std::sync::Arc; -use futures::{Future, IntoFuture, future}; -use hyper::{Error as HyperError, Method, Request, Response, StatusCode}; +use futures::{future, Future, IntoFuture}; use hyper::header::{ContentType, Location}; +use hyper::{Error as HyperError, Method, Request, Response, StatusCode}; +use once_cell::sync::Lazy; use route_recognizer::{Params, Router}; use semver::VersionReq; use slog::Logger; @@ -12,7 +13,7 @@ use tokio_service::Service; mod assets; mod views; -use crate::engine::{Engine, AnalyzeDependenciesOutcome}; +use crate::engine::{AnalyzeDependenciesOutcome, Engine}; use crate::models::crates::{CrateName, CratePath}; use crate::models::repo::RepoPath; use crate::models::SubjectPath; @@ -20,13 +21,13 @@ use crate::models::SubjectPath; #[derive(Clone, Copy, PartialEq)] enum StatusFormat { Html, - Svg + Svg, } #[derive(Clone, Copy)] enum StaticFile { StyleCss, - FaviconPng + FaviconPng, } enum Route { @@ -34,14 +35,14 @@ enum Route { Static(StaticFile), RepoStatus(StatusFormat), CrateRedirect, - CrateStatus(StatusFormat) + CrateStatus(StatusFormat), } #[derive(Clone)] pub struct Server { logger: Logger, engine: Engine, - router: Arc> + router: Arc>, } impl Server { @@ -53,14 +54,30 @@ impl Server { router.add("/static/style.css", Route::Static(StaticFile::StyleCss)); router.add("/static/favicon.png", Route::Static(StaticFile::FaviconPng)); - router.add("/repo/:site/:qual/:name", Route::RepoStatus(StatusFormat::Html)); - router.add("/repo/:site/:qual/:name/status.svg", Route::RepoStatus(StatusFormat::Svg)); + router.add( + "/repo/:site/:qual/:name", + Route::RepoStatus(StatusFormat::Html), + ); + router.add( + "/repo/:site/:qual/:name/status.svg", + Route::RepoStatus(StatusFormat::Svg), + ); router.add("/crate/:name", Route::CrateRedirect); - router.add("/crate/:name/:version", Route::CrateStatus(StatusFormat::Html)); - router.add("/crate/:name/:version/status.svg", Route::CrateStatus(StatusFormat::Svg)); + router.add( + "/crate/:name/:version", + Route::CrateStatus(StatusFormat::Html), + ); + router.add( + "/crate/:name/:version/status.svg", + Route::CrateStatus(StatusFormat::Svg), + ); - Server { logger, engine, router: Arc::new(router) } + Server { + logger, + engine, + router: Arc::new(router), + } } } @@ -68,10 +85,12 @@ impl Service for Server { type Request = Request; type Response = Response; type Error = HyperError; - type Future = Box>; + type Future = Box>; fn call(&self, req: Request) -> Self::Future { - let logger = self.logger.new(o!("http_path" => req.uri().path().to_owned())); + let logger = self + .logger + .new(o!("http_path" => req.uri().path().to_owned())); if let Ok(route_match) = self.router.recognize(req.uri().path()) { match route_match.handler { @@ -79,28 +98,32 @@ impl Service for Server { if *req.method() == Method::Get { return Box::new(self.index(req, route_match.params, logger)); } - }, + } &Route::RepoStatus(format) => { if *req.method() == Method::Get { return Box::new(self.repo_status(req, route_match.params, logger, format)); } - }, + } &Route::CrateStatus(format) => { if *req.method() == Method::Get { - return Box::new(self.crate_status(req, route_match.params, logger, format)); + return Box::new(self.crate_status( + req, + route_match.params, + logger, + format, + )); } - }, + } &Route::CrateRedirect => { if *req.method() == Method::Get { return Box::new(self.crate_redirect(req, route_match.params, logger)); } - }, + } &Route::Static(file) => { if *req.method() == Method::Get { return Box::new(future::ok(Server::static_file(file))); } } - } } @@ -111,175 +134,216 @@ impl Service for Server { } impl Server { - fn index(&self, _req: Request, _params: Params, logger: Logger) -> - impl Future - { - self.engine.get_popular_repos() + fn index( + &self, + _req: Request, + _params: Params, + logger: Logger, + ) -> impl Future { + self.engine + .get_popular_repos() .join(self.engine.get_popular_crates()) - .then(move |popular_result| { - match popular_result { - Err(err) => { - error!(logger, "error: {}", err); - let mut response = views::html::error::render("Could not retrieve popular items", ""); - response.set_status(StatusCode::InternalServerError); - future::ok(response) - }, - Ok((popular_repos, popular_crates)) => - future::ok(views::html::index::render(popular_repos, popular_crates)) + .then(move |popular_result| match popular_result { + Err(err) => { + error!(logger, "error: {}", err); + let mut response = + views::html::error::render("Could not retrieve popular items", ""); + response.set_status(StatusCode::InternalServerError); + future::ok(response) + } + Ok((popular_repos, popular_crates)) => { + future::ok(views::html::index::render(popular_repos, popular_crates)) } }) } - fn repo_status(&self, _req: Request, params: Params, logger: Logger, format: StatusFormat) -> - impl Future - { + fn repo_status( + &self, + _req: Request, + params: Params, + logger: Logger, + format: StatusFormat, + ) -> impl Future { let server = self.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 { + RepoPath::from_parts(site, qual, name) + .into_future() + .then(move |repo_path_result| match repo_path_result { Err(err) => { error!(logger, "error: {}", err); - let mut response = views::html::error::render("Could not parse repository path", - "Please make sure to provide a valid repository path."); + let mut response = views::html::error::render( + "Could not parse repository path", + "Please make sure to provide a valid repository path.", + ); response.set_status(StatusCode::BadRequest); future::Either::A(future::ok(response)) - }, - Ok(repo_path) => { - future::Either::B(server.engine.analyze_repo_dependencies(repo_path.clone()).then(move |analyze_result| { - match analyze_result { + } + Ok(repo_path) => future::Either::B( + server + .engine + .analyze_repo_dependencies(repo_path.clone()) + .then(move |analyze_result| match analyze_result { Err(err) => { error!(logger, "error: {}", err); - let response = Server::status_format_analysis(None, format, SubjectPath::Repo(repo_path)); - future::ok(response) - }, - Ok(analysis_outcome) => { - let response = Server::status_format_analysis(Some(analysis_outcome), format, SubjectPath::Repo(repo_path)); + let response = Server::status_format_analysis( + None, + format, + SubjectPath::Repo(repo_path), + ); future::ok(response) } - } - })) - } - } - }) + Ok(analysis_outcome) => { + let response = Server::status_format_analysis( + Some(analysis_outcome), + format, + SubjectPath::Repo(repo_path), + ); + future::ok(response) + } + }), + ), + }) } - fn crate_redirect(&self, _req: Request, params: Params, logger: Logger) -> - impl Future - { + fn crate_redirect( + &self, + _req: Request, + params: Params, + logger: Logger, + ) -> impl Future { let engine = self.engine.clone(); let name = params.find("name").expect("route param 'name' not found"); - name.parse::().into_future().then(move |crate_name_result| { - match crate_name_result { + name.parse::() + .into_future() + .then(move |crate_name_result| match crate_name_result { Err(err) => { error!(logger, "error: {}", err); - let mut response = views::html::error::render("Could not parse crate name", - "Please make sure to provide a valid crate name."); + let mut response = views::html::error::render( + "Could not parse crate name", + "Please make sure to provide a valid crate name.", + ); response.set_status(StatusCode::BadRequest); future::Either::A(future::ok(response)) - }, - Ok(crate_name) => { - future::Either::B(engine.find_latest_crate_release(crate_name, VersionReq::any()).then(move |release_result| { - match release_result { + } + Ok(crate_name) => future::Either::B( + engine + .find_latest_crate_release(crate_name, VersionReq::any()) + .then(move |release_result| match release_result { Err(err) => { error!(logger, "error: {}", err); - let mut response = views::html::error::render("Could not fetch crate information", - "Please make sure to provide a valid crate name."); + let mut response = views::html::error::render( + "Could not fetch crate information", + "Please make sure to provide a valid crate name.", + ); response.set_status(StatusCode::NotFound); future::ok(response) - }, + } Ok(None) => { - let mut response = views::html::error::render("Could not fetch crate information", - "Please make sure to provide a valid crate name."); + let mut response = views::html::error::render( + "Could not fetch crate information", + "Please make sure to provide a valid crate name.", + ); response.set_status(StatusCode::NotFound); future::ok(response) - }, + } Ok(Some(release)) => { let mut response = Response::new(); response.set_status(StatusCode::TemporaryRedirect); - let url = format!("{}/crate/{}/{}", + let url = format!( + "{}/crate/{}/{}", &SELF_BASE_URL as &str, release.name.as_ref(), - release.version); + release.version + ); response.headers_mut().set(Location::new(url)); future::ok(response) } - } - })) - } - } - }) + }), + ), + }) } - fn crate_status(&self, _req: Request, params: Params, logger: Logger, format: StatusFormat) -> - impl Future - { + fn crate_status( + &self, + _req: Request, + params: Params, + logger: Logger, + format: StatusFormat, + ) -> impl Future { let server = self.clone(); let name = params.find("name").expect("route param 'name' not found"); - let version = params.find("version").expect("route param 'version' not found"); + let version = params + .find("version") + .expect("route param 'version' not found"); - CratePath::from_parts(name, version).into_future().then(move |crate_path_result| { - match crate_path_result { + CratePath::from_parts(name, version) + .into_future() + .then(move |crate_path_result| match crate_path_result { Err(err) => { error!(logger, "error: {}", err); - let mut response = views::html::error::render("Could not parse crate path", - "Please make sure to provide a valid crate name and version."); + let mut response = views::html::error::render( + "Could not parse crate path", + "Please make sure to provide a valid crate name and version.", + ); response.set_status(StatusCode::BadRequest); future::Either::A(future::ok(response)) - }, - Ok(crate_path) => { - future::Either::B(server.engine.analyze_crate_dependencies(crate_path.clone()).then(move |analyze_result| { - match analyze_result { + } + Ok(crate_path) => future::Either::B( + server + .engine + .analyze_crate_dependencies(crate_path.clone()) + .then(move |analyze_result| match analyze_result { Err(err) => { error!(logger, "error: {}", err); - let response = Server::status_format_analysis(None, format, SubjectPath::Crate(crate_path)); - future::ok(response) - }, - Ok(analysis_outcome) => { - let response = Server::status_format_analysis(Some(analysis_outcome), format, SubjectPath::Crate(crate_path)); + let response = Server::status_format_analysis( + None, + format, + SubjectPath::Crate(crate_path), + ); future::ok(response) } - } - })) - } - } - }) + Ok(analysis_outcome) => { + let response = Server::status_format_analysis( + Some(analysis_outcome), + format, + SubjectPath::Crate(crate_path), + ); + future::ok(response) + } + }), + ), + }) } - fn status_format_analysis(analysis_outcome: Option, format: StatusFormat, subject_path: SubjectPath) -> Response { + fn status_format_analysis( + analysis_outcome: Option, + format: StatusFormat, + subject_path: SubjectPath, + ) -> Response { match format { - StatusFormat::Svg => - views::badge::response(analysis_outcome.as_ref()), - StatusFormat::Html => - views::html::status::render(analysis_outcome, subject_path) + StatusFormat::Svg => views::badge::response(analysis_outcome.as_ref()), + StatusFormat::Html => views::html::status::render(analysis_outcome, subject_path), } } fn static_file(file: StaticFile) -> Response { match file { - StaticFile::StyleCss => { - Response::new() - .with_header(ContentType("text/css".parse().unwrap())) - .with_body(assets::STATIC_STYLE_CSS) - }, - StaticFile::FaviconPng => { - Response::new() - .with_header(ContentType("image/png".parse().unwrap())) - .with_body(assets::STATIC_FAVICON_PNG.to_vec()) - } + StaticFile::StyleCss => Response::new() + .with_header(ContentType("text/css".parse().unwrap())) + .with_body(assets::STATIC_STYLE_CSS), + StaticFile::FaviconPng => Response::new() + .with_header(ContentType("image/png".parse().unwrap())) + .with_body(assets::STATIC_FAVICON_PNG.to_vec()), } } } -lazy_static! { - static ref SELF_BASE_URL: String = { - env::var("BASE_URL") - .unwrap_or_else(|_| "http://localhost:8080".to_string()) - }; -} +static SELF_BASE_URL: Lazy = + Lazy::new(|| env::var("BASE_URL").unwrap_or_else(|_| "http://localhost:8080".to_string())); diff --git a/src/utils/cache.rs b/src/utils/cache.rs index d09ebf3..80303fe 100644 --- a/src/utils/cache.rs +++ b/src/utils/cache.rs @@ -24,7 +24,7 @@ impl Debug for Cache where S: Service + Debug, S::Request: Hash + Eq { - fn fmt(&self, fmt: &mut Formatter) -> FmtResult { + fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult { fmt.debug_struct("Cache") .field("inner", &self.inner) .field("duration", &self.duration) @@ -76,7 +76,7 @@ impl Debug for Cached where F: Future + Debug, F::Item: Debug { - fn fmt(&self, fmt: &mut Formatter) -> FmtResult { + fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult { self.0.fmt(fmt) } }