mirror of
https://github.com/deps-rs/deps.rs.git
synced 2024-11-21 18:06:30 +00:00
replace lazy-static with once-cell
This commit is contained in:
parent
1d5fdd5dc5
commit
63a8355543
5 changed files with 190 additions and 131 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1249,7 +1249,6 @@ dependencies = [
|
|||
"hyper 0.11.27",
|
||||
"hyper-tls",
|
||||
"indexmap",
|
||||
"lazy_static 1.4.0",
|
||||
"lru-cache",
|
||||
"maud",
|
||||
"once_cell",
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Route>>
|
||||
router: Arc<Router<Route>>,
|
||||
}
|
||||
|
||||
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<dyn Future<Item=Response, Error=HyperError>>;
|
||||
type Future = Box<dyn Future<Item = Response, Error = HyperError>>;
|
||||
|
||||
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<Item=Response, Error=HyperError>
|
||||
{
|
||||
self.engine.get_popular_repos()
|
||||
fn index(
|
||||
&self,
|
||||
_req: Request,
|
||||
_params: Params,
|
||||
logger: Logger,
|
||||
) -> impl Future<Item = Response, Error = HyperError> {
|
||||
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<Item=Response, Error=HyperError>
|
||||
{
|
||||
fn repo_status(
|
||||
&self,
|
||||
_req: Request,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
format: StatusFormat,
|
||||
) -> impl Future<Item = Response, Error = HyperError> {
|
||||
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<Item=Response, Error=HyperError>
|
||||
{
|
||||
fn crate_redirect(
|
||||
&self,
|
||||
_req: Request,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
) -> impl Future<Item = Response, Error = HyperError> {
|
||||
let engine = self.engine.clone();
|
||||
|
||||
let name = params.find("name").expect("route param 'name' not found");
|
||||
|
||||
name.parse::<CrateName>().into_future().then(move |crate_name_result| {
|
||||
match crate_name_result {
|
||||
name.parse::<CrateName>()
|
||||
.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<Item=Response, Error=HyperError>
|
||||
{
|
||||
fn crate_status(
|
||||
&self,
|
||||
_req: Request,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
format: StatusFormat,
|
||||
) -> impl Future<Item = Response, Error = HyperError> {
|
||||
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<AnalyzeDependenciesOutcome>, format: StatusFormat, subject_path: SubjectPath) -> Response {
|
||||
fn status_format_analysis(
|
||||
analysis_outcome: Option<AnalyzeDependenciesOutcome>,
|
||||
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<String> =
|
||||
Lazy::new(|| env::var("BASE_URL").unwrap_or_else(|_| "http://localhost:8080".to_string()));
|
||||
|
|
|
@ -24,7 +24,7 @@ impl<S> Debug for Cache<S>
|
|||
where S: Service<Error=Error> + 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<F> Debug for Cached<F>
|
|||
where F: Future<Error=Error> + Debug,
|
||||
F::Item: Debug
|
||||
{
|
||||
fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
|
||||
self.0.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue