@@ -11,6 +11,7 @@ use std::io;
11
11
use std:: io:: prelude:: * ;
12
12
use std:: collections:: HashMap ;
13
13
use std:: path:: Path ;
14
+ use std:: path:: PathBuf ;
14
15
use std:: sync:: { Mutex } ;
15
16
16
17
use dotenv:: dotenv;
@@ -42,9 +43,13 @@ use models::file;
42
43
43
44
struct UploadState {
44
45
map : Mutex < HashMap < String , UploadEntry > > ,
45
- tmp : String ,
46
- upload : String ,
46
+
47
+ tmp_dir : String ,
48
+ upload_dir : String ,
49
+ web_dir : String ,
50
+
47
51
chunk_size : ByteUnit ,
52
+
48
53
datapool : database:: PgPool ,
49
54
50
55
embed_description : String ,
@@ -79,23 +84,23 @@ impl<'r, 'o: 'r, 'a, R: Responder<'r, 'o>> Responder<'r, 'o> for Advanced<R> {
79
84
}
80
85
}
81
86
82
- //----- START OF ROUTE CODE -----
87
+ //----- START OF API CODE -----
83
88
84
89
#[ get( "/" ) ]
85
- fn index ( ) -> ( ContentType , & ' static str ) {
86
- ( ContentType :: HTML , "KekUpload api made by KekOnTheWorld! <a href='https://github.com/KekOnTheWorld/ uploadserver/wiki /API-Documentation '>Docs</a>" )
90
+ fn api_index ( ) -> ( ContentType , & ' static str ) {
91
+ ( ContentType :: HTML , "UploadServer api made by KekOnTheWorld! <a href='https://oss.kotw.dev/ uploadserver/docs /API'>Docs</a>" )
87
92
}
88
93
89
94
#[ post( "/c/<ext>" ) ]
90
- fn create ( ext : String , state : & State < UploadState > ) -> status:: Custom < String > {
95
+ fn api_create ( ext : String , state : & State < UploadState > ) -> status:: Custom < String > {
91
96
if ext. len ( ) > 6 {
92
97
return status:: Custom ( Status :: BadRequest , "EXT_TOO_LONG" . to_owned ( ) ) ;
93
98
}
94
99
95
100
let map = & mut state. map . lock ( ) . unwrap ( ) ;
96
101
97
102
let id = random:: random_b64 ( 64 ) ;
98
- let file = File :: create ( state. tmp . clone ( ) + & id) . unwrap ( ) ;
103
+ let file = File :: create ( state. tmp_dir . clone ( ) + & id) . unwrap ( ) ;
99
104
let hasher = Sha1 :: new ( ) ;
100
105
101
106
let entry = UploadEntry { file : file, ext, hasher } ;
@@ -108,7 +113,7 @@ fn create(ext: String, state: &State<UploadState>) -> status::Custom<String> {
108
113
}
109
114
110
115
#[ post( "/u/<id>/<hash>" , data = "<data>" ) ]
111
- async fn upload ( data : Data < ' _ > , id : String , hash : String , state : & State < UploadState > ) -> io:: Result < status:: Custom < & ' static str > > {
116
+ async fn api_upload ( data : Data < ' _ > , id : String , hash : String , state : & State < UploadState > ) -> io:: Result < status:: Custom < & ' static str > > {
112
117
let bytes = data. open ( state. chunk_size ) . into_bytes ( ) . await ?. into_inner ( ) ;
113
118
114
119
let map = & mut state. map . lock ( ) . unwrap ( ) ;
@@ -133,9 +138,9 @@ async fn upload(data: Data<'_>, id: String, hash: String, state: &State<UploadSt
133
138
}
134
139
135
140
#[ post( "/r/<id>" ) ]
136
- async fn remove ( id : String , state : & State < UploadState > ) -> status:: Custom < & ' static str > {
141
+ async fn api_remove ( id : String , state : & State < UploadState > ) -> status:: Custom < & ' static str > {
137
142
let map = & mut state. map . lock ( ) . unwrap ( ) ;
138
- let file_path = state. tmp . clone ( ) + & id;
143
+ let file_path = state. tmp_dir . clone ( ) + & id;
139
144
if fs:: remove_file ( file_path) . is_ok ( ) {
140
145
map. remove ( & id) ;
141
146
return status:: Custom ( Status :: Ok , "OK" ) ;
@@ -145,14 +150,14 @@ async fn remove(id: String, state: &State<UploadState>) -> status::Custom<&'stat
145
150
}
146
151
147
152
#[ post( "/f/<id>/<hash>" ) ]
148
- async fn finish ( id : String , hash : String , state : & State < UploadState > ) -> status:: Custom < String > {
153
+ async fn api_finish ( id : String , hash : String , state : & State < UploadState > ) -> status:: Custom < String > {
149
154
let map = & mut state. map . lock ( ) . unwrap ( ) ;
150
155
if let Some ( entry) = map. get_mut ( & id) {
151
156
let file_hash = hex:: encode ( entry. hasher . clone ( ) . finalize ( ) ) ;
152
- let file_path = state. tmp . clone ( ) + & id;
157
+ let file_path = state. tmp_dir . clone ( ) + & id;
153
158
154
159
if file_hash. eq ( & hash) {
155
- fs:: rename ( file_path, state. upload . clone ( ) + & file_hash)
160
+ fs:: rename ( file_path, state. upload_dir . clone ( ) + & file_hash)
156
161
. expect ( "File rename error!" ) ;
157
162
158
163
let nid = random_b64 ( 6 ) ;
@@ -183,7 +188,7 @@ async fn finish(id: String, hash: String, state: &State<UploadState>) -> status:
183
188
}
184
189
185
190
#[ get( "/d/<id>" ) ]
186
- async fn download ( id : String , state : & State < UploadState > ) -> Advanced < String > {
191
+ async fn api_download ( id : String , state : & State < UploadState > ) -> Advanced < String > {
187
192
let hash;
188
193
let ext;
189
194
@@ -196,13 +201,13 @@ async fn download(id: String, state: &State<UploadState>) -> Advanced<String> {
196
201
197
202
let filename = hash. clone ( ) + "." + ext. as_str ( ) ;
198
203
199
- let nf = NamedFile :: open ( Path :: new ( state. upload . as_str ( ) ) . join ( hash) ) . await . ok ( ) ;
204
+ let nf = NamedFile :: open ( Path :: new ( state. upload_dir . as_str ( ) ) . join ( hash) ) . await . ok ( ) ;
200
205
201
206
return Advanced ( Some ( filename) , nf, "Kekw" . to_owned ( ) ) ;
202
207
}
203
208
204
209
#[ get( "/e/<id>" ) ]
205
- async fn embed ( id : String , state : & State < UploadState > ) -> status:: Custom < ( ContentType , String ) > {
210
+ async fn api_embed ( id : String , state : & State < UploadState > ) -> status:: Custom < ( ContentType , String ) > {
206
211
if let Some ( entry) = file:: File :: find ( id, & state. datapool . get ( ) . expect ( "Error while connecting to database!" ) ) . first ( ) {
207
212
let filename = entry. hash . clone ( ) + "." + entry. ext . as_str ( ) ;
208
213
@@ -244,7 +249,20 @@ async fn embed(id: String, state: &State<UploadState>) -> status::Custom<(Conten
244
249
}
245
250
}
246
251
247
- //----- END OF ROUTE CODE -----
252
+ //----- END OF API CODE -----
253
+
254
+ //----- START OF WEB CODE -----
255
+ #[ get( "/" ) ]
256
+ async fn web_index ( state : & State < UploadState > ) -> Option < NamedFile > {
257
+ NamedFile :: open ( Path :: new ( state. web_dir . as_str ( ) ) . join ( "index.html" ) ) . await . ok ( )
258
+ }
259
+
260
+ #[ get( "/<path..>" ) ]
261
+ async fn web_base ( path : PathBuf , state : & State < UploadState > ) -> Option < NamedFile > {
262
+ NamedFile :: open ( Path :: new ( state. web_dir . as_str ( ) ) . join ( path) ) . await . ok ( )
263
+ }
264
+
265
+ //----- END OF WEB CODE -----
248
266
249
267
fn clean_tmp ( tmp : String ) {
250
268
let dir = tmp. as_str ( ) ;
@@ -256,15 +274,21 @@ fn clean_tmp(tmp: String) {
256
274
fn rocket ( ) -> _ {
257
275
dotenv ( ) . ok ( ) ;
258
276
259
- let base = env:: var ( "base " )
277
+ let embed_route_base = env:: var ( "embed_route_base " )
260
278
. unwrap_or ( "/" . to_owned ( ) ) ;
261
279
262
- let tmp = env:: var ( "tmp" )
280
+ let api_base = env:: var ( "api_base" )
281
+ . unwrap_or ( "/api/" . to_owned ( ) ) ;
282
+
283
+ let tmp_dir = env:: var ( "tmp_dir" )
263
284
. unwrap_or ( "tmp/" . to_owned ( ) ) ;
264
285
265
- let upload = env:: var ( "upload " )
286
+ let upload_dir = env:: var ( "upload_dir " )
266
287
. unwrap_or ( "upload/" . to_owned ( ) ) ;
267
288
289
+ let web_dir = env:: var ( "web_dir" )
290
+ . unwrap_or ( "web/" . to_owned ( ) ) ;
291
+
268
292
let chunk_size = ByteUnit :: Kibibyte ( env:: var ( "chunk_size" )
269
293
. unwrap_or ( "2048" . to_owned ( ) ) . parse ( ) . unwrap_or ( 2048 ) ) ;
270
294
@@ -294,7 +318,7 @@ fn rocket() -> _ {
294
318
..Default :: default ( )
295
319
} . to_cors ( ) . unwrap ( ) ;
296
320
297
- clean_tmp ( tmp . clone ( ) ) ;
321
+ clean_tmp ( tmp_dir . clone ( ) ) ;
298
322
299
323
database:: establish_connection ( env:: var ( "DATABASE_URL" ) . expect ( "Missing dburl in .env" ) ) ;
300
324
@@ -303,29 +327,47 @@ fn rocket() -> _ {
303
327
. merge ( ( "limits" , limits) )
304
328
. merge ( ( "port" , port) ) ;
305
329
306
- println ! ( "http://localhost:{}{}" , port, base ) ;
330
+ println ! ( "API: http://localhost:{}{}" , port, api_base ) ;
307
331
308
- rocket:: custom ( figment)
332
+ let mut server = rocket:: custom ( figment)
309
333
. manage ( UploadState {
310
334
map : Mutex :: new ( HashMap :: new ( ) ) ,
311
335
312
- tmp ,
313
- upload ,
336
+ tmp_dir ,
337
+ upload_dir ,
314
338
chunk_size,
339
+ web_dir,
315
340
datapool,
316
341
317
342
embed_description,
318
343
embed_color,
319
344
download_url
320
345
} )
321
346
. attach ( cors)
322
- . mount ( base , routes ! [
323
- index ,
324
- create ,
325
- upload ,
326
- finish ,
327
- embed ,
328
- remove ,
329
- download
347
+ . mount ( api_base , routes ! [
348
+ api_index ,
349
+ api_create ,
350
+ api_upload ,
351
+ api_finish ,
352
+ api_embed ,
353
+ api_remove ,
354
+ api_download
330
355
] )
356
+ . mount ( embed_route_base, routes ! [
357
+ api_embed
358
+ ] ) ;
359
+
360
+ if env:: var ( "web_host" ) . is_ok ( ) {
361
+ let web_base = env:: var ( "web_base" )
362
+ . unwrap_or ( "/" . to_owned ( ) ) ;
363
+
364
+ println ! ( "Web: http://localhost:{}{}" , port, web_base) ;
365
+
366
+ server = server. mount ( web_base, routes ! [
367
+ web_index,
368
+ web_base
369
+ ] ) ;
370
+ }
371
+
372
+ server
331
373
}
0 commit comments