Skip to content

Commit c9b0816

Browse files
Emilgardissyphar
authored andcommitted
keep queries when doing lucky, :: or crate-name searches
enables `docs.rs/releases/search?query=tokio::spawn&i-am-feeling-lucky=1&go_to_first=true` and `docs.rs/tokio::spawn?go_to_first=true` to go to first result after redirect
1 parent b42ffe9 commit c9b0816

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

src/web/releases.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,25 @@ pub fn search_handler(req: &mut Request) -> IronResult<Response> {
584584
return redirect_to_random_crate(req, &mut conn);
585585
}
586586

587-
let (krate, query) = match query.split_once("::") {
587+
let (krate, mut query) = match query.split_once("::") {
588588
Some((krate, query)) => (krate.to_string(), format!("?search={query}")),
589589
None => (query.clone(), "".to_string()),
590590
};
591591

592+
for (k, v) in params
593+
.iter()
594+
.filter(|(k, _)| !matches!(k.as_ref(), "i-am-feeling-lucky" | "query"))
595+
{
596+
if query.is_empty() {
597+
query.push('?');
598+
} else {
599+
query.push('&')
600+
}
601+
query.push_str(k);
602+
query.push('=');
603+
query.push_str(v);
604+
}
605+
592606
// since we never pass a version into `match_version` here, we'll never get
593607
// `MatchVersion::Exact`, so the distinction between `Exact` and `Semver` doesn't
594608
// matter
@@ -907,6 +921,21 @@ mod tests {
907921
})
908922
}
909923

924+
#[test]
925+
fn search_coloncolon_path_redirects_to_crate_docs_and_keeps_query() {
926+
wrapper(|env| {
927+
let web = env.frontend();
928+
env.fake_release().name("some_random_crate").create()?;
929+
930+
assert_redirect(
931+
"/releases/search?query=some_random_crate::somepath&go_to_first=true",
932+
"/some_random_crate/1.0.0/some_random_crate/?search=somepath&go_to_first=true",
933+
web,
934+
)?;
935+
Ok(())
936+
})
937+
}
938+
910939
#[test]
911940
fn search_result_passes_cratesio_pagination_links() {
912941
wrapper(|env| {

src/web/rustdoc.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,19 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
4646
permanent: bool,
4747
path_in_crate: Option<&str>,
4848
) -> IronResult<Response> {
49-
if let Some(query) = req.url.query() {
50-
url_str.push('?');
51-
url_str.push_str(query);
52-
} else if let Some(path) = path_in_crate {
49+
let mut question_mark = false;
50+
if let Some(path) = path_in_crate {
5351
url_str.push_str("?search=");
5452
url_str.push_str(path);
53+
question_mark = true;
54+
}
55+
if let Some(query) = req.url.query() {
56+
if !question_mark {
57+
url_str.push('?');
58+
} else {
59+
url_str.push('&');
60+
}
61+
url_str.push_str(query);
5562
}
5663
let url = ctry!(req, Url::parse(&url_str));
5764
let (status_code, max_age) = if permanent {
@@ -1776,6 +1783,11 @@ mod test {
17761783
"/some_random_crate/latest/some_random_crate/?search=some::path",
17771784
web,
17781785
)?;
1786+
assert_redirect(
1787+
"/some_random_crate::some::path?go_to_first=true",
1788+
"/some_random_crate/latest/some_random_crate/?search=some::path&go_to_first=true",
1789+
web,
1790+
)?;
17791791

17801792
assert_redirect(
17811793
"/std::some::path",

0 commit comments

Comments
 (0)