Skip to content

Commit f857f2a

Browse files
committed
fix wrong semver redirects with items
1 parent 855b164 commit f857f2a

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

src/web/extractors/rustdoc.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,9 +720,24 @@ fn generate_rustdoc_url(name: &str, version: &ReqVersion, path: &str) -> Escaped
720720
fn generate_rustdoc_path_for_url(
721721
target_name: Option<&str>,
722722
default_target: Option<&str>,
723-
doc_target: Option<&str>,
724-
inner_path: Option<&str>,
723+
mut doc_target: Option<&str>,
724+
mut inner_path: Option<&str>,
725725
) -> String {
726+
// if we have an "unparsed" set of params, we might have a part of
727+
// the inner path in `doc_target`. Thing is:
728+
// We don't know if that's a real target, or a part of the path,
729+
// But the "saner" default for this method is to treat it as part
730+
// of the path, not a potential doc target.
731+
let inner_path = if target_name.is_none()
732+
&& default_target.is_none()
733+
&& let (Some(doc_target), Some(inner_path)) = (doc_target.take(), inner_path.as_mut())
734+
&& !doc_target.is_empty()
735+
{
736+
Some(format!("{doc_target}/{inner_path}"))
737+
} else {
738+
inner_path.map(|s| s.to_string())
739+
};
740+
726741
// first validate & fix the inner path to use.
727742
let result = if let Some(path) = inner_path
728743
&& !path.is_empty()
@@ -737,7 +752,7 @@ fn generate_rustdoc_path_for_url(
737752
// * it's not just "index.html"
738753
// * we have a slash in the path.
739754
path.to_string()
740-
} else if ROOT_RUSTDOC_HTML_FILES.contains(&path) {
755+
} else if ROOT_RUSTDOC_HTML_FILES.contains(&path.as_str()) {
741756
// special case: some files are at the root of the rustdoc output,
742757
// without a trailing slash, and the routes are fine with that.
743758
// e.g. `/help.html`, `/settings.html`, `/all.html`, ...
@@ -1682,4 +1697,23 @@ mod tests {
16821697

16831698
assert_eq!(params.rustdoc_url(), expected_url);
16841699
}
1700+
1701+
#[test]
1702+
fn test_item_with_semver_url() {
1703+
// https://github.com/rust-lang/docs.rs/iss
1704+
1705+
let ver: Version = "0.14.0".parse().unwrap();
1706+
let params = RustdocParams::new(KRATE)
1707+
.with_page_kind(PageKind::Rustdoc)
1708+
.with_req_version(ReqVersion::Exact(ver))
1709+
.with_doc_target(KRATE)
1710+
.with_inner_path("trait.Itertools.html");
1711+
1712+
dbg!(&params);
1713+
1714+
assert_eq!(
1715+
params.rustdoc_url(),
1716+
format!("/{KRATE}/0.14.0/{KRATE}/trait.Itertools.html")
1717+
)
1718+
}
16851719
}

src/web/rustdoc.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ pub(crate) async fn rustdoc_html_server_handler(
474474
})?
475475
.into_canonical_req_version_or_else(|version| {
476476
AxumNope::Redirect(
477-
params.clone().with_req_version(version).rustdoc_url(),
477+
dbg!(params.clone().with_req_version(version)).rustdoc_url(),
478478
CachePolicy::ForeverInCdn,
479479
)
480480
})?;
@@ -3464,4 +3464,28 @@ mod test {
34643464

34653465
Ok(())
34663466
}
3467+
3468+
#[tokio::test(flavor = "multi_thread")]
3469+
async fn test_fetch_item_with_semver_url() -> Result<()> {
3470+
// https://github.com/rust-lang/docs.rs/issues/3036
3471+
3472+
let env = TestEnvironment::new().await?;
3473+
3474+
env.fake_release()
3475+
.await
3476+
.name("itertools")
3477+
.version("0.14.0")
3478+
.rustdoc_file("itertools/trait.Itertools.html")
3479+
.create()
3480+
.await?;
3481+
3482+
let web = env.web_app().await;
3483+
web.assert_redirect(
3484+
"/itertools/^0.14/itertools/trait.Itertools.html",
3485+
"/itertools/0.14.0/itertools/trait.Itertools.html",
3486+
)
3487+
.await?;
3488+
3489+
Ok(())
3490+
}
34673491
}

0 commit comments

Comments
 (0)