1
1
//! rustdoc handler
2
2
3
- use super :: crate_details:: CrateDetails ;
4
- use super :: error:: Nope ;
5
- use super :: file:: File ;
6
- use super :: metrics;
7
- use super :: page:: Page ;
8
- use super :: redirect_base;
9
- use super :: { match_version, MatchSemver } ;
10
- use crate :: db:: Pool ;
11
- use crate :: utils;
12
- use crate :: Config ;
13
- use iron:: headers:: { CacheControl , CacheDirective , Expires , HttpDate } ;
14
- use iron:: modifiers:: Redirect ;
15
- use iron:: prelude:: * ;
16
- use iron:: Handler ;
17
- use iron:: { status, Url } ;
3
+ use crate :: {
4
+ db:: Pool ,
5
+ impl_webpage, utils,
6
+ web:: {
7
+ crate_details:: CrateDetails , error:: Nope , file:: File , match_version, metrics,
8
+ page:: WebPage , redirect_base, MatchSemver ,
9
+ } ,
10
+ Config ,
11
+ } ;
12
+ use iron:: {
13
+ headers:: { CacheControl , CacheDirective , Expires , HttpDate } ,
14
+ modifiers:: Redirect ,
15
+ status, Handler , IronError , IronResult , Plugin , Request , Response , Url ,
16
+ } ;
18
17
use postgres:: Connection ;
19
18
use router:: Router ;
20
- use serde:: ser:: { Serialize , SerializeStruct , Serializer } ;
21
-
22
- #[ derive( Debug , Default ) ]
23
- struct RustdocPage {
24
- head : String ,
25
- body : String ,
26
- body_class : String ,
27
- name : String ,
28
- full : String ,
29
- version : String ,
30
- description : Option < String > ,
31
- crate_details : Option < CrateDetails > ,
32
- }
33
-
34
- impl Serialize for RustdocPage {
35
- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
36
- where
37
- S : Serializer ,
38
- {
39
- let mut state = serializer. serialize_struct ( "RustdocPage" , 9 ) ?;
40
- state. serialize_field ( "rustdoc_head" , & self . head ) ?;
41
- state. serialize_field ( "rustdoc_body" , & self . body ) ?;
42
- state. serialize_field ( "rustdoc_body_class" , & self . body_class ) ?;
43
- state. serialize_field ( "rustdoc_full" , & self . full ) ?;
44
- state. serialize_field ( "rustdoc_status" , & true ) ?;
45
- state. serialize_field ( "name" , & self . name ) ?;
46
- state. serialize_field ( "version" , & self . version ) ?;
47
- state. serialize_field ( "description" , & self . description ) ?;
48
- state. serialize_field ( "crate_details" , & self . crate_details ) ?;
49
-
50
- state. end ( )
51
- }
52
- }
19
+ use serde:: Serialize ;
53
20
54
21
#[ derive( Clone ) ]
55
22
pub struct RustLangRedirector {
@@ -63,6 +30,7 @@ impl RustLangRedirector {
63
30
. join ( target)
64
31
. expect ( "failed to append crate name to rust-lang.org base URL" ) ;
65
32
let url = Url :: from_generic_url ( url) . expect ( "failed to convert url::Url to iron::Url" ) ;
33
+
66
34
Self { url }
67
35
}
68
36
}
@@ -215,6 +183,22 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
215
183
}
216
184
}
217
185
186
+ #[ derive( Debug , Clone , PartialEq , Serialize ) ]
187
+ struct RustdocPage {
188
+ latest_path : String ,
189
+ latest_version : String ,
190
+ inner_path : String ,
191
+ is_latest_version : bool ,
192
+ rustdoc_head : String ,
193
+ rustdoc_body : String ,
194
+ rustdoc_body_class : String ,
195
+ krate : CrateDetails ,
196
+ }
197
+
198
+ impl_webpage ! {
199
+ RustdocPage = "rustdoc/page.html" ,
200
+ }
201
+
218
202
/// Serves documentation generated by rustdoc.
219
203
///
220
204
/// This includes all HTML files for an individual crate, as well as the `search-index.js`, which is
@@ -289,11 +273,11 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
289
273
290
274
// Get the crate's details from the database
291
275
// NOTE: we know this crate must exist because we just checked it above (or else `match_version` is buggy)
292
- let crate_details = cexpect ! ( req, CrateDetails :: new( & conn, & name, & version) ) ;
276
+ let krate = cexpect ! ( req, CrateDetails :: new( & conn, & name, & version) ) ;
293
277
294
278
// if visiting the full path to the default target, remove the target from the path
295
279
// expects a req_path that looks like `[/:target]/.*`
296
- if req_path. get ( 0 ) . copied ( ) == Some ( & crate_details . metadata . default_target ) {
280
+ if req_path. get ( 0 ) . copied ( ) == Some ( & krate . metadata . default_target ) {
297
281
return redirect ( & name, & version, & req_path[ 1 ..] ) ;
298
282
}
299
283
@@ -334,19 +318,20 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
334
318
335
319
let file_content = ctry ! ( req, String :: from_utf8( file. 0 . content) ) ;
336
320
// Extract the head and body of the rustdoc file so that we can insert it into our own html
337
- let ( head, body, mut body_class) = ctry ! ( req, utils:: extract_head_and_body( & file_content) ) ;
321
+ let ( rustdoc_head, rustdoc_body, mut rustdoc_body_class) =
322
+ ctry ! ( req, utils:: extract_head_and_body( & file_content) ) ;
338
323
339
324
// Add the `rustdoc` classes to the html body
340
- if body_class . is_empty ( ) {
341
- body_class = "rustdoc container-rustdoc" . to_string ( ) ;
325
+ if rustdoc_body_class . is_empty ( ) {
326
+ rustdoc_body_class = "rustdoc container-rustdoc" . to_string ( ) ;
342
327
} else {
343
328
// rustdoc adds its own "rustdoc" class to the body
344
- body_class . push_str ( " container-rustdoc" ) ;
329
+ rustdoc_body_class . push_str ( " container-rustdoc" ) ;
345
330
}
346
331
347
332
rendering_time. step ( "find latest path" ) ;
348
333
349
- let latest_release = crate_details . latest_release ( ) ;
334
+ let latest_release = krate . latest_release ( ) ;
350
335
351
336
// Get the latest version of the crate
352
337
let latest_version = latest_release. version . to_owned ( ) ;
@@ -366,7 +351,7 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
366
351
"/{}/{}/{}" ,
367
352
name,
368
353
latest_version,
369
- path_for_version( & latest_path, & crate_details . doc_targets, & conn, & config)
354
+ path_for_version( & latest_path, & krate . doc_targets, & conn, & config)
370
355
)
371
356
} else {
372
357
format ! ( "/crate/{}/{}" , name, latest_version)
@@ -381,35 +366,25 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
381
366
// Drop the `rustdoc/:crate/:version[/:platform]` prefix
382
367
inner_path. drain ( ..3 ) . for_each ( drop) ;
383
368
384
- if inner_path. len ( ) > 1 && crate_details . doc_targets . iter ( ) . any ( |s| s == inner_path[ 0 ] ) {
369
+ if inner_path. len ( ) > 1 && krate . doc_targets . iter ( ) . any ( |s| s == inner_path[ 0 ] ) {
385
370
inner_path. remove ( 0 ) ;
386
371
}
387
372
388
373
inner_path. join ( "/" )
389
374
} ;
390
375
391
376
// Build the page of documentation
392
- let content = RustdocPage {
393
- head,
394
- body,
395
- body_class,
396
- name,
397
- full : file_content,
398
- version,
399
- crate_details : Some ( crate_details) ,
400
- ..Default :: default ( )
401
- } ;
402
-
403
- // Build the page served to the user while setting options for templating
404
- Page :: new ( content)
405
- . set_true ( "show_package_navigation" )
406
- . set_true ( "package_navigation_documentation_tab" )
407
- . set_true ( "package_navigation_show_platforms_tab" )
408
- . set_bool ( "is_latest_version" , is_latest_version)
409
- . set ( "latest_path" , & latest_path)
410
- . set ( "latest_version" , & latest_version)
411
- . set ( "inner_path" , & inner_path)
412
- . to_resp ( "rustdoc" )
377
+ RustdocPage {
378
+ latest_path,
379
+ latest_version,
380
+ inner_path,
381
+ is_latest_version,
382
+ rustdoc_head,
383
+ rustdoc_body,
384
+ rustdoc_body_class,
385
+ krate,
386
+ }
387
+ . into_response ( req)
413
388
}
414
389
415
390
/// Checks whether the given path exists.
@@ -606,12 +581,9 @@ impl Handler for SharedResourceHandler {
606
581
607
582
#[ cfg( test) ]
608
583
mod test {
609
- use super :: * ;
610
584
use crate :: test:: * ;
611
- use chrono:: Utc ;
612
585
use kuchiki:: traits:: TendrilSink ;
613
586
use reqwest:: StatusCode ;
614
- use serde_json:: json;
615
587
use std:: { collections:: BTreeMap , iter:: FromIterator } ;
616
588
617
589
fn try_latest_version_redirect (
@@ -1455,101 +1427,4 @@ mod test {
1455
1427
Ok ( ( ) )
1456
1428
} )
1457
1429
}
1458
-
1459
- #[ test]
1460
- fn serialize_rustdoc_page ( ) {
1461
- let time = Utc :: now ( ) ;
1462
-
1463
- let details = json ! ( {
1464
- "name" : "rcc" ,
1465
- "version" : "100.0.0" ,
1466
- "description" : null,
1467
- "authors" : [ ] ,
1468
- "owners" : [ ] ,
1469
- "authors_json" : null,
1470
- "dependencies" : null,
1471
- "release_time" : super :: super :: duration_to_str( time) ,
1472
- "build_status" : true ,
1473
- "last_successful_build" : null,
1474
- "rustdoc_status" : true ,
1475
- "repository_url" : null,
1476
- "homepage_url" : null,
1477
- "keywords" : null,
1478
- "have_examples" : true ,
1479
- "target_name" : "x86_64-unknown-linux-gnu" ,
1480
- "releases" : [ ] ,
1481
- "github" : true ,
1482
- "yanked" : false ,
1483
- "github_stars" : null,
1484
- "github_forks" : null,
1485
- "github_issues" : null,
1486
- "metadata" : {
1487
- "name" : "serde" ,
1488
- "version" : "1.0.0" ,
1489
- "description" : "serde does stuff" ,
1490
- "target_name" : null,
1491
- "rustdoc_status" : true ,
1492
- "default_target" : "x86_64-unknown-linux-gnu"
1493
- } ,
1494
- "is_library" : true ,
1495
- "doc_targets" : [ ] ,
1496
- "license" : null,
1497
- "documentation_url" : null
1498
- } ) ;
1499
-
1500
- let mut page = RustdocPage {
1501
- head : "<head><title>Whee</title></head>" . to_string ( ) ,
1502
- body : "<body><h1>idk</h1></body>" . to_string ( ) ,
1503
- body_class : "docsrs-body" . to_string ( ) ,
1504
- name : "rcc" . to_string ( ) ,
1505
- full : "??" . to_string ( ) ,
1506
- version : "100.0.100" . to_string ( ) ,
1507
- description : Some ( "a Rust compiler in C. Wait, maybe the other way around" . to_string ( ) ) ,
1508
- crate_details : Some ( CrateDetails :: default_tester ( time) ) ,
1509
- } ;
1510
-
1511
- let correct_json = json ! ( {
1512
- "rustdoc_head" : "<head><title>Whee</title></head>" ,
1513
- "rustdoc_body" : "<body><h1>idk</h1></body>" ,
1514
- "rustdoc_body_class" : "docsrs-body" ,
1515
- "rustdoc_full" : "??" ,
1516
- "rustdoc_status" : true ,
1517
- "name" : "rcc" ,
1518
- "version" : "100.0.100" ,
1519
- "description" : "a Rust compiler in C. Wait, maybe the other way around" ,
1520
- "crate_details" : details
1521
- } ) ;
1522
-
1523
- assert_eq ! ( correct_json, serde_json:: to_value( & page) . unwrap( ) ) ;
1524
-
1525
- page. description = None ;
1526
- let correct_json = json ! ( {
1527
- "rustdoc_head" : "<head><title>Whee</title></head>" ,
1528
- "rustdoc_body" : "<body><h1>idk</h1></body>" ,
1529
- "rustdoc_body_class" : "docsrs-body" ,
1530
- "rustdoc_full" : "??" ,
1531
- "rustdoc_status" : true ,
1532
- "name" : "rcc" ,
1533
- "version" : "100.0.100" ,
1534
- "description" : null,
1535
- "crate_details" : details
1536
- } ) ;
1537
-
1538
- assert_eq ! ( correct_json, serde_json:: to_value( & page) . unwrap( ) ) ;
1539
-
1540
- page. crate_details = None ;
1541
- let correct_json = json ! ( {
1542
- "rustdoc_head" : "<head><title>Whee</title></head>" ,
1543
- "rustdoc_body" : "<body><h1>idk</h1></body>" ,
1544
- "rustdoc_body_class" : "docsrs-body" ,
1545
- "rustdoc_full" : "??" ,
1546
- "rustdoc_status" : true ,
1547
- "name" : "rcc" ,
1548
- "version" : "100.0.100" ,
1549
- "description" : null,
1550
- "crate_details" : null
1551
- } ) ;
1552
-
1553
- assert_eq ! ( correct_json, serde_json:: to_value( & page) . unwrap( ) ) ;
1554
- }
1555
1430
}
0 commit comments