@@ -17,7 +17,6 @@ use crate::{
17
17
use anyhow:: { Context , Result } ;
18
18
use axum:: {
19
19
extract:: { Extension , Path } ,
20
- http:: Uri ,
21
20
response:: { IntoResponse , Response as AxumResponse } ,
22
21
} ;
23
22
use chrono:: { DateTime , Utc } ;
@@ -491,12 +490,11 @@ impl_axum_webpage! {
491
490
}
492
491
493
492
#[ tracing:: instrument]
494
- pub ( crate ) async fn get_all_platforms (
493
+ pub ( crate ) async fn get_all_platforms_inner (
495
494
Path ( params) : Path < RustdocHtmlParams > ,
496
495
Extension ( pool) : Extension < Pool > ,
497
- uri : Uri ,
496
+ is_crate_root : bool ,
498
497
) -> AxumResult < AxumResponse > {
499
- let is_crate_root = uri. path ( ) . starts_with ( "/-/menus/platforms/crate/" ) ;
500
498
let req_path: String = params. path . unwrap_or_default ( ) ;
501
499
let req_path: Vec < & str > = req_path. split ( '/' ) . collect ( ) ;
502
500
@@ -590,16 +588,23 @@ pub(crate) async fn get_all_platforms(
590
588
. unwrap_or ( & releases[ 0 ] ) ;
591
589
592
590
// The path within this crate version's rustdoc output
591
+ let inner;
593
592
let ( target, inner_path) = {
594
593
let mut inner_path = req_path. clone ( ) ;
595
594
596
- let target = if inner_path. len ( ) > 1 && doc_targets. iter ( ) . any ( |s| s == inner_path[ 0 ] ) {
597
- inner_path. remove ( 0 )
595
+ let target = if inner_path. len ( ) > 1
596
+ && doc_targets
597
+ . iter ( )
598
+ . any ( |s| Some ( s) == params. target . as_ref ( ) )
599
+ {
600
+ inner_path. remove ( 0 ) ;
601
+ params. target . as_ref ( ) . unwrap ( )
598
602
} else {
599
603
""
600
604
} ;
601
605
602
- ( target, inner_path. join ( "/" ) )
606
+ inner = inner_path. join ( "/" ) ;
607
+ ( target, inner. trim_end_matches ( '/' ) )
603
608
} ;
604
609
let inner_path = if inner_path. is_empty ( ) {
605
610
format ! ( "{name}/index.html" )
@@ -630,6 +635,21 @@ pub(crate) async fn get_all_platforms(
630
635
Ok ( res. into_response ( ) )
631
636
}
632
637
638
+ pub ( crate ) async fn get_all_platforms_root (
639
+ Path ( mut params) : Path < RustdocHtmlParams > ,
640
+ pool : Extension < Pool > ,
641
+ ) -> AxumResult < AxumResponse > {
642
+ params. path = None ;
643
+ get_all_platforms_inner ( Path ( params) , pool, true ) . await
644
+ }
645
+
646
+ pub ( crate ) async fn get_all_platforms (
647
+ params : Path < RustdocHtmlParams > ,
648
+ pool : Extension < Pool > ,
649
+ ) -> AxumResult < AxumResponse > {
650
+ get_all_platforms_inner ( params, pool, false ) . await
651
+ }
652
+
633
653
#[ cfg( test) ]
634
654
mod tests {
635
655
use super :: * ;
@@ -1242,22 +1262,26 @@ mod tests {
1242
1262
1243
1263
#[ test]
1244
1264
fn platform_links_are_direct_and_without_nofollow ( ) {
1245
- fn check_links ( response_text : String , ajax : bool , should_contain_redirect : bool ) {
1246
- let platform_links: Vec < ( String , String ) > = kuchikiki:: parse_html ( )
1265
+ fn check_links (
1266
+ response_text : String ,
1267
+ ajax : bool ,
1268
+ should_contain_redirect : bool ,
1269
+ ) -> Vec < ( String , String , String ) > {
1270
+ let platform_links: Vec < ( String , String , String ) > = kuchikiki:: parse_html ( )
1247
1271
. one ( response_text)
1248
1272
. select ( & format ! ( r#"{}li a"# , if ajax { "" } else { "#platforms " } ) )
1249
1273
. expect ( "invalid selector" )
1250
1274
. map ( |el| {
1251
1275
let attributes = el. attributes . borrow ( ) ;
1252
1276
let url = attributes. get ( "href" ) . expect ( "href" ) . to_string ( ) ;
1253
1277
let rel = attributes. get ( "rel" ) . unwrap_or ( "" ) . to_string ( ) ;
1254
- ( url, rel)
1278
+ ( el . text_contents ( ) , url, rel)
1255
1279
} )
1256
1280
. collect ( ) ;
1257
1281
1258
1282
assert_eq ! ( platform_links. len( ) , 2 ) ;
1259
1283
1260
- for ( url, rel) in platform_links {
1284
+ for ( _ , url, rel) in & platform_links {
1261
1285
assert_eq ! (
1262
1286
url. contains( "/target-redirect/" ) ,
1263
1287
should_contain_redirect,
@@ -1269,25 +1293,53 @@ mod tests {
1269
1293
assert_eq ! ( rel, "nofollow" ) ;
1270
1294
}
1271
1295
}
1296
+ return platform_links;
1272
1297
}
1273
1298
1274
1299
fn run_check_links (
1275
1300
env : & TestEnvironment ,
1276
1301
url : & str ,
1277
1302
extra : & str ,
1278
1303
should_contain_redirect : bool ,
1304
+ ) {
1305
+ run_check_links_redir (
1306
+ env,
1307
+ url,
1308
+ extra,
1309
+ should_contain_redirect,
1310
+ should_contain_redirect,
1311
+ )
1312
+ }
1313
+
1314
+ fn run_check_links_redir (
1315
+ env : & TestEnvironment ,
1316
+ url : & str ,
1317
+ extra : & str ,
1318
+ should_contain_redirect : bool ,
1319
+ ajax_should_contain_redirect : bool ,
1279
1320
) {
1280
1321
let response = env. frontend ( ) . get ( url) . send ( ) . unwrap ( ) ;
1281
1322
assert ! ( response. status( ) . is_success( ) ) ;
1282
- check_links ( response. text ( ) . unwrap ( ) , false , should_contain_redirect) ;
1323
+ let list1 = check_links ( response. text ( ) . unwrap ( ) , false , should_contain_redirect) ;
1283
1324
// Same test with AJAX endpoint.
1284
1325
let response = env
1285
1326
. frontend ( )
1286
1327
. get ( & format ! ( "/-/menus/platforms{url}{extra}" ) )
1287
1328
. send ( )
1288
1329
. unwrap ( ) ;
1289
1330
assert ! ( response. status( ) . is_success( ) ) ;
1290
- check_links ( response. text ( ) . unwrap ( ) , true , should_contain_redirect) ;
1331
+ let list2 = check_links ( response. text ( ) . unwrap ( ) , true , ajax_should_contain_redirect) ;
1332
+ if should_contain_redirect == ajax_should_contain_redirect {
1333
+ assert_eq ! ( list1, list2) ;
1334
+ } else {
1335
+ // If redirects differ, we only check platform names.
1336
+ assert ! (
1337
+ list1. iter( ) . zip( & list2) . all( |( a, b) | a. 0 == b. 0 ) ,
1338
+ "{:?} != {:?}" ,
1339
+ list1,
1340
+ list2,
1341
+ ) ;
1342
+ }
1291
1343
}
1292
1344
1293
1345
wrapper ( |env| {
@@ -1299,8 +1351,16 @@ mod tests {
1299
1351
. rustdoc_file ( "x86_64-pc-windows-msvc/dummy/struct.A.html" )
1300
1352
. default_target ( "x86_64-unknown-linux-gnu" )
1301
1353
. add_target ( "x86_64-pc-windows-msvc" )
1354
+ . source_file ( "README.md" , b"storage readme" )
1302
1355
. create ( ) ?;
1303
1356
1357
+ // FIXME: For some reason, there are target-redirects on non-AJAX lists on docs.rs
1358
+ // crate pages other than the "default" one.
1359
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/features" , "" , true , false ) ;
1360
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/builds" , "" , true , false ) ;
1361
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/source/" , "" , true , false ) ;
1362
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/source/README.md" , "" , true , false ) ;
1363
+
1304
1364
run_check_links ( env, "/crate/dummy/0.4.0" , "" , false ) ;
1305
1365
run_check_links ( env, "/dummy/latest/dummy" , "/" , true ) ;
1306
1366
run_check_links ( env, "/dummy/0.4.0/x86_64-pc-windows-msvc/dummy" , "/" , true ) ;
0 commit comments