Skip to content

Commit 8e71b4e

Browse files
sypharjyn514
authored andcommitted
get rid of empty url parameter section in some redirects
1 parent 111865a commit 8e71b4e

File tree

3 files changed

+52
-42
lines changed

3 files changed

+52
-42
lines changed

src/web/mod.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ use postgres::Client;
107107
use router::{NoRoute, TrailingSlash};
108108
use semver::{Version, VersionReq};
109109
use serde::Serialize;
110+
use std::borrow::Borrow;
110111
use std::{borrow::Cow, net::SocketAddr, sync::Arc};
111112

112113
/// Duration of static files for staticfile and DatabaseFileHandler (in seconds)
@@ -507,6 +508,25 @@ fn redirect_base(req: &Request) -> String {
507508
}
508509
}
509510

511+
/// Parse and URL into a iron::Url struct.
512+
/// When `queries` are given these are added to the URL,
513+
/// with empty `queries` the `?` will be omitted.
514+
pub(crate) fn parse_url_with_params<I, K, V>(url: &str, queries: I) -> Result<Url, Error>
515+
where
516+
I: IntoIterator,
517+
I::Item: Borrow<(K, V)>,
518+
K: AsRef<str>,
519+
V: AsRef<str>,
520+
{
521+
let mut queries = queries.into_iter().peekable();
522+
if queries.peek().is_some() {
523+
Url::from_generic_url(iron::url::Url::parse_with_params(url, queries)?)
524+
.map_err(|msg| anyhow!(msg))
525+
} else {
526+
Url::parse(url).map_err(|msg| anyhow!(msg))
527+
}
528+
}
529+
510530
/// MetaData used in header
511531
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
512532
pub(crate) struct MetaData {
@@ -728,24 +748,24 @@ mod test {
728748
wrapper(|env| {
729749
let web = env.frontend();
730750
for krate in &["std", "alloc", "core", "proc_macro", "test"] {
731-
let target = format!("https://doc.rust-lang.org/stable/{}/?", krate);
751+
let target = format!("https://doc.rust-lang.org/stable/{}/", krate);
732752

733753
// with or without slash
734754
assert_redirect(&format!("/{}", krate), &target, web)?;
735755
assert_redirect(&format!("/{}/", krate), &target, web)?;
736756
}
737757

738-
let target = "https://doc.rust-lang.org/stable/proc_macro/?";
758+
let target = "https://doc.rust-lang.org/stable/proc_macro/";
739759
// with or without slash
740760
assert_redirect("/proc-macro", target, web)?;
741761
assert_redirect("/proc-macro/", target, web)?;
742762

743-
let target = "https://doc.rust-lang.org/nightly/nightly-rustc/?";
763+
let target = "https://doc.rust-lang.org/nightly/nightly-rustc/";
744764
// with or without slash
745765
assert_redirect("/rustc", target, web)?;
746766
assert_redirect("/rustc/", target, web)?;
747767

748-
let target = "https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/?";
768+
let target = "https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/";
749769
// with or without slash
750770
assert_redirect("/rustdoc", target, web)?;
751771
assert_redirect("/rustdoc/", target, web)?;

src/web/releases.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
db::{Pool, PoolClient},
66
impl_webpage,
77
utils::report_error,
8-
web::{error::Nope, match_version, page::WebPage, redirect_base},
8+
web::{error::Nope, match_version, page::WebPage, parse_url_with_params, redirect_base},
99
BuildQueue, Config,
1010
};
1111
use anyhow::{anyhow, Result};
@@ -20,7 +20,7 @@ use log::{debug, warn};
2020
use postgres::Client;
2121
use router::Router;
2222
use serde::{Deserialize, Serialize};
23-
use std::collections::HashMap;
23+
use std::collections::{BTreeMap, HashMap};
2424
use std::str;
2525
use url::form_urlencoded;
2626

@@ -584,11 +584,11 @@ pub fn search_handler(req: &mut Request) -> IronResult<Response> {
584584
return redirect_to_random_crate(req, &mut conn);
585585
}
586586

587-
let mut queries = std::collections::BTreeMap::new();
587+
let mut queries = BTreeMap::new();
588588

589589
let krate = match query.split_once("::") {
590590
Some((krate, query)) => {
591-
queries.insert("search", query);
591+
queries.insert("search".into(), query.into());
592592
krate.to_string()
593593
}
594594
None => query.clone(),
@@ -599,21 +599,15 @@ pub fn search_handler(req: &mut Request) -> IronResult<Response> {
599599
// matter
600600
if let Ok(matchver) = match_version(&mut conn, &krate, None) {
601601
params.remove("query");
602-
queries.extend(params.iter().map(|(k, v)| (k.as_ref(), v.as_ref())));
602+
queries.extend(params);
603603
let (version, _) = matchver.version.into_parts();
604604
let krate = matchver.corrected_name.unwrap_or(krate);
605605

606606
let base = redirect_base(req);
607607
let url = if matchver.rustdoc_status {
608608
let target_name = matchver.target_name;
609609
let path = format!("{base}/{krate}/{version}/{target_name}/");
610-
ctry!(
611-
req,
612-
Url::from_generic_url(ctry!(
613-
req,
614-
iron::url::Url::parse_with_params(&path, queries)
615-
))
616-
)
610+
ctry!(req, parse_url_with_params(&path, queries))
617611
} else {
618612
ctry!(req, Url::parse(&format!("{base}/crate/{krate}/{version}")))
619613
};
@@ -861,7 +855,7 @@ mod tests {
861855

862856
assert_redirect(
863857
"/releases/search?query=some_random_crate&i-am-feeling-lucky=1",
864-
"/some_random_crate/1.0.0/some_random_crate/?",
858+
"/some_random_crate/1.0.0/some_random_crate/",
865859
web,
866860
)?;
867861
Ok(())

src/web/rustdoc.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use crate::{
66
utils,
77
web::{
88
crate_details::CrateDetails, csp::Csp, error::Nope, file::File, match_version,
9-
metrics::RenderingTimesRecorder, redirect_base, MatchSemver, MetaData,
9+
metrics::RenderingTimesRecorder, parse_url_with_params, redirect_base, MatchSemver,
10+
MetaData,
1011
},
1112
Config, Metrics, Storage,
1213
};
@@ -22,7 +23,11 @@ use lol_html::errors::RewritingError;
2223
use once_cell::sync::Lazy;
2324
use router::Router;
2425
use serde::Serialize;
25-
use std::{collections::HashMap, fmt::Write, path::Path};
26+
use std::{
27+
collections::{BTreeMap, HashMap},
28+
fmt::Write,
29+
path::Path,
30+
};
2631

2732
static DOC_RUST_LANG_ORG_REDIRECTS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
2833
HashMap::from([
@@ -46,21 +51,12 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
4651
permanent: bool,
4752
path_in_crate: Option<&str>,
4853
) -> IronResult<Response> {
49-
let mut queries: std::collections::BTreeMap<
50-
std::borrow::Cow<'_, str>,
51-
std::borrow::Cow<'_, str>,
52-
> = std::collections::BTreeMap::new();
54+
let mut queries = BTreeMap::new();
5355
if let Some(path) = path_in_crate {
5456
queries.insert("search".into(), path.into());
5557
}
5658
queries.extend(req.url.as_ref().query_pairs());
57-
let url = ctry!(
58-
req,
59-
Url::from_generic_url(ctry!(
60-
req,
61-
iron::url::Url::parse_with_params(&url_str, queries)
62-
))
63-
);
59+
let url = ctry!(req, parse_url_with_params(&url_str, queries));
6460
let (status_code, max_age) = if permanent {
6561
(status::MovedPermanently, 86400)
6662
} else {
@@ -865,8 +861,8 @@ mod test {
865861
"/dummy/0.3.0/all.html",
866862
web,
867863
)?;
868-
assert_redirect("/dummy/0.3.0/", &format!("{}?", base), web)?;
869-
assert_redirect("/dummy/0.3.0/index.html", &format!("{}?", base), web)?;
864+
assert_redirect("/dummy/0.3.0/", base, web)?;
865+
assert_redirect("/dummy/0.3.0/index.html", base, web)?;
870866
Ok(())
871867
});
872868
}
@@ -1183,7 +1179,7 @@ mod test {
11831179
.create()?;
11841180

11851181
let web = env.frontend();
1186-
assert_redirect("/fake%2Dcrate", "/fake-crate/latest/fake_crate/?", web)?;
1182+
assert_redirect("/fake%2Dcrate", "/fake-crate/latest/fake_crate/", web)?;
11871183

11881184
Ok(())
11891185
});
@@ -1213,37 +1209,37 @@ mod test {
12131209

12141210
let web = env.frontend();
12151211

1216-
assert_redirect("/dummy_dash", "/dummy-dash/latest/dummy_dash/?", web)?;
1217-
assert_redirect("/dummy_dash/*", "/dummy-dash/0.2.0/dummy_dash/?", web)?;
1218-
assert_redirect("/dummy_dash/0.1.0", "/dummy-dash/0.1.0/dummy_dash/?", web)?;
1212+
assert_redirect("/dummy_dash", "/dummy-dash/latest/dummy_dash/", web)?;
1213+
assert_redirect("/dummy_dash/*", "/dummy-dash/0.2.0/dummy_dash/", web)?;
1214+
assert_redirect("/dummy_dash/0.1.0", "/dummy-dash/0.1.0/dummy_dash/", web)?;
12191215
assert_redirect(
12201216
"/dummy-underscore",
1221-
"/dummy_underscore/latest/dummy_underscore/?",
1217+
"/dummy_underscore/latest/dummy_underscore/",
12221218
web,
12231219
)?;
12241220
assert_redirect(
12251221
"/dummy-underscore/*",
1226-
"/dummy_underscore/0.2.0/dummy_underscore/?",
1222+
"/dummy_underscore/0.2.0/dummy_underscore/",
12271223
web,
12281224
)?;
12291225
assert_redirect(
12301226
"/dummy-underscore/0.1.0",
1231-
"/dummy_underscore/0.1.0/dummy_underscore/?",
1227+
"/dummy_underscore/0.1.0/dummy_underscore/",
12321228
web,
12331229
)?;
12341230
assert_redirect(
12351231
"/dummy-mixed_separators",
1236-
"/dummy_mixed-separators/latest/dummy_mixed_separators/?",
1232+
"/dummy_mixed-separators/latest/dummy_mixed_separators/",
12371233
web,
12381234
)?;
12391235
assert_redirect(
12401236
"/dummy_mixed_separators/*",
1241-
"/dummy_mixed-separators/0.2.0/dummy_mixed_separators/?",
1237+
"/dummy_mixed-separators/0.2.0/dummy_mixed_separators/",
12421238
web,
12431239
)?;
12441240
assert_redirect(
12451241
"/dummy-mixed-separators/0.1.0",
1246-
"/dummy_mixed-separators/0.1.0/dummy_mixed_separators/?",
1242+
"/dummy_mixed-separators/0.1.0/dummy_mixed_separators/",
12471243
web,
12481244
)?;
12491245

0 commit comments

Comments
 (0)