1
+ extern crate dotenv;
2
+
1
3
mod consts;
2
4
mod db;
3
5
mod models;
@@ -6,10 +8,15 @@ use bb8_redis::redis::AsyncCommands;
6
8
use db:: RedisConnection ;
7
9
use models:: { NewShorterURL , ShorterURL } ;
8
10
use nanoid:: nanoid;
9
- use rocket:: response:: status:: Created ;
11
+ use rocket:: { http :: { ContentType , Method } , response:: status:: Created } ;
10
12
use rocket:: response:: Redirect ;
11
13
use rocket:: serde:: json:: Json ;
12
- use rocket:: { get, launch, post, routes, Responder } ;
14
+ use rocket:: { get, launch, post, options, routes, Request , Response , Responder } ;
15
+ use rocket:: http:: Header ;
16
+ use rocket:: fairing:: { Fairing , Info , Kind } ;
17
+ use dotenv:: dotenv;
18
+ use std:: env;
19
+
13
20
14
21
const REDIS_KEY_PREFIX : & str = "microshort::ids" ;
15
22
@@ -18,6 +25,9 @@ async fn index() -> &'static str {
18
25
"Hello, world!"
19
26
}
20
27
28
+ #[ options( "/" ) ]
29
+ async fn cors ( ) { }
30
+
21
31
#[ post( "/" , format = "json" , data = "<data>" ) ]
22
32
async fn shorten (
23
33
data : Json < NewShorterURL > ,
@@ -27,6 +37,8 @@ async fn shorten(
27
37
let id = nanoid ! ( 4 , & consts:: ALPHANUMERIC ) ;
28
38
let key = format ! ( "{}::{}" , REDIS_KEY_PREFIX , id) ;
29
39
let result = conn. set_nx ( & key, & data. url ) . await . expect ( "RedisSetNXError" ) ;
40
+
41
+ conn. expire :: < & str , usize > ( & key, data. duration ) . await . expect ( "RedisExpireError" ) ;
30
42
31
43
if result {
32
44
break id;
@@ -58,9 +70,42 @@ async fn access(id: &str, mut conn: RedisConnection<'_>) -> AccessResponse {
58
70
}
59
71
}
60
72
73
+ struct Cors ;
74
+
75
+ #[ rocket:: async_trait]
76
+ impl Fairing for Cors {
77
+ fn info ( & self ) -> Info {
78
+ Info {
79
+ name : "My Custom Fairing" ,
80
+ kind : Kind :: Response
81
+ }
82
+ }
83
+
84
+ async fn on_response < ' r > ( & self , req : & ' r Request < ' _ > , res : & mut Response < ' r > ) {
85
+ let origin = match env:: var ( "ORIGIN_ADDRESS" ) {
86
+ Ok ( val) => val,
87
+ Err ( e) => panic ! ( "{}" , e) ,
88
+ } ;
89
+
90
+ if req. method ( ) == Method :: Options || res. content_type ( ) == Some ( ContentType :: JSON ) {
91
+ res. set_header ( Header :: new ( "Access-Control-Allow-Origin" , origin) ) ;
92
+ res. set_header ( Header :: new ( "Access-Control-Allow-Methods" , "POST, GET, OPTIONS" ) ) ;
93
+ res. set_header ( Header :: new ( "Access-Control-Allow-Headers" , "Content-Type" ) ) ;
94
+ res. set_header ( Header :: new ( "Access-Control-Allow-Credentials" , "true" ) ) ;
95
+ }
96
+
97
+ if req. method ( ) == Method :: Options {
98
+ res. set_header ( ContentType :: Plain ) ;
99
+ }
100
+ }
101
+ }
102
+
61
103
#[ launch]
62
104
async fn rocket ( ) -> _ {
105
+ dotenv ( ) . ok ( ) ;
106
+
63
107
rocket:: build ( )
108
+ . attach ( Cors )
64
109
. manage ( db:: pool ( ) . await )
65
- . mount ( "/" , routes ! [ index, access, shorten] )
110
+ . mount ( "/" , routes ! [ index, access, shorten, cors ] )
66
111
}
0 commit comments