pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
    fn redirect_to_doc(
        req: &Request,
        name: &str,
        vers: &str,
        target: Option<&str>,
        target_name: &str,
    ) -> IronResult<Response> {
        let mut url_str = if let Some(target) = target {
            format!(
                "{}/{}/{}/{}/{}/",
                redirect_base(req),
                name,
                vers,
                target,
                target_name
            )
        } else {
            format!("{}/{}/{}/{}/", redirect_base(req), name, vers, target_name)
        };
        if let Some(query) = req.url.query() {
            url_str.push('?');
            url_str.push_str(query);
        }
        let url = ctry!(req, Url::parse(&url_str));
        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    fn redirect_to_crate(req: &Request, name: &str, vers: &str) -> IronResult<Response> {
        let url = ctry!(
            req,
            Url::parse(&format!("{}/crate/{}/{}", redirect_base(req), name, vers)),
        );

        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    let metrics = extension!(req, Metrics).clone();
    let mut rendering_time = RenderingTimesRecorder::new(&metrics.rustdoc_redirect_rendering_times);

    // this unwrap is safe because iron urls are always able to use `path_segments`
    // i'm using this instead of `req.url.path()` to avoid allocating the Vec, and also to avoid
    // keeping the borrow alive into the return statement
    if req
        .url
        .as_ref()
        .path_segments()
        .unwrap()
        .last()
        .map_or(false, |s| s.ends_with(".js"))
    {
        // javascript files should be handled by the file server instead of erroneously
        // redirecting to the crate root page
        if req.url.as_ref().path_segments().unwrap().count() > 2 {
            // this URL is actually from a crate-internal path, serve it there instead
            rendering_time.step("serve JS for crate");
            return rustdoc_html_server_handler(req);
        } else {
            rendering_time.step("serve JS");
            let storage = extension!(req, Storage);
            let config = extension!(req, Config);

            let path = req.url.path();
            let path = path.join("/");
            return match File::from_path(&storage, &path, &config) {
                Ok(f) => Ok(f.serve()),
                Err(..) => Err(Nope::ResourceNotFound.into()),
            };
        }
    } else if req
        .url
        .as_ref()
        .path_segments()
        .unwrap()
        .last()
        .map_or(false, |s| s.ends_with(".ico"))
    {
        // route .ico files into their dedicated handler so that docs.rs's favicon is always
        // displayed
        rendering_time.step("serve ICO");
        return super::statics::ico_handler(req);
    }

    let router = extension!(req, Router);
    let mut conn = extension!(req, Pool).get()?;

    // this handler should never called without crate pattern
    let crate_name = cexpect!(req, router.find("crate"));
    let mut crate_name = percent_decode(crate_name.as_bytes())
        .decode_utf8()
        .unwrap_or_else(|_| crate_name.into())
        .into_owned();
    let req_version = router.find("version");
    let mut target = router.find("target");

    // it doesn't matter if the version that was given was exact or not, since we're redirecting
    // anyway
    rendering_time.step("match version");
    let v = match_version(&mut conn, &crate_name, req_version)?;
    if let Some(new_name) = v.corrected_name {
        // `match_version` checked against -/_ typos, so if we have a name here we should
        // use that instead
        crate_name = new_name;
    }
    let (version, id) = v.version.into_parts();

    // get target name and whether it has docs
    // FIXME: This is a bit inefficient but allowing us to use less code in general
    rendering_time.step("fetch release doc status");
    let (target_name, has_docs): (String, bool) = {
        let rows = ctry!(
            req,
            conn.query(
                "SELECT target_name, rustdoc_status
                 FROM releases
                 WHERE releases.id = $1",
                &[&id]
            ),
        );

        (rows[0].get(0), rows[0].get(1))
    };

    if target == Some("index.html") || target == Some(&target_name) {
        target = None;
    }

    if has_docs {
        rendering_time.step("redirect to doc");
        redirect_to_doc(req, &crate_name, &version, target, &target_name)
    } else {
        rendering_time.step("redirect to crate");
        redirect_to_crate(req, &crate_name, &version)
    }
}
/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
/// or crate details page based on whether the given crate version was successfully built.
Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
or crate details page based on whether the given crate version was successfully built.
Handler called for ` / : crate ` and ` / : crate / : version ` URLs . Automatically redirects to the docs or crate details page based on whether the given crate version was successfully built .
pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
    fn redirect_to_doc(
        req: &Request,
        name: &str,
        vers: &str,
        target: Option<&str>,
        target_name: &str,
    ) -> IronResult<Response> {
        let mut url_str = if let Some(target) = target {
            format!(
                "{}/{}/{}/{}/{}/",
                redirect_base(req),
                name,
                vers,
                target,
                target_name
            )
        } else {
            format!("{}/{}/{}/{}/", redirect_base(req), name, vers, target_name)
        };
        if let Some(query) = req.url.query() {
            url_str.push('?');
            url_str.push_str(query);
        }
        let url = ctry!(req, Url::parse(&url_str));
        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));
        Ok(resp)
    }
    fn redirect_to_crate(req: &Request, name: &str, vers: &str) -> IronResult<Response> {
        let url = ctry!(
            req,
            Url::parse(&format!("{}/crate/{}/{}", redirect_base(req), name, vers)),
        );
        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));
        Ok(resp)
    }
    let metrics = extension!(req, Metrics).clone();
    let mut rendering_time = RenderingTimesRecorder::new(&metrics.rustdoc_redirect_rendering_times);
    // this unwrap is safe because iron urls are always able to use `path_segments`
    // i'm using this instead of `req.url.path()` to avoid allocating the Vec, and also to avoid
    // keeping the borrow alive into the return statement
    if req
        .url
        .as_ref()
        .path_segments()
        .unwrap()
        .last()
        .map_or(false, |s| s.ends_with(".js"))
    {
        // javascript files should be handled by the file server instead of erroneously
        // redirecting to the crate root page
        if req.url.as_ref().path_segments().unwrap().count() > 2 {
            // this URL is actually from a crate-internal path, serve it there instead
            rendering_time.step("serve JS for crate");
            return rustdoc_html_server_handler(req);
        } else {
            rendering_time.step("serve JS");
            let storage = extension!(req, Storage);
            let config = extension!(req, Config);
            let path = req.url.path();
            let path = path.join("/");
            return match File::from_path(&storage, &path, &config) {
                Ok(f) => Ok(f.serve()),
                Err(..) => Err(Nope::ResourceNotFound.into()),
            };
        }
    } else if req
        .url
        .as_ref()
        .path_segments()
        .unwrap()
        .last()
        .map_or(false, |s| s.ends_with(".ico"))
    {
        // route .ico files into their dedicated handler so that docs.rs's favicon is always
        // displayed
        rendering_time.step("serve ICO");
        return super::statics::ico_handler(req);
    }
    let router = extension!(req, Router);
    let mut conn = extension!(req, Pool).get()?;
    // this handler should never called without crate pattern
    let crate_name = cexpect!(req, router.find("crate"));
    let mut crate_name = percent_decode(crate_name.as_bytes())
        .decode_utf8()
        .unwrap_or_else(|_| crate_name.into())
        .into_owned();
    let req_version = router.find("version");
    let mut target = router.find("target");
    // it doesn't matter if the version that was given was exact or not, since we're redirecting
    // anyway
    rendering_time.step("match version");
    let v = match_version(&mut conn, &crate_name, req_version)?;
    if let Some(new_name) = v.corrected_name {
        // `match_version` checked against -/_ typos, so if we have a name here we should
        // use that instead
        crate_name = new_name;
    }
    let (version, id) = v.version.into_parts();
    // get target name and whether it has docs
    // FIXME: This is a bit inefficient but allowing us to use less code in general
    rendering_time.step("fetch release doc status");
    let (target_name, has_docs): (String, bool) = {
        let rows = ctry!(
            req,
            conn.query(
                "SELECT target_name, rustdoc_status
                 FROM releases
                 WHERE releases.id = $1",
                &[&id]
            ),
        );
        (rows[0].get(0), rows[0].get(1))
    };
    if target == Some("index.html") || target == Some(&target_name) {
        target = None;
    }
    if has_docs {
        rendering_time.step("redirect to doc");
        redirect_to_doc(req, &crate_name, &version, target, &target_name)
    } else {
        rendering_time.step("redirect to crate");
        redirect_to_crate(req, &crate_name, &version)
    }
}
pub fn rustdoc_redirector_handler ( req : & mut Request ) -> IronResult < Response > { fn redirect_to_doc ( req : & Request , name : & str , vers : & str , target : Option < & str > , target_name : & str , ) -> IronResult < Response > { let mut url_str = if let Some ( target ) = target { format ! ( " " redirect_base ( req ) name vers target target_name ) } else { format ! ( " " redirect_base ( req ) name vers target_name ) } ; if let Some ( query ) = req . url . query ( ) { url_str . push ( '?' ) ; url_str . push_str ( query ) ; } let url = ctry ! ( req Url parse ( url_str ) ) ; let mut resp = Response :: with ( ( status :: Found , Redirect ( url ) ) ) ; resp . headers . set ( Expires ( HttpDate ( time :: now ( ) ) ) ) ; Ok ( resp ) } fn redirect_to_crate ( req : & Request , name : & str , vers : & str ) -> IronResult < Response > { let url = ctry ! ( req Url parse ( format ( " " redirect_base ( req ) name vers ) ) ) ; let mut resp = Response :: with ( ( status :: Found , Redirect ( url ) ) ) ; resp . headers . set ( Expires ( HttpDate ( time :: now ( ) ) ) ) ; Ok ( resp ) } let metrics = extension ! ( req Metrics ) . clone ( ) ; let mut rendering_time = RenderingTimesRecorder :: new ( & metrics . rustdoc_redirect_rendering_times ) ; // this unwrap is safe because iron urls are always able to use `path_segments` // i'm using this instead of `req.url.path()` to avoid allocating the Vec, and also to avoid // keeping the borrow alive into the return statement if req . url . as_ref ( ) . path_segments ( ) . unwrap ( ) . last ( ) . map_or ( false , | s | s . ends_with ( " " ) ) { // javascript files should be handled by the file server instead of erroneously // redirecting to the crate root page if req . url . as_ref ( ) . path_segments ( ) . unwrap ( ) . count ( ) > 2 { // this URL is actually from a crate-internal path, serve it there instead rendering_time . step ( " " ) ; return rustdoc_html_server_handler ( req ) ; } else { rendering_time . step ( " " ) ; let storage = extension ! ( req Storage ) ; let config = extension ! ( req Config ) ; let path = req . url . path ( ) ; let path = path . join ( " " ) ; return match File :: from_path ( & storage , & path , & config ) { Ok ( f ) => Ok ( f . serve ( ) ) , Err ( .. ) => Err ( Nope :: ResourceNotFound . into ( ) ) , } ; } } else if req . url . as_ref ( ) . path_segments ( ) . unwrap ( ) . last ( ) . map_or ( false , | s | s . ends_with ( " " ) ) { // route .ico files into their dedicated handler so that docs.rs's favicon is always // displayed rendering_time . step ( " " ) ; return super :: statics :: ico_handler ( req ) ; } let router = extension ! ( req Router ) ; let mut conn = extension ! ( req Pool ) . get ( ) ? ; // this handler should never called without crate pattern let crate_name = cexpect ! ( req router find ( " " ) ) ; let mut crate_name = percent_decode ( crate_name . as_bytes ( ) ) . decode_utf8 ( ) . unwrap_or_else ( | _ | crate_name . into ( ) ) . into_owned ( ) ; let req_version = router . find ( " " ) ; let mut target = router . find ( " " ) ; // it doesn't matter if the version that was given was exact or not, since we're redirecting // anyway rendering_time . step ( " " ) ; let v = match_version ( & mut conn , & crate_name , req_version ) ? ; if let Some ( new_name ) = v . corrected_name { // `match_version` checked against -/_ typos, so if we have a name here we should // use that instead crate_name = new_name ; } let ( version , id ) = v . version . into_parts ( ) ; // get target name and whether it has docs // FIXME: This is a bit inefficient but allowing us to use less code in general rendering_time . step ( " " ) ; let ( target_name , has_docs ) : ( String , bool ) = { let rows = ctry ! ( req conn query ( " " [ id ] ) ) ; ( rows [ 0 ] . get ( 0 ) , rows [ 0 ] . get ( 1 ) ) } ; if target == Some ( " " ) || target == Some ( & target_name ) { target = None ; } if has_docs { rendering_time . step ( " " ) ; redirect_to_doc ( req , & crate_name , & version , target , & target_name ) } else { rendering_time . step ( " " ) ; redirect_to_crate ( req , & crate_name , & version ) } }
Handler called for `/:crate` and `/:crate/:version` URLs.
Handler called for ` / : crate ` and ` / : crate / : version ` URLs .
req
&mut Request
req
&mut Request