@@ -39,8 +39,11 @@ pub struct Document {
39
39
}
40
40
41
41
impl Document {
42
- pub async fn from_path ( path : & PathBuf ) -> anyhow:: Result < Document > {
43
- let contents = tokio:: fs:: read_to_string ( & path) . await ?;
42
+ pub async fn from_path ( path : & PathBuf ) -> anyhow:: Result < Document , std:: io:: Error > {
43
+ let contents = match tokio:: fs:: read_to_string ( & path) . await {
44
+ Ok ( contents) => contents,
45
+ Err ( _) => String :: from ( "<h3>Failed to find your requested document!</h3>" ) ,
46
+ } ;
44
47
45
48
let parts = contents. split ( "---" ) . collect :: < Vec < & str > > ( ) ;
46
49
@@ -271,35 +274,40 @@ impl Collection {
271
274
272
275
// renders document in layout
273
276
async fn render < ' a > ( & self , path : & ' a PathBuf , cluster : & Cluster ) -> Result < ResponseOk , Status > {
274
- let doc = Document :: from_path ( & path) . await . unwrap ( ) ;
275
- let index = self . open_index ( doc. path ) ;
277
+ match Document :: from_path ( & path) . await {
278
+ Ok ( doc) => {
279
+ let index = self . open_index ( doc. path ) ;
280
+
281
+ let user = if cluster. context . user . is_anonymous ( ) {
282
+ None
283
+ } else {
284
+ Some ( cluster. context . user . clone ( ) )
285
+ } ;
286
+
287
+ let mut layout = crate :: templates:: Layout :: new ( & doc. title , Some ( cluster) ) ;
288
+ if let Some ( image) = doc. image {
289
+ layout. image ( & config:: asset_url ( image. into ( ) ) ) ;
290
+ }
291
+ if let Some ( description) = & doc. description {
292
+ layout. description ( description) ;
293
+ }
294
+ if let Some ( user) = & user {
295
+ layout. user ( user) ;
296
+ }
276
297
277
- let user = if cluster . context . user . is_anonymous ( ) {
278
- None
279
- } else {
280
- Some ( cluster . context . user . clone ( ) )
281
- } ;
298
+ let layout = layout
299
+ . nav_title ( & self . name )
300
+ . nav_links ( & index )
301
+ . toc_links ( & doc . toc_links )
302
+ . footer ( cluster . context . marketing_footer . to_string ( ) ) ;
282
303
283
- let mut layout = crate :: templates:: Layout :: new ( & doc. title , Some ( cluster) ) ;
284
- if let Some ( image) = doc. image {
285
- layout. image ( & config:: asset_url ( image. into ( ) ) ) ;
286
- }
287
- if let Some ( description) = & doc. description {
288
- layout. description ( description) ;
289
- }
290
- if let Some ( user) = & user {
291
- layout. user ( user) ;
304
+ Ok ( ResponseOk (
305
+ layout. render ( crate :: templates:: Article { content : doc. html } ) ,
306
+ ) )
307
+ }
308
+ // Return page not found on bad path
309
+ _ => Err ( Status :: NotFound ) ,
292
310
}
293
-
294
- let layout = layout
295
- . nav_title ( & self . name )
296
- . nav_links ( & index)
297
- . toc_links ( & doc. toc_links )
298
- . footer ( cluster. context . marketing_footer . to_string ( ) ) ;
299
-
300
- Ok ( ResponseOk (
301
- layout. render ( crate :: templates:: Article { content : doc. html } ) ,
302
- ) )
303
311
}
304
312
}
305
313
@@ -534,4 +542,17 @@ This is the end of the markdown
534
542
)
535
543
}
536
544
}
545
+
546
+ #[ sqlx:: test]
547
+ async fn doc_not_found ( ) {
548
+ let client = Client :: tracked ( rocket ( ) . await ) . await . unwrap ( ) ;
549
+ let req = client. get ( "/docs/not_a_doc" ) ;
550
+ let rsp = req. dispatch ( ) . await ;
551
+
552
+ assert ! (
553
+ rsp. status( ) == Status :: NotFound ,
554
+ "Returned status {:?}" ,
555
+ rsp. status( )
556
+ ) ;
557
+ }
537
558
}
0 commit comments