From 13e12d54993b37ecbb8a5c8618220ce5c13f3ac2 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Fri, 12 Aug 2016 16:53:15 -0400 Subject: [PATCH 1/3] Extract a method for incrementing the download counts --- src/krate.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/krate.rs b/src/krate.rs index fac3625f01f..4b3d7926e76 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -827,6 +827,22 @@ fn read_fill(r: &mut R, mut slice: &mut [u8]) pub fn download(req: &mut Request) -> CargoResult { let crate_name = &req.params()["crate_id"]; let version = &req.params()["version"]; + + try!(increment_download_counts(req, crate_name, version)); + let redirect_url = format!("https://{}/crates/{}/{}-{}.crate", + req.app().bucket.host(), + crate_name, crate_name, version); + + if req.wants_json() { + #[derive(RustcEncodable)] + struct R { url: String } + Ok(req.json(&R{ url: redirect_url })) + } else { + Ok(req.redirect(redirect_url)) + } +} + +fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> CargoResult<()> { let tx = try!(req.tx()); let stmt = try!(tx.prepare("SELECT versions.id as version_id FROM crates @@ -836,7 +852,7 @@ pub fn download(req: &mut Request) -> CargoResult { canon_crate_name($1) AND versions.num = $2 LIMIT 1")); - let rows = try!(stmt.query(&[crate_name, version])); + let rows = try!(stmt.query(&[&crate_name, &version])); let row = try!(rows.iter().next().chain_error(|| { human("crate or version not found") })); @@ -862,19 +878,7 @@ pub fn download(req: &mut Request) -> CargoResult { try!(tx.execute("INSERT INTO version_downloads (version_id) VALUES ($1)", &[&version_id])); } - - // Now that we've done our business, redirect to the actual data. - let redirect_url = format!("https://{}/crates/{}/{}-{}.crate", - req.app().bucket.host(), - crate_name, crate_name, version); - - if req.wants_json() { - #[derive(RustcEncodable)] - struct R { url: String } - Ok(req.json(&R{ url: redirect_url })) - } else { - Ok(req.redirect(redirect_url)) - } + Ok(()) } /// Handles the `GET /crates/:crate_id/downloads` route. From a28e79c619fb7036c400423954bbd309e0770042 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 23 Aug 2016 20:49:06 -0400 Subject: [PATCH 2/3] Add an env var setting for whether we are a mirror or not By default, we are not a mirror. --- .env.sample | 3 +++ src/bin/fill-in-user-id.rs | 1 + src/bin/server.rs | 1 + src/config.rs | 1 + src/tests/all.rs | 1 + 5 files changed, 7 insertions(+) diff --git a/.env.sample b/.env.sample index e292f69fbc8..a2bfa74b844 100644 --- a/.env.sample +++ b/.env.sample @@ -3,6 +3,9 @@ # `postgres://postgres:@localhost/cargo_registry`. export DATABASE_URL="" +# If you are running a mirror of crates.io, uncomment this line. +# export MIRROR=1 + # Key to sign and encrypt cookies with. Change this to a long, random string # for production. export SESSION_KEY="badkey" diff --git a/src/bin/fill-in-user-id.rs b/src/bin/fill-in-user-id.rs index df3a17a0588..7a522755866 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -33,6 +33,7 @@ fn main() { db_url: env("DATABASE_URL"), env: cargo_registry::Env::Production, max_upload_size: 0, + mirror: false, }; let app = cargo_registry::App::new(&config); { diff --git a/src/bin/server.rs b/src/bin/server.rs index 3c6ebd2c134..bf0749d65e4 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -57,6 +57,7 @@ fn main() { db_url: env("DATABASE_URL"), env: cargo_env, max_upload_size: 10 * 1024 * 1024, + mirror: env::var("MIRROR").is_ok(), }; let app = cargo_registry::App::new(&config); let app = cargo_registry::middleware(Arc::new(app)); diff --git a/src/config.rs b/src/config.rs index 32833d5653f..76483c58321 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,7 @@ pub struct Config { pub db_url: String, pub env: ::Env, pub max_upload_size: u64, + pub mirror: bool, } impl Config { diff --git a/src/tests/all.rs b/src/tests/all.rs index e5122359fd2..10fd5609a31 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -90,6 +90,7 @@ fn app() -> (record::Bomb, Arc, conduit_middleware::MiddlewareBuilder) { db_url: env("TEST_DATABASE_URL"), env: cargo_registry::Env::Test, max_upload_size: 1000, + mirror: false, }; INIT.call_once(|| db_setup(&config.db_url)); let app = App::new(&config); From 4a7d2703d71acbfb25ac05c3fb9d3a5df0b9e693 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 23 Aug 2016 20:59:40 -0400 Subject: [PATCH 3/3] If we are a mirror, allow incrementing download count to fail This might fail because we don't have any crates in the database; we just want to be an API mirror and pass along the redirect URL. --- src/krate.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/krate.rs b/src/krate.rs index 4b3d7926e76..951ea962479 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -828,7 +828,16 @@ pub fn download(req: &mut Request) -> CargoResult { let crate_name = &req.params()["crate_id"]; let version = &req.params()["version"]; - try!(increment_download_counts(req, crate_name, version)); + // If we are a mirror, ignore failure to update download counts. + // API-only mirrors won't have any crates in their database, and + // incrementing the download count will look up the crate in the + // database. Mirrors just want to pass along a redirect URL. + if req.app().config.mirror { + let _ = increment_download_counts(req, crate_name, version); + } else { + try!(increment_download_counts(req, crate_name, version)); + } + let redirect_url = format!("https://{}/crates/{}/{}-{}.crate", req.app().bucket.host(), crate_name, crate_name, version);