@@ -3,11 +3,14 @@ use std::str::FromStr;
3
3
use std:: sync:: atomic:: AtomicU64 ;
4
4
use std:: sync:: Arc ;
5
5
6
+ use axum:: body:: Body ;
6
7
use axum:: extract:: { Path , Request , State } ;
7
- use axum:: http:: StatusCode ;
8
+ use axum:: http:: { header , StatusCode } ;
8
9
use axum:: response:: { IntoResponse , Response } ;
9
10
use axum:: routing:: get;
10
11
use axum:: { Json , Router } ;
12
+ use rari_doc:: cached_readers:: wiki_histories;
13
+ use rari_doc:: contributors:: contributors_txt;
11
14
use rari_doc:: error:: DocError ;
12
15
use rari_doc:: issues:: { to_display_issues, InMemoryLayer } ;
13
16
use rari_doc:: pages:: json:: BuiltPage ;
@@ -28,14 +31,23 @@ struct SearchItem {
28
31
title : String ,
29
32
url : String ,
30
33
}
34
+
35
+ async fn handler ( state : State < Arc < InMemoryLayer > > , req : Request ) -> Response < Body > {
36
+ if req. uri ( ) . path ( ) . ends_with ( "/contributors.txt" ) {
37
+ get_contributors_handler ( req) . await . into_response ( )
38
+ } else {
39
+ get_json_handler ( state, req) . await . into_response ( )
40
+ }
41
+ }
42
+
31
43
async fn get_json_handler (
32
44
State ( memory_layer) : State < Arc < InMemoryLayer > > ,
33
45
req : Request ,
34
46
) -> Result < Json < BuiltPage > , AppError > {
47
+ let url = req. uri ( ) . path ( ) ;
35
48
let req_id = REQ_COUNTER . fetch_add ( 1 , std:: sync:: atomic:: Ordering :: Relaxed ) ;
36
49
let span = span ! ( Level :: WARN , "serve" , req = req_id) ;
37
50
let _enter1 = span. enter ( ) ;
38
- let url = req. uri ( ) . path ( ) ;
39
51
let mut json = get_json ( url) ?;
40
52
if let BuiltPage :: Doc ( json_doc) = & mut json {
41
53
let m = memory_layer. get_events ( ) ;
@@ -66,6 +78,38 @@ fn get_json(url: &str) -> Result<BuiltPage, DocError> {
66
78
Ok ( json)
67
79
}
68
80
81
+ async fn get_contributors_handler ( req : Request ) -> impl IntoResponse {
82
+ let url = req. uri ( ) . path ( ) ;
83
+ match get_contributors ( url. strip_suffix ( "/contributors.txt" ) . unwrap_or ( url) ) {
84
+ Ok ( contributors_txt_str) => (
85
+ StatusCode :: OK ,
86
+ [ ( header:: CONTENT_TYPE , "text/plain" ) ] ,
87
+ contributors_txt_str,
88
+ )
89
+ . into_response ( ) ,
90
+ Err ( e) => {
91
+ tracing:: error!( "error generating contributors.txt for {url}: {e:?}" ) ;
92
+ ( StatusCode :: INTERNAL_SERVER_ERROR ) . into_response ( )
93
+ }
94
+ }
95
+ }
96
+
97
+ fn get_contributors ( url : & str ) -> Result < String , AppError > {
98
+ let page = Page :: from_url_with_fallback ( url) ?;
99
+ let json = page. build ( ) ?;
100
+ let github_file_url = if let BuiltPage :: Doc ( ref doc) = json {
101
+ & doc. doc . source . github_url
102
+ } else {
103
+ ""
104
+ } ;
105
+ let wiki_histories = wiki_histories ( ) ;
106
+ let wiki_history = wiki_histories
107
+ . get ( & page. locale ( ) )
108
+ . and_then ( |wh| wh. get ( page. slug ( ) ) ) ;
109
+ let contributors_txt_str = contributors_txt ( wiki_history, github_file_url) ;
110
+ Ok ( contributors_txt_str)
111
+ }
112
+
69
113
async fn get_search_index_handler (
70
114
Path ( locale) : Path < String > ,
71
115
) -> Result < Json < Vec < SearchItem > > , AppError > {
@@ -118,10 +162,11 @@ fn get_search_index(locale: Locale) -> Result<Vec<SearchItem>, DocError> {
118
162
Ok ( out)
119
163
}
120
164
165
+ #[ derive( Debug ) ]
121
166
struct AppError ( anyhow:: Error ) ;
122
167
123
168
impl IntoResponse for AppError {
124
- fn into_response ( self ) -> Response {
169
+ fn into_response ( self ) -> Response < Body > {
125
170
( StatusCode :: INTERNAL_SERVER_ERROR , error ! ( "🤷: {}" , self . 0 ) ) . into_response ( )
126
171
}
127
172
}
@@ -142,7 +187,7 @@ pub fn serve(memory_layer: InMemoryLayer) -> Result<(), anyhow::Error> {
142
187
. block_on ( async {
143
188
let app = Router :: new ( )
144
189
. route ( "/:locale/search-index.json" , get ( get_search_index_handler) )
145
- . fallback ( get_json_handler )
190
+ . fallback ( handler )
146
191
. with_state ( Arc :: new ( memory_layer) ) ;
147
192
148
193
let listener = tokio:: net:: TcpListener :: bind ( "0.0.0.0:8083" ) . await . unwrap ( ) ;
0 commit comments