1- use crate :: config:: * ;
2- use crate :: error:: RocketLambError ;
3- use crate :: request_ext:: RequestExt as _;
1+ use std:: future:: Future ;
2+ use std:: pin:: Pin ;
3+ use std:: sync:: Arc ;
4+
45use aws_lambda_events:: encodings:: Body ;
56use lamedh_http:: { Handler , Request , RequestExt , Response } ;
67use lamedh_runtime:: Context ;
8+ use parking_lot:: Mutex ;
79use rocket:: http:: { uri:: Uri , Header } ;
810use rocket:: local:: asynchronous:: { Client , LocalRequest , LocalResponse } ;
9- use std:: future:: Future ;
10- use std:: pin:: Pin ;
11- use std:: sync:: Arc ;
11+ use rocket:: { Rocket , Route } ;
12+
13+ use crate :: config:: * ;
14+ use crate :: error:: RocketLambError ;
15+ use crate :: request_ext:: RequestExt as _;
1216
1317/// A Lambda handler for API Gateway events that processes requests using a [Rocket](rocket::Rocket) instance.
1418pub struct RocketHandler {
15- pub ( super ) client : Arc < Client > ,
19+ pub ( super ) lazy_client : Arc < Mutex < LazyClient > > ,
1620 pub ( super ) config : Arc < Config > ,
1721}
1822
23+ pub ( super ) enum LazyClient {
24+ Uninitialized ( Option < Rocket > ) ,
25+ Ready ( Arc < Client > ) ,
26+ }
27+
1928impl Handler for RocketHandler {
2029 type Error = failure:: Error ;
2130 type Response = Response < Body > ;
2231 type Fut = Pin < Box < dyn Future < Output = Result < Self :: Response , Self :: Error > > + ' static > > ;
2332
2433 fn call ( & mut self , req : Request , _ctx : Context ) -> Self :: Fut {
25- let client = Arc :: clone ( & self . client ) ;
2634 let config = Arc :: clone ( & self . config ) ;
35+ let lazy_client = Arc :: clone ( & self . lazy_client ) ;
2736 let fut = async {
28- process_request ( client , config, req)
37+ process_request ( lazy_client , config, req)
2938 . await
3039 . map_err ( failure:: Error :: from)
3140 . map_err ( failure:: Error :: into)
@@ -35,10 +44,9 @@ impl Handler for RocketHandler {
3544}
3645
3746fn 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 ( ) ,
47+ let mut uri = match & config. base_path_behaviour {
48+ BasePathBehaviour :: Include | BasePathBehaviour :: RemountAndInclude => dbg ! ( req. full_path( ) ) ,
49+ BasePathBehaviour :: Exclude => dbg ! ( req. api_path( ) . to_owned( ) ) ,
4250 } ;
4351 let query = req. query_string_parameters ( ) ;
4452
@@ -58,15 +66,46 @@ fn get_path_and_query(config: &Config, req: &Request) -> String {
5866}
5967
6068async fn process_request (
61- client : Arc < Client > ,
69+ lazy_client : Arc < Mutex < LazyClient > > ,
6270 config : Arc < Config > ,
6371 req : Request ,
6472) -> Result < Response < Body > , RocketLambError > {
73+ let client = get_client_from_lazy ( & lazy_client, & config, & req) . await ;
6574 let local_req = create_rocket_request ( & client, Arc :: clone ( & config) , req) ?;
6675 let local_res = local_req. dispatch ( ) . await ;
6776 create_lambda_response ( config, local_res) . await
6877}
6978
79+ async fn get_client_from_lazy (
80+ lazy_client_lock : & Mutex < LazyClient > ,
81+ config : & Config ,
82+ req : & Request ,
83+ ) -> Arc < Client > {
84+ let mut lazy_client = lazy_client_lock. lock ( ) ;
85+ match & mut * lazy_client {
86+ LazyClient :: Ready ( c) => Arc :: clone ( & c) ,
87+ LazyClient :: Uninitialized ( r) => {
88+ let r = r
89+ . take ( )
90+ . expect ( "It should not be possible for this to be None" ) ;
91+ let base_path = req. base_path ( ) ;
92+ let client = if config. base_path_behaviour == BasePathBehaviour :: RemountAndInclude
93+ && !base_path. is_empty ( )
94+ {
95+ let routes: Vec < Route > = r. routes ( ) . cloned ( ) . collect ( ) ;
96+ let rocket = r. mount ( & base_path, routes) ;
97+ Client :: untracked ( rocket) . await . unwrap ( )
98+ } else {
99+ Client :: untracked ( r) . await . unwrap ( )
100+ } ;
101+ let client = Arc :: new ( client) ;
102+ let client_clone = Arc :: clone ( & client) ;
103+ * lazy_client = LazyClient :: Ready ( client) ;
104+ client_clone
105+ }
106+ }
107+ }
108+
70109fn create_rocket_request (
71110 client : & Client ,
72111 config : Arc < Config > ,
0 commit comments