Skip to content

Commit

Permalink
Serve /crate/latest/crate rather than redirect
Browse files Browse the repository at this point in the history
  • Loading branch information
jsha committed Nov 28, 2021
1 parent e5d9879 commit cea3de0
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/web/build_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub fn build_details_handler(req: &mut Request) -> IronResult<Response> {
};

BuildDetailsPage {
metadata: cexpect!(req, MetaData::from_crate(&mut conn, name, version)),
metadata: cexpect!(req, MetaData::from_crate(&mut conn, name, version, version)),
build_details,
}
.into_response(req)
Expand Down
21 changes: 15 additions & 6 deletions src/web/builds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ pub fn build_list_handler(req: &mut Request) -> IronResult<Response> {
.last()
.map_or(false, |segment| segment.ends_with(".json"));

let version =
let (version, version_or_latest) =
match match_version(&mut conn, name, req_version).and_then(|m| m.assume_exact())? {
MatchSemver::Exact((version, _)) => version,
MatchSemver::Exact((version, _)) => (version.clone(), version),
MatchSemver::Latest((version, _)) => (version, "latest".to_string()),

MatchSemver::Semver((version, _)) => {
let ext = if is_json { ".json" } else { "" };
Expand Down Expand Up @@ -117,7 +118,10 @@ pub fn build_list_handler(req: &mut Request) -> IronResult<Response> {
Ok(resp)
} else {
BuildsPage {
metadata: cexpect!(req, MetaData::from_crate(&mut conn, name, &version)),
metadata: cexpect!(
req,
MetaData::from_crate(&mut conn, name, &version, &version_or_latest)
),
builds,
limits,
}
Expand Down Expand Up @@ -307,7 +311,7 @@ mod tests {
}

#[test]
fn latest_redirect() {
fn latest_200() {
wrapper(|env| {
env.fake_release()
.name("aquarelle")
Expand All @@ -332,7 +336,12 @@ mod tests {
assert!(resp
.url()
.as_str()
.ends_with("/crate/aquarelle/0.2.0/builds"));
.ends_with("/crate/aquarelle/latest/builds"));
let body = String::from_utf8(resp.bytes().unwrap().to_vec()).unwrap();
assert!(body.contains("<a href=\"/crate/aquarelle/latest/features\""));
assert!(body.contains("<a href=\"/crate/aquarelle/latest/builds\""));
assert!(body.contains("<a href=\"/crate/aquarelle/latest/source/\""));
assert!(body.contains("<a href=\"/crate/aquarelle/latest\""));

let resp_json = env
.frontend()
Expand All @@ -341,7 +350,7 @@ mod tests {
assert!(resp_json
.url()
.as_str()
.ends_with("/crate/aquarelle/0.2.0/builds.json"));
.ends_with("/crate/aquarelle/latest/builds.json"));

Ok(())
});
Expand Down
85 changes: 74 additions & 11 deletions src/web/crate_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ impl CrateDetails {
conn: &mut Client,
name: &str,
version: &str,
version_or_latest: &str,
up: &RepositoryStatsUpdater,
) -> Option<CrateDetails> {
// get all stuff, I love you rustfmt
Expand Down Expand Up @@ -150,6 +151,7 @@ impl CrateDetails {
let metadata = MetaData {
name: krate.get("name"),
version: krate.get("version"),
version_or_latest: version_or_latest.to_string(),
description: krate.get("description"),
rustdoc_status: krate.get("rustdoc_status"),
target_name: krate.get("target_name"),
Expand Down Expand Up @@ -281,16 +283,21 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
let name = cexpect!(req, router.find("name"));
let req_version = router.find("version");

let mut conn = extension!(req, Pool).get()?;

match match_version(&mut conn, name, req_version).and_then(|m| m.assume_exact())? {
MatchSemver::Exact((version, _)) => {
let updater = extension!(req, RepositoryStatsUpdater);
let details = cexpect!(req, CrateDetails::new(&mut conn, name, &version, updater));
if req_version == None {
let url = ctry!(
req,
Url::parse(&format!("{}/crate/{}/latest", redirect_base(req), name,)),
);
return Ok(super::redirect(url));
}

CrateDetailsPage { details }.into_response(req)
}
let mut conn = extension!(req, Pool).get()?;

let found_version =
match_version(&mut conn, name, req_version).and_then(|m| m.assume_exact())?;
let (version, version_or_latest) = match found_version {
MatchSemver::Exact((version, _)) => (version.clone(), version),
MatchSemver::Latest((version, _)) => (version, "latest".to_string()),
MatchSemver::Semver((version, _)) => {
let url = ctry!(
req,
Expand All @@ -302,16 +309,24 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
)),
);

Ok(super::redirect(url))
return Ok(super::redirect(url));
}
}
};

let updater = extension!(req, RepositoryStatsUpdater);
let details = cexpect!(
req,
CrateDetails::new(&mut conn, name, &version, &version_or_latest, updater)
);

CrateDetailsPage { details }.into_response(req)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::index::api::CrateOwner;
use crate::test::{wrapper, TestDatabase};
use crate::test::{assert_redirect, wrapper, TestDatabase};
use anyhow::{Context, Error};
use kuchiki::traits::TendrilSink;
use std::collections::HashMap;
Expand All @@ -326,6 +341,7 @@ mod tests {
&mut db.conn(),
package,
version,
version,
db.repository_stats_updater(),
)
.with_context(|| anyhow::anyhow!("could not fetch crate details"))?;
Expand Down Expand Up @@ -459,6 +475,7 @@ mod tests {
&mut db.conn(),
"foo",
"0.2.0",
"0.2.0",
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -534,6 +551,7 @@ mod tests {
&mut db.conn(),
"foo",
version,
version,
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -564,6 +582,7 @@ mod tests {
&mut db.conn(),
"foo",
version,
version,
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -595,6 +614,7 @@ mod tests {
&mut db.conn(),
"foo",
version,
version,
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -634,6 +654,7 @@ mod tests {
&mut db.conn(),
"foo",
version,
version,
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -696,6 +717,7 @@ mod tests {
&mut db.conn(),
"foo",
"0.0.1",
"0.0.1",
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -726,6 +748,7 @@ mod tests {
&mut db.conn(),
"foo",
"0.0.1",
"0.0.1",
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -755,6 +778,7 @@ mod tests {
&mut db.conn(),
"foo",
"0.0.1",
"0.0.1",
db.repository_stats_updater(),
)
.unwrap();
Expand All @@ -779,6 +803,7 @@ mod tests {
&mut db.conn(),
"foo",
"0.0.1",
"0.0.1",
db.repository_stats_updater(),
)
.unwrap();
Expand Down Expand Up @@ -956,4 +981,42 @@ mod tests {
Ok(())
});
}

#[test]
fn latest_url() {
wrapper(|env| {
env.fake_release()
.name("dummy")
.version("0.4.0")
.rustdoc_file("dummy/index.html")
.rustdoc_file("x86_64-pc-windows-msvc/dummy/index.html")
.default_target("x86_64-unknown-linux-gnu")
.add_target("x86_64-pc-windows-msvc")
.create()?;
let web = env.frontend();

let resp = env.frontend().get("/crate/dummy/latest").send()?;
assert!(resp.status().is_success());
assert!(resp.url().as_str().ends_with("/crate/dummy/latest"));
let body = String::from_utf8(resp.bytes().unwrap().to_vec()).unwrap();
assert!(body.contains("<a href=\"/crate/dummy/latest/features\""));
assert!(body.contains("<a href=\"/crate/dummy/latest/builds\""));
assert!(body.contains("<a href=\"/crate/dummy/latest/source/\""));
assert!(body.contains("<a href=\"/crate/dummy/latest\""));

assert_redirect("/crate/dummy/latest/", "/crate/dummy/latest", web)?;
assert_redirect("/crate/dummy", "/crate/dummy/latest", web)?;

let resp_json = env
.frontend()
.get("/crate/aquarelle/latest/builds.json")
.send()?;
assert!(resp_json
.url()
.as_str()
.ends_with("/crate/aquarelle/latest/builds.json"));

Ok(())
});
}
}
18 changes: 13 additions & 5 deletions src/web/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
let req_version = router.find("version");

let mut conn = extension!(req, Pool).get()?;
let version =
let (version, version_or_latest) =
match match_version(&mut conn, name, req_version).and_then(|m| m.assume_exact())? {
MatchSemver::Exact((version, _)) => version,
MatchSemver::Exact((version, _)) => (version.clone(), version),
MatchSemver::Latest((version, _)) => (version, "latest".to_string()),

MatchSemver::Semver((version, _)) => {
let url = ctry!(
Expand Down Expand Up @@ -69,7 +70,10 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
}

FeaturesPage {
metadata: cexpect!(req, MetaData::from_crate(&mut conn, name, &version)),
metadata: cexpect!(
req,
MetaData::from_crate(&mut conn, name, &version, &version_or_latest)
),
features,
default_len,
}
Expand Down Expand Up @@ -244,7 +248,7 @@ mod tests {
}

#[test]
fn latest_redirect() {
fn latest_200() {
wrapper(|env| {
env.fake_release()
.name("foo")
Expand All @@ -259,7 +263,11 @@ mod tests {
.create()?;

let resp = env.frontend().get("/crate/foo/latest/features").send()?;
assert!(resp.url().as_str().ends_with("/crate/foo/0.2.0/features"));
assert!(resp.url().as_str().ends_with("/crate/foo/latest/features"));
let body = String::from_utf8(resp.bytes().unwrap().to_vec()).unwrap();
assert!(body.contains("<a href=\"/crate/foo/latest/builds\""));
assert!(body.contains("<a href=\"/crate/foo/latest/source/\""));
assert!(body.contains("<a href=\"/crate/foo/latest\""));
Ok(())
});
}
Expand Down
Loading

0 comments on commit cea3de0

Please sign in to comment.