@@ -15,13 +15,14 @@ use rari_doc::contributors::contributors_txt;
15
15
use rari_doc:: error:: DocError ;
16
16
use rari_doc:: issues:: { to_display_issues, IN_MEMORY , ISSUE_COUNTER_F } ;
17
17
use rari_doc:: pages:: json:: BuiltPage ;
18
- use rari_doc:: pages:: page:: { Page , PageBuilder , PageLike } ;
18
+ use rari_doc:: pages:: page:: { Page , PageBuilder , PageCategory , PageLike } ;
19
19
use rari_doc:: pages:: templates:: DocPage ;
20
20
use rari_doc:: pages:: types:: doc:: Doc ;
21
21
use rari_doc:: reader:: read_docs_parallel;
22
+ use rari_doc:: resolve:: { url_meta_from, UrlMeta } ;
22
23
use rari_tools:: error:: ToolError ;
23
24
use rari_tools:: fix:: issues:: fix_page;
24
- use rari_types:: globals:: { self , content_root, content_translated_root} ;
25
+ use rari_types:: globals:: { self , blog_root , content_root, content_translated_root} ;
25
26
use rari_types:: locale:: Locale ;
26
27
use rari_types:: Popularities ;
27
28
use rari_utils:: io:: read_to_string;
@@ -32,6 +33,10 @@ use tracing::{error, span, Level};
32
33
33
34
static REQ_COUNTER : AtomicU64 = AtomicU64 :: new ( 1 ) ;
34
35
36
+ static ASSET_EXTENSION : & [ & str ] = & [
37
+ "gif" , "jpeg" , "jpg" , "mp3" , "mp4" , "ogg" , "png" , "svg" , "webm" , "webp" , "woff2" ,
38
+ ] ;
39
+
35
40
tokio:: task_local! {
36
41
static SERVER_ISSUE_COUNTER : AtomicI64 ;
37
42
}
@@ -49,8 +54,16 @@ struct SearchItem {
49
54
}
50
55
51
56
async fn handler ( req : Request ) -> Response < Body > {
52
- if req. uri ( ) . path ( ) . ends_with ( "/contributors.txt" ) {
57
+ let path = req. uri ( ) . path ( ) ;
58
+ if path. ends_with ( "/contributors.txt" ) {
53
59
get_contributors_handler ( req) . await . into_response ( )
60
+ } else if ASSET_EXTENSION . contains (
61
+ & path
62
+ . rsplit_once ( '.' )
63
+ . map ( |( _, ext) | ext)
64
+ . unwrap_or_default ( ) ,
65
+ ) {
66
+ get_file_handler ( req) . await . into_response ( )
54
67
} else {
55
68
get_json_handler ( req) . await . into_response ( )
56
69
}
@@ -81,6 +94,46 @@ async fn wrapped_fix_issues(
81
94
. await
82
95
}
83
96
97
+ async fn get_file_handler ( req : Request ) -> Result < Response , AppError > {
98
+ let url = req. uri ( ) . path ( ) ;
99
+ tracing:: info!( "(asset) {}" , url) ;
100
+ let UrlMeta {
101
+ page_category,
102
+ slug,
103
+ ..
104
+ } = url_meta_from ( url) ?;
105
+
106
+ // Blog author avatars are special.
107
+ if matches ! ( page_category, PageCategory :: BlogPost ) && slug. starts_with ( "author/" ) {
108
+ if let Some ( blog_root_parent) = blog_root ( ) {
109
+ let path = blog_root_parent
110
+ . join ( "authors" )
111
+ . join ( slug. strip_prefix ( "author/" ) . unwrap ( ) ) ;
112
+ return Ok ( ServeFile :: new ( path) . oneshot ( req) . await . into_response ( ) ) ;
113
+ }
114
+ }
115
+
116
+ if let Some ( last_slash) = url. rfind ( '/' ) {
117
+ let doc_url = & url[ ..( if matches ! (
118
+ page_category,
119
+ PageCategory :: BlogPost | PageCategory :: Curriculum
120
+ ) {
121
+ // Add trailing slash for paths that require it.
122
+ last_slash + 1
123
+ } else {
124
+ last_slash
125
+ } ) ] ;
126
+
127
+ let file_name = & url[ last_slash + 1 ..] ;
128
+ let page = Page :: from_url_with_fallback ( doc_url) ?;
129
+ let path = page. full_path ( ) . with_file_name ( file_name) ;
130
+
131
+ return Ok ( ServeFile :: new ( path) . oneshot ( req) . await . into_response ( ) ) ;
132
+ }
133
+
134
+ Ok ( ( StatusCode :: BAD_REQUEST ) . into_response ( ) )
135
+ }
136
+
84
137
async fn get_json_handler ( req : Request ) -> Result < Response , AppError > {
85
138
let url = req. uri ( ) . path ( ) ;
86
139
let req_id = REQ_COUNTER . fetch_add ( 1 , std:: sync:: atomic:: Ordering :: Relaxed ) ;
0 commit comments