@@ -53,6 +53,7 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
53
53
vers : & str ,
54
54
target : Option < & str > ,
55
55
target_name : & str ,
56
+ path_in_crate : Option < & str > ,
56
57
) -> IronResult < Response > {
57
58
let mut url_str = if let Some ( target) = target {
58
59
format ! (
@@ -69,6 +70,9 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
69
70
if let Some ( query) = req. url . query ( ) {
70
71
url_str. push ( '?' ) ;
71
72
url_str. push_str ( query) ;
73
+ } else if let Some ( path) = path_in_crate {
74
+ url_str. push_str ( "?query=" ) ;
75
+ url_str. push_str ( path) ;
72
76
}
73
77
let url = ctry ! ( req, Url :: parse( & url_str) ) ;
74
78
let ( status_code, max_age) = if vers == "latest" {
@@ -145,10 +149,13 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
145
149
146
150
// this handler should never called without crate pattern
147
151
let crate_name = cexpect ! ( req, router. find( "crate" ) ) ;
148
- let mut crate_name = percent_decode ( crate_name. as_bytes ( ) )
152
+ let crate_name = percent_decode ( crate_name. as_bytes ( ) )
149
153
. decode_utf8 ( )
150
- . unwrap_or_else ( |_| crate_name. into ( ) )
151
- . into_owned ( ) ;
154
+ . unwrap_or_else ( |_| crate_name. into ( ) ) ;
155
+ let ( mut crate_name, path_in_crate) = match crate_name. split_once ( "::" ) {
156
+ Some ( ( krate, path) ) => ( krate. to_string ( ) , Some ( path. to_string ( ) ) ) ,
157
+ None => ( crate_name. to_string ( ) , None ) ,
158
+ } ;
152
159
let req_version = router. find ( "version" ) ;
153
160
let mut target = router. find ( "target" ) ;
154
161
@@ -190,7 +197,14 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
190
197
191
198
if has_docs {
192
199
rendering_time. step ( "redirect to doc" ) ;
193
- redirect_to_doc ( req, & crate_name, & version, target, & target_name)
200
+ redirect_to_doc (
201
+ req,
202
+ & crate_name,
203
+ & version,
204
+ target,
205
+ & target_name,
206
+ path_in_crate. as_deref ( ) ,
207
+ )
194
208
} else {
195
209
rendering_time. step ( "redirect to crate" ) ;
196
210
redirect_to_crate ( req, & crate_name, & version)
@@ -1701,6 +1715,27 @@ mod test {
1701
1715
} )
1702
1716
}
1703
1717
1718
+ #[ test]
1719
+ fn test_redirect_crate_coloncolon_path ( ) {
1720
+ wrapper ( |env| {
1721
+ let web = env. frontend ( ) ;
1722
+ env. fake_release ( ) . name ( "some_random_crate" ) . create ( ) ?;
1723
+ env. fake_release ( ) . name ( "some_other_crate" ) . create ( ) ?;
1724
+
1725
+ assert_redirect (
1726
+ "/some_random_crate::somepath" ,
1727
+ "/some_random_crate/latest/some_random_crate/?query=somepath" ,
1728
+ web,
1729
+ ) ?;
1730
+ assert_redirect (
1731
+ "/some_random_crate::some::path" ,
1732
+ "/some_random_crate/latest/some_random_crate/?query=some::path" ,
1733
+ web,
1734
+ ) ?;
1735
+ Ok ( ( ) )
1736
+ } )
1737
+ }
1738
+
1704
1739
#[ test]
1705
1740
// regression test for https://github.com/rust-lang/docs.rs/pull/885#issuecomment-655147643
1706
1741
fn test_no_panic_on_missing_kind ( ) {
0 commit comments