@@ -10,6 +10,7 @@ use models::{
1010 utils:: { AppAuthentication , BearerToken , HasHeader , NoAuthentication } ,
1111} ;
1212use preprocess:: Preprocessable ;
13+ use serde:: { de:: DeserializeOwned , Serialize } ;
1314use tower:: {
1415 ServiceBuilder ,
1516 util:: { BoxCloneService , BoxLayer } ,
4445 /// Rate limiter using tower layers.
4546 #[ track_caller]
4647 fn mount_endpoint < E , H > ( self , handler : H , state : & AppState ) -> Self
48+ where
49+ for < ' req > H : EndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
50+ E : ApiEndpoint < Authenticator = NoAuthentication > + Sync ,
51+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
52+ E :: RequestBody : Serialize + DeserializeOwned ,
53+ E :: ResponseBody : Serialize + DeserializeOwned ;
54+
55+ /// Mount an API stream endpoint directly along with the required request
56+ /// parser, Rate limiter using tower layers.
57+ #[ track_caller]
58+ fn mount_stream < E , H > ( self , handler : H , state : & AppState ) -> Self
4759 where
4860 for < ' req > H : EndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
4961 E : ApiEndpoint < Authenticator = NoAuthentication > + Sync ,
5365 /// Rate limiter, Audit logger and Auth middlewares, using tower layers.
5466 #[ track_caller]
5567 fn mount_auth_endpoint < E , H > ( self , handler : H , state : & AppState ) -> Self
68+ where
69+ for < ' req > H : AuthEndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
70+ E : ApiEndpoint < Authenticator = AppAuthentication < E > > + Sync ,
71+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
72+ E :: RequestBody : Serialize + DeserializeOwned ,
73+ E :: ResponseBody : Serialize + DeserializeOwned ,
74+ E :: RequestHeaders : HasHeader < BearerToken > ;
75+
76+ /// Mount an API stream endpoint directly along with the required request
77+ /// parser, Rate limiter, Audit logger and Auth middlewares, using tower
78+ /// layers.
79+ #[ track_caller]
80+ fn mount_auth_stream < E , H > ( self , handler : H , state : & AppState ) -> Self
5681 where
5782 for < ' req > H : AuthEndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
5883 E : ApiEndpoint < Authenticator = AppAuthentication < E > > + Sync ,
6691{
6792 #[ instrument( skip_all) ]
6893 fn mount_endpoint < E , H > ( self , handler : H , state : & AppState ) -> Self
94+ where
95+ for < ' req > H : EndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
96+ E : ApiEndpoint < Authenticator = NoAuthentication > + Sync ,
97+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
98+ E :: RequestBody : Serialize + DeserializeOwned ,
99+ E :: ResponseBody : Serialize + DeserializeOwned ,
100+ {
101+ frontend:: utils:: API_CALL_REGISTRY
102+ . get_or_init ( || RwLock :: new ( Default :: default ( ) ) )
103+ . write ( )
104+ . expect ( "API call registry poisoned" )
105+ . entry ( E :: METHOD )
106+ . or_default ( )
107+ . insert (
108+ <E :: RequestPath as TypedPath >:: PATH ,
109+ Box :: new ( BoxLayer :: <
110+ BoxCloneService < ( ApiRequest < E > , IpAddr ) , AppResponse < E > , ErrorType > ,
111+ ( ApiRequest < E > , IpAddr ) ,
112+ AppResponse < E > ,
113+ ErrorType ,
114+ > :: new (
115+ ServiceBuilder :: new ( )
116+ // .layer(todo!("Add rate limiter checker middleware here")),
117+ . layer ( DataStoreConnectionLayer :: < E > :: with_state ( state. clone ( ) ) )
118+ . layer ( PreprocessLayer :: new ( ) )
119+ . layer ( UserAgentValidationLayer :: new ( ) )
120+ // .layer(todo!("Add rate limiter value updater middleware here"))
121+ . layer ( EndpointLayer :: new ( handler. clone ( ) ) ) ,
122+ ) ) ,
123+ )
124+ . unwrap_or_else ( |_| {
125+ panic ! (
126+ "API endpoint `{} {}` already registered" ,
127+ E :: METHOD ,
128+ <E :: RequestPath as TypedPath >:: PATH
129+ ) ;
130+ } ) ;
131+
132+ frontend:: utils:: register_api_call :: < E > ( ) ;
133+
134+ // Setup the layers for the backend
135+ if <E as ApiEndpoint >:: API_ALLOWED || cfg ! ( debug_assertions) {
136+ self . route (
137+ <<E as ApiEndpoint >:: RequestPath as TypedPath >:: PATH ,
138+ MethodRouter :: < S > :: new ( )
139+ . on (
140+ MethodFilter :: try_from ( <E as ApiEndpoint >:: METHOD ) . unwrap ( ) ,
141+ || async { } ,
142+ )
143+ . layer (
144+ ServiceBuilder :: new ( )
145+ // .layer(todo!("Add rate limiter checker middleware here")),
146+ . layer ( RequestParserLayer :: new ( ) )
147+ . layer ( DataStoreConnectionLayer :: with_state ( state. clone ( ) ) )
148+ // .layer(todo!("Add rate limiter value updater middleware here"))
149+ . layer ( PreprocessLayer :: new ( ) )
150+ . layer ( UserAgentValidationLayer :: new ( ) )
151+ . layer ( EndpointLayer :: new ( handler) ) ,
152+ ) ,
153+ )
154+ } else {
155+ self
156+ }
157+ }
158+
159+ #[ instrument( skip_all) ]
160+ fn mount_stream < E , H > ( self , handler : H , state : & AppState ) -> Self
69161 where
70162 for < ' req > H : EndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
71163 E : ApiEndpoint < Authenticator = NoAuthentication > + Sync ,
@@ -129,6 +221,80 @@ where
129221
130222 #[ instrument( skip_all) ]
131223 fn mount_auth_endpoint < E , H > ( self , handler : H , state : & AppState ) -> Self
224+ where
225+ for < ' req > H : AuthEndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
226+ E : ApiEndpoint < Authenticator = AppAuthentication < E > > + Sync ,
227+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
228+ E :: RequestBody : Serialize + DeserializeOwned ,
229+ E :: ResponseBody : Serialize + DeserializeOwned ,
230+ E :: RequestHeaders : HasHeader < BearerToken > ,
231+ {
232+ frontend:: utils:: API_CALL_REGISTRY
233+ . get_or_init ( || RwLock :: new ( Default :: default ( ) ) )
234+ . write ( )
235+ . expect ( "API call registry poisoned" )
236+ . entry ( E :: METHOD )
237+ . or_default ( )
238+ . insert (
239+ <E :: RequestPath as TypedPath >:: PATH ,
240+ Box :: new ( BoxLayer :: <
241+ BoxCloneService < ( ApiRequest < E > , IpAddr ) , AppResponse < E > , ErrorType > ,
242+ ( ApiRequest < E > , IpAddr ) ,
243+ AppResponse < E > ,
244+ ErrorType ,
245+ > :: new (
246+ ServiceBuilder :: new ( )
247+ // .layer(todo!("Add rate limiter checker middleware here")),
248+ . layer ( DataStoreConnectionLayer :: with_state ( state. clone ( ) ) )
249+ . layer ( PreprocessLayer :: new ( ) )
250+ . layer ( UserAgentValidationLayer :: new ( ) )
251+ . layer ( AuthenticationLayer :: new ( ClientType :: WebDashboard ) )
252+ // .layer(todo!("Add permission checker middleware here"))
253+ // .layer(todo!("Add rate limiter value updater middleware here"))
254+ // .layer(todo!("Add audit logger middleware here"))
255+ . layer ( AuthEndpointLayer :: new ( handler. clone ( ) ) ) ,
256+ ) ) ,
257+ )
258+ . unwrap_or_else ( |_| {
259+ panic ! (
260+ "API endpoint `{} {}` already registered" ,
261+ E :: METHOD ,
262+ <E :: RequestPath as TypedPath >:: PATH
263+ ) ;
264+ } ) ;
265+
266+ frontend:: utils:: register_api_call :: < E > ( ) ;
267+
268+ // Setup the layers for the backend
269+ if <E as ApiEndpoint >:: API_ALLOWED || cfg ! ( debug_assertions) {
270+ self . route (
271+ <<E as ApiEndpoint >:: RequestPath as TypedPath >:: PATH ,
272+ MethodRouter :: < S > :: new ( )
273+ . on (
274+ MethodFilter :: try_from ( <E as ApiEndpoint >:: METHOD ) . unwrap ( ) ,
275+ || async { } ,
276+ )
277+ . layer (
278+ ServiceBuilder :: new ( )
279+ // .layer(todo!("Add rate limiter checker middleware here")),
280+ . layer ( RequestParserLayer :: new ( ) )
281+ . layer ( DataStoreConnectionLayer :: with_state ( state. clone ( ) ) )
282+ . layer ( PreprocessLayer :: new ( ) )
283+ . layer ( UserAgentValidationLayer :: new ( ) )
284+ . layer ( AuthenticationLayer :: new ( ClientType :: ApiToken ) )
285+ // .layer(todo!("Add permission checker middleware here"))
286+ // .layer(todo!("Add rate limiter value updater middleware here"))
287+ // .layer(todo!("Add audit logger middleware here"))
288+ . layer ( AuthEndpointLayer :: new ( handler) ) ,
289+ ) ,
290+ )
291+ } else {
292+ self
293+ }
294+ }
295+
296+ #[ instrument( skip_all) ]
297+ fn mount_auth_stream < E , H > ( self , handler : H , state : & AppState ) -> Self
132298 where
133299 for < ' req > H : AuthEndpointHandler < ' req , E > + Clone + Send + Sync + ' static ,
134300 E : ApiEndpoint < Authenticator = AppAuthentication < E > > + Sync ,
0 commit comments