@@ -19,54 +19,33 @@ use iron::{
19
19
Handler , IronResult , Request , Response , Url ,
20
20
} ;
21
21
use lol_html:: errors:: RewritingError ;
22
+ use once_cell:: sync:: Lazy ;
22
23
use router:: Router ;
23
24
use serde:: Serialize ;
24
- use std:: { fmt:: Write , path:: Path } ;
25
-
26
- #[ derive( Clone ) ]
27
- pub struct RustLangRedirector {
28
- url : Url ,
29
- }
30
-
31
- impl RustLangRedirector {
32
- pub fn new ( version : & str , target : & str ) -> Self {
33
- let url = iron:: url:: Url :: parse ( & format ! ( "https://doc.rust-lang.org/{version}/{target}/" ) )
34
- . expect ( "failed to parse rust-lang.org doc URL" ) ;
35
- let url = Url :: from_generic_url ( url) . expect ( "failed to convert url::Url to iron::Url" ) ;
36
-
37
- Self { url }
38
- }
39
- }
40
-
41
- impl iron:: Handler for RustLangRedirector {
42
- fn handle ( & self , _req : & mut Request ) -> IronResult < Response > {
43
- Ok ( Response :: with ( ( status:: Found , Redirect ( self . url . clone ( ) ) ) ) )
44
- }
45
- }
25
+ use std:: { collections:: HashMap , fmt:: Write , path:: Path } ;
26
+
27
+ static DOC_RUST_LANG_ORG_REDIRECTS : Lazy < HashMap < & str , & str > > = Lazy :: new ( || {
28
+ HashMap :: from ( [
29
+ ( "alloc" , "stable/alloc" ) ,
30
+ ( "core" , "stable/core" ) ,
31
+ ( "proc_macro" , "stable/proc_macro" ) ,
32
+ ( "proc-macro" , "stable/proc_macro" ) ,
33
+ ( "std" , "stable/std" ) ,
34
+ ( "test" , "stable/test" ) ,
35
+ ( "rustc" , "nightly/nightly-rustc" ) ,
36
+ ( "rustdoc" , "nightly/nightly-rustc/rustdoc" ) ,
37
+ ] )
38
+ } ) ;
46
39
47
40
/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
48
41
/// or crate details page based on whether the given crate version was successfully built.
49
42
pub fn rustdoc_redirector_handler ( req : & mut Request ) -> IronResult < Response > {
50
43
fn redirect_to_doc (
51
44
req : & Request ,
52
- name : & str ,
53
- vers : & str ,
54
- target : Option < & str > ,
55
- target_name : & str ,
45
+ mut url_str : String ,
46
+ permanent : bool ,
56
47
path_in_crate : Option < & str > ,
57
48
) -> IronResult < Response > {
58
- let mut url_str = if let Some ( target) = target {
59
- format ! (
60
- "{}/{}/{}/{}/{}/" ,
61
- redirect_base( req) ,
62
- name,
63
- vers,
64
- target,
65
- target_name
66
- )
67
- } else {
68
- format ! ( "{}/{}/{}/{}/" , redirect_base( req) , name, vers, target_name)
69
- } ;
70
49
if let Some ( query) = req. url . query ( ) {
71
50
url_str. push ( '?' ) ;
72
51
url_str. push_str ( query) ;
@@ -75,7 +54,7 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
75
54
url_str. push_str ( path) ;
76
55
}
77
56
let url = ctry ! ( req, Url :: parse( & url_str) ) ;
78
- let ( status_code, max_age) = if vers == "latest" {
57
+ let ( status_code, max_age) = if permanent {
79
58
( status:: MovedPermanently , 86400 )
80
59
} else {
81
60
( status:: Found , 0 )
@@ -156,6 +135,12 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
156
135
Some ( ( krate, path) ) => ( krate. to_string ( ) , Some ( path. to_string ( ) ) ) ,
157
136
None => ( crate_name. to_string ( ) , None ) ,
158
137
} ;
138
+
139
+ if let Some ( inner_path) = DOC_RUST_LANG_ORG_REDIRECTS . get ( crate_name. as_str ( ) ) {
140
+ let url = format ! ( "https://doc.rust-lang.org/{inner_path}/" ) ;
141
+ return redirect_to_doc ( req, url, false , path_in_crate. as_deref ( ) ) ;
142
+ }
143
+
159
144
let req_version = router. find ( "version" ) ;
160
145
let mut target = router. find ( "target" ) ;
161
146
@@ -197,14 +182,15 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
197
182
198
183
if has_docs {
199
184
rendering_time. step ( "redirect to doc" ) ;
200
- redirect_to_doc (
201
- req,
202
- & crate_name,
203
- & version,
204
- target,
205
- & target_name,
206
- path_in_crate. as_deref ( ) ,
207
- )
185
+
186
+ let base = redirect_base ( req) ;
187
+ let url_str = if let Some ( target) = target {
188
+ format ! ( "{base}/{crate_name}/{version}/{target}/{target_name}/" )
189
+ } else {
190
+ format ! ( "{base}/{crate_name}/{version}/{target_name}/" )
191
+ } ;
192
+
193
+ redirect_to_doc ( req, url_str, version == "latest" , path_in_crate. as_deref ( ) )
208
194
} else {
209
195
rendering_time. step ( "redirect to crate" ) ;
210
196
redirect_to_crate ( req, & crate_name, & version)
@@ -1790,6 +1776,13 @@ mod test {
1790
1776
"/some_random_crate/latest/some_random_crate/?search=some::path" ,
1791
1777
web,
1792
1778
) ?;
1779
+
1780
+ assert_redirect (
1781
+ "/std::some::path" ,
1782
+ "https://doc.rust-lang.org/stable/std/?search=some::path" ,
1783
+ web,
1784
+ ) ?;
1785
+
1793
1786
Ok ( ( ) )
1794
1787
} )
1795
1788
}
0 commit comments