@@ -19,54 +19,33 @@ use iron::{
1919 Handler , IronResult , Request , Response , Url ,
2020} ;
2121use lol_html:: errors:: RewritingError ;
22+ use once_cell:: sync:: Lazy ;
2223use router:: Router ;
2324use 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+ } ) ;
4639
4740/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
4841/// or crate details page based on whether the given crate version was successfully built.
4942pub fn rustdoc_redirector_handler ( req : & mut Request ) -> IronResult < Response > {
5043 fn redirect_to_doc (
5144 req : & Request ,
52- name : & str ,
53- vers : & str ,
54- target : Option < & str > ,
55- target_name : & str ,
45+ mut url_str : String ,
46+ permanent : bool ,
5647 path_in_crate : Option < & str > ,
5748 ) -> 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- } ;
7049 if let Some ( query) = req. url . query ( ) {
7150 url_str. push ( '?' ) ;
7251 url_str. push_str ( query) ;
@@ -75,7 +54,7 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
7554 url_str. push_str ( path) ;
7655 }
7756 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 {
7958 ( status:: MovedPermanently , 86400 )
8059 } else {
8160 ( status:: Found , 0 )
@@ -156,6 +135,12 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
156135 Some ( ( krate, path) ) => ( krate. to_string ( ) , Some ( path. to_string ( ) ) ) ,
157136 None => ( crate_name. to_string ( ) , None ) ,
158137 } ;
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+
159144 let req_version = router. find ( "version" ) ;
160145 let mut target = router. find ( "target" ) ;
161146
@@ -197,14 +182,15 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
197182
198183 if has_docs {
199184 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 ( ) )
208194 } else {
209195 rendering_time. step ( "redirect to crate" ) ;
210196 redirect_to_crate ( req, & crate_name, & version)
@@ -1790,6 +1776,13 @@ mod test {
17901776 "/some_random_crate/latest/some_random_crate/?search=some::path" ,
17911777 web,
17921778 ) ?;
1779+
1780+ assert_redirect (
1781+ "/std::some::path" ,
1782+ "https://doc.rust-lang.org/stable/std/?search=some::path" ,
1783+ web,
1784+ ) ?;
1785+
17931786 Ok ( ( ) )
17941787 } )
17951788 }
0 commit comments