@@ -6,21 +6,14 @@ use lamedh_http::{Handler, Request, RequestExt, Response};
66use lamedh_runtime:: Context ;
77use rocket:: http:: { uri:: Uri , Header } ;
88use rocket:: local:: blocking:: { Client , LocalRequest , LocalResponse } ;
9- use rocket:: { Rocket , Route } ;
109use std:: future:: Future ;
11- use std:: mem;
1210use std:: pin:: Pin ;
11+ use std:: sync:: Arc ;
1312
1413/// A Lambda handler for API Gateway events that processes requests using a [Rocket](rocket::Rocket) instance.
1514pub struct RocketHandler {
16- pub ( super ) client : LazyClient ,
17- pub ( super ) config : Config ,
18- }
19-
20- pub ( super ) enum LazyClient {
21- Placeholder ,
22- Uninitialized ( Rocket ) ,
23- Ready ( Client ) ,
15+ pub ( super ) client : Arc < Client > ,
16+ pub ( super ) config : Arc < Config > ,
2417}
2518
2619impl Handler for RocketHandler {
@@ -29,9 +22,10 @@ impl Handler for RocketHandler {
2922 type Fut = Pin < Box < dyn Future < Output = Result < Self :: Response , Self :: Error > > + ' static > > ;
3023
3124 fn call ( & mut self , req : Request , _ctx : Context ) -> Self :: Fut {
32- self . ensure_client_ready ( & req) ;
25+ let client = Arc :: clone ( & self . client ) ;
26+ let config = Arc :: clone ( & self . config ) ;
3327 let fut = async {
34- process_request ( self , req)
28+ process_request ( client , config , req)
3529 . await
3630 . map_err ( failure:: Error :: from)
3731 . map_err ( failure:: Error :: into)
@@ -40,76 +34,47 @@ impl Handler for RocketHandler {
4034 }
4135}
4236
43- impl RocketHandler {
44- fn ensure_client_ready ( & mut self , req : & Request ) {
45- match self . client {
46- ref mut lazy_client @ LazyClient :: Uninitialized ( _) => {
47- let uninitialized_client = mem:: replace ( lazy_client, LazyClient :: Placeholder ) ;
48- let mut rocket = match uninitialized_client {
49- LazyClient :: Uninitialized ( rocket) => rocket,
50- _ => unreachable ! ( "LazyClient must be uninitialized at this point." ) ,
51- } ;
52- if self . config . base_path_behaviour == BasePathBehaviour :: RemountAndInclude {
53- let base_path = req. base_path ( ) ;
54- if !base_path. is_empty ( ) {
55- let routes: Vec < Route > = rocket. routes ( ) . cloned ( ) . collect ( ) ;
56- rocket = rocket. mount ( & base_path, routes) ;
57- }
58- }
59- let client = Client :: untracked ( rocket) . unwrap ( ) ;
60- self . client = LazyClient :: Ready ( client) ;
61- }
62- LazyClient :: Ready ( _) => { }
63- LazyClient :: Placeholder => panic ! ( "LazyClient has previously begun initialiation." ) ,
64- }
65- }
66-
67- fn client ( & self ) -> & Client {
68- match & self . client {
69- LazyClient :: Ready ( client) => client,
70- _ => panic ! ( "Rocket client wasn't ready. ensure_client_ready should have been called!" ) ,
71- }
72- }
73-
74- fn get_path_and_query ( & self , req : & Request ) -> String {
75- let mut uri = match self . config . base_path_behaviour {
76- BasePathBehaviour :: Include | BasePathBehaviour :: RemountAndInclude => req. full_path ( ) ,
77- BasePathBehaviour :: Exclude => req. api_path ( ) . to_owned ( ) ,
78- } ;
79- let query = req. query_string_parameters ( ) ;
37+ fn get_path_and_query ( config : & Config , req : & Request ) -> String {
38+ // TODO: Figure out base path behavior per request since the client doesn't have it now
39+ let mut uri = match config. base_path_behaviour {
40+ BasePathBehaviour :: Include | BasePathBehaviour :: RemountAndInclude => req. full_path ( ) ,
41+ BasePathBehaviour :: Exclude => req. api_path ( ) . to_owned ( ) ,
42+ } ;
43+ let query = req. query_string_parameters ( ) ;
8044
81- let mut separator = '?' ;
82- for ( key, _) in query. iter ( ) {
83- for value in query. get_all ( key) . unwrap ( ) {
84- uri. push_str ( & format ! (
85- "{}{}={}" ,
86- separator,
87- Uri :: percent_encode( key) ,
88- Uri :: percent_encode( value)
89- ) ) ;
90- separator = '&' ;
91- }
45+ let mut separator = '?' ;
46+ for ( key, _) in query. iter ( ) {
47+ for value in query. get_all ( key) . unwrap ( ) {
48+ uri. push_str ( & format ! (
49+ "{}{}={}" ,
50+ separator,
51+ Uri :: percent_encode( key) ,
52+ Uri :: percent_encode( value)
53+ ) ) ;
54+ separator = '&' ;
9255 }
93- uri
9456 }
57+ uri
9558}
9659
9760async fn process_request (
98- handler : & RocketHandler ,
61+ client : Arc < Client > ,
62+ config : Arc < Config > ,
9963 req : Request ,
10064) -> Result < Response < Body > , RocketLambError > {
101- let local_req = create_rocket_request ( handler , req) ?;
65+ let local_req = create_rocket_request ( & client , Arc :: clone ( & config ) , req) ?;
10266 let local_res = local_req. dispatch ( ) ;
103- create_lambda_response ( handler , local_res) . await
67+ create_lambda_response ( config , local_res) . await
10468}
10569
10670fn create_rocket_request (
107- handler : & RocketHandler ,
71+ client : & Client ,
72+ config : Arc < Config > ,
10873 req : Request ,
10974) -> Result < LocalRequest , RocketLambError > {
11075 let method = to_rocket_method ( req. method ( ) ) ?;
111- let uri = handler . get_path_and_query ( & req) ;
112- let mut local_req = handler . client ( ) . req ( method, uri) ;
76+ let uri = get_path_and_query ( & config , & req) ;
77+ let mut local_req = client. req ( method, uri) ;
11378 for ( name, value) in req. headers ( ) {
11479 match value. to_str ( ) {
11580 Ok ( v) => local_req. add_header ( Header :: new ( name. to_string ( ) , v. to_string ( ) ) ) ,
@@ -121,7 +86,7 @@ fn create_rocket_request(
12186}
12287
12388async fn create_lambda_response (
124- handler : & RocketHandler ,
89+ config : Arc < Config > ,
12590 local_res : LocalResponse < ' _ > ,
12691) -> Result < Response < Body > , RocketLambError > {
12792 let mut builder = Response :: builder ( ) ;
@@ -136,9 +101,9 @@ async fn create_lambda_response(
136101 . unwrap_or_default ( )
137102 . split ( ';' )
138103 . next ( )
139- . and_then ( |ct| handler . config . response_types . get ( & ct. to_lowercase ( ) ) )
104+ . and_then ( |ct| config. response_types . get ( & ct. to_lowercase ( ) ) )
140105 . copied ( )
141- . unwrap_or ( handler . config . default_response_type ) ;
106+ . unwrap_or ( config. default_response_type ) ;
142107 let body = match local_res. into_bytes ( ) {
143108 Some ( b) => match response_type {
144109 ResponseType :: Auto => match String :: from_utf8 ( b) {
0 commit comments