@@ -723,10 +723,24 @@ fn generate_rustdoc_path_for_url(
723723 && !path. is_empty ( )
724724 && path != INDEX_HTML
725725 {
726- // ust juse the given inner to start, if:
727- // * it's not empty
728- // * it's not just "index.html"
729- path. to_string ( )
726+ if let Some ( target_name) = target_name
727+ && path == target_name
728+ {
729+ // Sometimes people add a path that is just the target name.
730+ // This matches our `rustdoc_redirector_handler` route,
731+ // without trailing slash (`/{name}/{version}/{target}`).
732+ //
733+ // Even though the rustdoc html handler would also be capable
734+ // handling this input, we want to redirect to the trailing
735+ // slash version (`/{name}/{version}/{target}/`),
736+ // so they are separate.
737+ format ! ( "{}/" , target_name)
738+ } else {
739+ // just use the given inner to start, if:
740+ // * it's not empty
741+ // * it's not just "index.html"
742+ path. to_string ( )
743+ }
730744 } else if let Some ( target_name) = target_name {
731745 // after having no usable given path, we generate one with the
732746 // target name, if we have one.
@@ -1600,4 +1614,48 @@ mod tests {
16001614 assert_eq ! ( params. doc_target( ) , Some ( DEFAULT_TARGET ) ) ;
16011615 assert_eq ! ( params. inner_path( ) , "dummy/struct.Dummy.html" ) ;
16021616 }
1617+
1618+ #[ test]
1619+ fn test_parse_something ( ) {
1620+ // test for https://github.com/rust-lang/docs.rs/issues/2989
1621+ let params = dbg ! (
1622+ RustdocParams :: new( KRATE )
1623+ . with_page_kind( PageKind :: Rustdoc )
1624+ . try_with_original_uri( format!( "/{KRATE}/latest/{KRATE}" ) )
1625+ . unwrap( )
1626+ . with_req_version( ReqVersion :: Latest )
1627+ . with_doc_target( KRATE )
1628+ ) ;
1629+
1630+ assert_eq ! ( params. rustdoc_url( ) , "/krate/latest/krate/" ) ;
1631+
1632+ let params = dbg ! (
1633+ params
1634+ . with_target_name( KRATE )
1635+ . with_default_target( DEFAULT_TARGET )
1636+ . with_doc_targets( TARGETS . iter( ) . cloned( ) )
1637+ ) ;
1638+
1639+ assert_eq ! ( params. rustdoc_url( ) , "/krate/latest/krate/" ) ;
1640+ }
1641+
1642+ #[ test_case( Some ( PageKind :: Rustdoc ) ) ]
1643+ #[ test_case( None ) ]
1644+ fn test_only_target_name_without_slash ( page_kind : Option < PageKind > ) {
1645+ // test for https://github.com/rust-lang/docs.rs/issues/2989
1646+ let params = RustdocParams :: new ( KRATE )
1647+ . with_maybe_page_kind ( page_kind)
1648+ . try_with_original_uri ( "/dummy/latest/dummy" )
1649+ . unwrap ( )
1650+ . with_req_version ( ReqVersion :: Latest )
1651+ . with_maybe_doc_target ( None :: < String > )
1652+ . with_inner_path ( KRATE )
1653+ . with_default_target ( DEFAULT_TARGET )
1654+ . with_target_name ( KRATE )
1655+ . with_doc_targets ( TARGETS . iter ( ) . cloned ( ) ) ;
1656+
1657+ dbg ! ( & params) ;
1658+
1659+ assert_eq ! ( params. rustdoc_url( ) , "/krate/latest/krate/" ) ;
1660+ }
16031661}
0 commit comments