@@ -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 } ;
@@ -500,12 +499,11 @@ impl_axum_webpage! {
500
499
}
501
500
502
501
#[ tracing:: instrument]
503
- pub ( crate ) async fn get_all_platforms (
502
+ pub ( crate ) async fn get_all_platforms_inner (
504
503
Path ( params) : Path < RustdocHtmlParams > ,
505
504
Extension ( pool) : Extension < Pool > ,
506
- uri : Uri ,
505
+ is_crate_root : bool ,
507
506
) -> AxumResult < AxumResponse > {
508
- let is_crate_root = uri. path ( ) . starts_with ( "/-/menus/platforms/crate/" ) ;
509
507
let req_path: String = params. path . unwrap_or_default ( ) ;
510
508
let req_path: Vec < & str > = req_path. split ( '/' ) . collect ( ) ;
511
509
@@ -599,16 +597,23 @@ pub(crate) async fn get_all_platforms(
599
597
. unwrap_or ( & releases[ 0 ] ) ;
600
598
601
599
// The path within this crate version's rustdoc output
600
+ let inner;
602
601
let ( target, inner_path) = {
603
602
let mut inner_path = req_path. clone ( ) ;
604
603
605
- let target = if inner_path. len ( ) > 1 && doc_targets. iter ( ) . any ( |s| s == inner_path[ 0 ] ) {
606
- inner_path. remove ( 0 )
604
+ let target = if inner_path. len ( ) > 1
605
+ && doc_targets
606
+ . iter ( )
607
+ . any ( |s| Some ( s) == params. target . as_ref ( ) )
608
+ {
609
+ inner_path. remove ( 0 ) ;
610
+ params. target . as_ref ( ) . unwrap ( )
607
611
} else {
608
612
""
609
613
} ;
610
614
611
- ( target, inner_path. join ( "/" ) )
615
+ inner = inner_path. join ( "/" ) ;
616
+ ( target, inner. trim_end_matches ( '/' ) )
612
617
} ;
613
618
let inner_path = if inner_path. is_empty ( ) {
614
619
format ! ( "{name}/index.html" )
@@ -639,6 +644,21 @@ pub(crate) async fn get_all_platforms(
639
644
Ok ( res. into_response ( ) )
640
645
}
641
646
647
+ pub ( crate ) async fn get_all_platforms_root (
648
+ Path ( mut params) : Path < RustdocHtmlParams > ,
649
+ pool : Extension < Pool > ,
650
+ ) -> AxumResult < AxumResponse > {
651
+ params. path = None ;
652
+ get_all_platforms_inner ( Path ( params) , pool, true ) . await
653
+ }
654
+
655
+ pub ( crate ) async fn get_all_platforms (
656
+ params : Path < RustdocHtmlParams > ,
657
+ pool : Extension < Pool > ,
658
+ ) -> AxumResult < AxumResponse > {
659
+ get_all_platforms_inner ( params, pool, false ) . await
660
+ }
661
+
642
662
#[ cfg( test) ]
643
663
mod tests {
644
664
use super :: * ;
@@ -1251,22 +1271,26 @@ mod tests {
1251
1271
1252
1272
#[ test]
1253
1273
fn platform_links_are_direct_and_without_nofollow ( ) {
1254
- fn check_links ( response_text : String , ajax : bool , should_contain_redirect : bool ) {
1255
- let platform_links: Vec < ( String , String ) > = kuchikiki:: parse_html ( )
1274
+ fn check_links (
1275
+ response_text : String ,
1276
+ ajax : bool ,
1277
+ should_contain_redirect : bool ,
1278
+ ) -> Vec < ( String , String , String ) > {
1279
+ let platform_links: Vec < ( String , String , String ) > = kuchikiki:: parse_html ( )
1256
1280
. one ( response_text)
1257
1281
. select ( & format ! ( r#"{}li a"# , if ajax { "" } else { "#platforms " } ) )
1258
1282
. expect ( "invalid selector" )
1259
1283
. map ( |el| {
1260
1284
let attributes = el. attributes . borrow ( ) ;
1261
1285
let url = attributes. get ( "href" ) . expect ( "href" ) . to_string ( ) ;
1262
1286
let rel = attributes. get ( "rel" ) . unwrap_or ( "" ) . to_string ( ) ;
1263
- ( url, rel)
1287
+ ( el . text_contents ( ) , url, rel)
1264
1288
} )
1265
1289
. collect ( ) ;
1266
1290
1267
1291
assert_eq ! ( platform_links. len( ) , 2 ) ;
1268
1292
1269
- for ( url, rel) in platform_links {
1293
+ for ( _ , url, rel) in & platform_links {
1270
1294
assert_eq ! (
1271
1295
url. contains( "/target-redirect/" ) ,
1272
1296
should_contain_redirect,
@@ -1278,25 +1302,53 @@ mod tests {
1278
1302
assert_eq ! ( rel, "nofollow" ) ;
1279
1303
}
1280
1304
}
1305
+ platform_links
1281
1306
}
1282
1307
1283
1308
fn run_check_links (
1284
1309
env : & TestEnvironment ,
1285
1310
url : & str ,
1286
1311
extra : & str ,
1287
1312
should_contain_redirect : bool ,
1313
+ ) {
1314
+ run_check_links_redir (
1315
+ env,
1316
+ url,
1317
+ extra,
1318
+ should_contain_redirect,
1319
+ should_contain_redirect,
1320
+ )
1321
+ }
1322
+
1323
+ fn run_check_links_redir (
1324
+ env : & TestEnvironment ,
1325
+ url : & str ,
1326
+ extra : & str ,
1327
+ should_contain_redirect : bool ,
1328
+ ajax_should_contain_redirect : bool ,
1288
1329
) {
1289
1330
let response = env. frontend ( ) . get ( url) . send ( ) . unwrap ( ) ;
1290
1331
assert ! ( response. status( ) . is_success( ) ) ;
1291
- check_links ( response. text ( ) . unwrap ( ) , false , should_contain_redirect) ;
1332
+ let list1 = check_links ( response. text ( ) . unwrap ( ) , false , should_contain_redirect) ;
1292
1333
// Same test with AJAX endpoint.
1293
1334
let response = env
1294
1335
. frontend ( )
1295
1336
. get ( & format ! ( "/-/menus/platforms{url}{extra}" ) )
1296
1337
. send ( )
1297
1338
. unwrap ( ) ;
1298
1339
assert ! ( response. status( ) . is_success( ) ) ;
1299
- check_links ( response. text ( ) . unwrap ( ) , true , should_contain_redirect) ;
1340
+ let list2 = check_links ( response. text ( ) . unwrap ( ) , true , ajax_should_contain_redirect) ;
1341
+ if should_contain_redirect == ajax_should_contain_redirect {
1342
+ assert_eq ! ( list1, list2) ;
1343
+ } else {
1344
+ // If redirects differ, we only check platform names.
1345
+ assert ! (
1346
+ list1. iter( ) . zip( & list2) . all( |( a, b) | a. 0 == b. 0 ) ,
1347
+ "{:?} != {:?}" ,
1348
+ list1,
1349
+ list2,
1350
+ ) ;
1351
+ }
1300
1352
}
1301
1353
1302
1354
wrapper ( |env| {
@@ -1308,8 +1360,16 @@ mod tests {
1308
1360
. rustdoc_file ( "x86_64-pc-windows-msvc/dummy/struct.A.html" )
1309
1361
. default_target ( "x86_64-unknown-linux-gnu" )
1310
1362
. add_target ( "x86_64-pc-windows-msvc" )
1363
+ . source_file ( "README.md" , b"storage readme" )
1311
1364
. create ( ) ?;
1312
1365
1366
+ // FIXME: For some reason, there are target-redirects on non-AJAX lists on docs.rs
1367
+ // crate pages other than the "default" one.
1368
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/features" , "" , true , false ) ;
1369
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/builds" , "" , true , false ) ;
1370
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/source/" , "" , true , false ) ;
1371
+ run_check_links_redir ( env, "/crate/dummy/0.4.0/source/README.md" , "" , true , false ) ;
1372
+
1313
1373
run_check_links ( env, "/crate/dummy/0.4.0" , "" , false ) ;
1314
1374
run_check_links ( env, "/dummy/latest/dummy" , "/" , true ) ;
1315
1375
run_check_links ( env, "/dummy/0.4.0/x86_64-pc-windows-msvc/dummy" , "/" , true ) ;
0 commit comments