@@ -38,9 +38,18 @@ use crate::{
3838
3939/// An HTTP server which runs Spin apps.
4040pub struct HttpServer {
41+ /// The address the server is listening on.
42+ listen_addr : SocketAddr ,
43+ /// The TLS configuration for the server.
4144 tls_config : Option < TlsConfig > ,
45+ /// Request router.
4246 router : Router ,
43- handler : Arc < RequestHandler > ,
47+ /// The app being triggered.
48+ trigger_app : TriggerApp ,
49+ // Component ID -> component trigger config
50+ component_trigger_configs : HashMap < String , HttpTriggerConfig > ,
51+ // Component ID -> handler type
52+ component_handler_types : HashMap < String , HandlerType > ,
4453}
4554
4655impl HttpServer {
@@ -52,27 +61,32 @@ impl HttpServer {
5261 router : Router ,
5362 component_trigger_configs : HashMap < String , HttpTriggerConfig > ,
5463 ) -> anyhow:: Result < Self > {
64+ let component_handler_types = component_trigger_configs
65+ . keys ( )
66+ . map ( |component_id| {
67+ let component = trigger_app. get_component ( component_id) ?;
68+ let handler_type = HandlerType :: from_component ( trigger_app. engine ( ) , component) ?;
69+ Ok ( ( component_id. clone ( ) , handler_type) )
70+ } )
71+ . collect :: < anyhow:: Result < _ > > ( ) ?;
5572 Ok ( Self {
73+ listen_addr,
5674 tls_config,
5775 router,
58- handler : Arc :: new ( RequestHandler :: new (
59- listen_addr,
60- trigger_app,
61- component_trigger_configs,
62- ) ?) ,
76+ trigger_app,
77+ component_trigger_configs,
78+ component_handler_types,
6379 } )
6480 }
6581
6682 /// Serve incoming requests over the provided [`TcpListener`].
6783 pub async fn serve ( self : Arc < Self > ) -> anyhow:: Result < ( ) > {
68- let listener = TcpListener :: bind ( self . handler . listen_addr )
69- . await
70- . with_context ( || {
71- format ! (
72- "Unable to listen on {listen_addr}" ,
73- listen_addr = self . handler. listen_addr
74- )
75- } ) ?;
84+ let listener = TcpListener :: bind ( self . listen_addr ) . await . with_context ( || {
85+ format ! (
86+ "Unable to listen on {listen_addr}" ,
87+ listen_addr = self . listen_addr
88+ )
89+ } ) ?;
7690 if let Some ( tls_config) = self . tls_config . clone ( ) {
7791 self . serve_https ( listener, tls_config) . await ?;
7892 } else {
@@ -112,7 +126,7 @@ impl HttpServer {
112126 ///
113127 /// This method handles well known paths and routes requests to the handler when the router
114128 /// matches the requests path.
115- async fn handle (
129+ pub async fn handle (
116130 self : & Arc < Self > ,
117131 mut req : Request < Body > ,
118132 server_scheme : Scheme ,
@@ -150,15 +164,70 @@ impl HttpServer {
150164 /// Handles a successful route match.
151165 pub async fn handle_trigger_route (
152166 self : & Arc < Self > ,
153- req : Request < Body > ,
167+ mut req : Request < Body > ,
154168 route_match : RouteMatch ,
155169 server_scheme : Scheme ,
156170 client_addr : SocketAddr ,
157171 ) -> anyhow:: Result < Response < Body > > {
158- let res = self
159- . handler
160- . handle_trigger_route ( req, & route_match, server_scheme, client_addr)
161- . await ;
172+ set_req_uri ( & mut req, server_scheme. clone ( ) ) ?;
173+ let app_id = self
174+ . trigger_app
175+ . app ( )
176+ . get_metadata ( APP_NAME_KEY ) ?
177+ . unwrap_or_else ( || "<unnamed>" . into ( ) ) ;
178+
179+ let component_id = route_match. component_id ( ) ;
180+
181+ spin_telemetry:: metrics:: monotonic_counter!(
182+ spin. request_count = 1 ,
183+ trigger_type = "http" ,
184+ app_id = app_id,
185+ component_id = component_id
186+ ) ;
187+
188+ let mut instance_builder = self . trigger_app . prepare ( component_id) ?;
189+
190+ // Set up outbound HTTP request origin and service chaining
191+ let origin = SelfRequestOrigin :: create ( server_scheme, & self . listen_addr ) ?;
192+ instance_builder
193+ . factor_builders ( )
194+ . outbound_http ( )
195+ . set_request_interceptor ( OutboundHttpInterceptor :: new ( self . clone ( ) , origin) ) ?;
196+
197+ // Prepare HTTP executor
198+ let trigger_config = self . component_trigger_configs . get ( component_id) . unwrap ( ) ;
199+ let handler_type = self . component_handler_types . get ( component_id) . unwrap ( ) ;
200+ let executor = trigger_config
201+ . executor
202+ . as_ref ( )
203+ . unwrap_or ( & HttpExecutorType :: Http ) ;
204+
205+ let res = match executor {
206+ HttpExecutorType :: Http => match handler_type {
207+ HandlerType :: Spin => {
208+ SpinHttpExecutor
209+ . execute ( instance_builder, & route_match, req, client_addr)
210+ . await
211+ }
212+ HandlerType :: Wasi0_2
213+ | HandlerType :: Wasi2023_11_10
214+ | HandlerType :: Wasi2023_10_18 => {
215+ WasiHttpExecutor {
216+ handler_type : * handler_type,
217+ }
218+ . execute ( instance_builder, & route_match, req, client_addr)
219+ . await
220+ }
221+ } ,
222+ HttpExecutorType :: Wagi ( wagi_config) => {
223+ let executor = WagiHttpExecutor {
224+ wagi_config : wagi_config. clone ( ) ,
225+ } ;
226+ executor
227+ . execute ( instance_builder, & route_match, req, client_addr)
228+ . await
229+ }
230+ } ;
162231 match res {
163232 Ok ( res) => Ok ( MatchedRoute :: with_response_extension (
164233 res,
@@ -174,7 +243,7 @@ impl HttpServer {
174243
175244 /// Returns spin status information.
176245 fn app_info ( & self , route : String ) -> anyhow:: Result < Response < Body > > {
177- let info = AppInfo :: new ( self . handler . trigger_app . app ( ) ) ;
246+ let info = AppInfo :: new ( self . trigger_app . app ( ) ) ;
178247 let body = serde_json:: to_vec_pretty ( & info) ?;
179248 Ok ( MatchedRoute :: with_response_extension (
180249 Response :: builder ( )
@@ -278,7 +347,7 @@ impl HttpServer {
278347 println ! ( "Available Routes:" ) ;
279348 for ( route, component_id) in self . router . routes ( ) {
280349 println ! ( " {}: {}{}" , component_id, base_url, route) ;
281- if let Some ( component) = self . handler . trigger_app . app ( ) . get_component ( component_id) {
350+ if let Some ( component) = self . trigger_app . app ( ) . get_component ( component_id) {
282351 if let Some ( description) = component. get_metadata ( APP_DESCRIPTION_KEY ) ? {
283352 println ! ( " {}" , description) ;
284353 }
@@ -288,111 +357,6 @@ impl HttpServer {
288357 }
289358}
290359
291- /// Handles a routed HTTP trigger request.
292- pub struct RequestHandler {
293- /// The address the server is listening on.
294- pub ( crate ) listen_addr : SocketAddr ,
295- /// The app being triggered.
296- trigger_app : TriggerApp ,
297- // Component ID -> component trigger config
298- component_trigger_configs : HashMap < String , HttpTriggerConfig > ,
299- // Component ID -> handler type
300- component_handler_types : HashMap < String , HandlerType > ,
301- }
302-
303- impl RequestHandler {
304- /// Create a new [`RequestHandler`]
305- pub fn new (
306- listen_addr : SocketAddr ,
307- trigger_app : TriggerApp ,
308- component_trigger_configs : HashMap < String , HttpTriggerConfig > ,
309- ) -> anyhow:: Result < Self > {
310- let component_handler_types = component_trigger_configs
311- . keys ( )
312- . map ( |component_id| {
313- let component = trigger_app. get_component ( component_id) ?;
314- let handler_type = HandlerType :: from_component ( trigger_app. engine ( ) , component) ?;
315- Ok ( ( component_id. clone ( ) , handler_type) )
316- } )
317- . collect :: < anyhow:: Result < _ > > ( ) ?;
318- Ok ( Self {
319- listen_addr,
320- trigger_app,
321- component_trigger_configs,
322- component_handler_types,
323- } )
324- }
325-
326- /// Handle a routed request.
327- pub async fn handle_trigger_route (
328- self : & Arc < Self > ,
329- mut req : Request < Body > ,
330- route_match : & RouteMatch ,
331- server_scheme : Scheme ,
332- client_addr : SocketAddr ,
333- ) -> anyhow:: Result < Response < Body > > {
334- set_req_uri ( & mut req, server_scheme. clone ( ) ) ?;
335- let app_id = self
336- . trigger_app
337- . app ( )
338- . get_metadata ( APP_NAME_KEY ) ?
339- . unwrap_or_else ( || "<unnamed>" . into ( ) ) ;
340-
341- let component_id = route_match. component_id ( ) ;
342-
343- spin_telemetry:: metrics:: monotonic_counter!(
344- spin. request_count = 1 ,
345- trigger_type = "http" ,
346- app_id = app_id,
347- component_id = component_id
348- ) ;
349-
350- let mut instance_builder = self . trigger_app . prepare ( component_id) ?;
351-
352- // Set up outbound HTTP request origin and service chaining
353- let origin = SelfRequestOrigin :: create ( server_scheme, & self . listen_addr ) ?;
354- instance_builder
355- . factor_builders ( )
356- . outbound_http ( )
357- . set_request_interceptor ( OutboundHttpInterceptor :: new ( self . clone ( ) , origin) ) ?;
358-
359- // Prepare HTTP executor
360- let trigger_config = self . component_trigger_configs . get ( component_id) . unwrap ( ) ;
361- let handler_type = self . component_handler_types . get ( component_id) . unwrap ( ) ;
362- let executor = trigger_config
363- . executor
364- . as_ref ( )
365- . unwrap_or ( & HttpExecutorType :: Http ) ;
366-
367- match executor {
368- HttpExecutorType :: Http => match handler_type {
369- HandlerType :: Spin => {
370- SpinHttpExecutor
371- . execute ( instance_builder, route_match, req, client_addr)
372- . await
373- }
374- HandlerType :: Wasi0_2
375- | HandlerType :: Wasi2023_11_10
376- | HandlerType :: Wasi2023_10_18 => {
377- WasiHttpExecutor {
378- handler_type : * handler_type,
379- }
380- . execute ( instance_builder, route_match, req, client_addr)
381- . await
382- }
383- } ,
384- HttpExecutorType :: Wagi ( wagi_config) => {
385- let executor = WagiHttpExecutor {
386- wagi_config : wagi_config. clone ( ) ,
387- } ;
388- executor
389- . execute ( instance_builder, route_match, req, client_addr)
390- . await
391- }
392- }
393- }
394- }
395-
396360/// The incoming request's scheme and authority
397361///
398362/// The incoming request's URI is relative to the server, so we need to set the scheme and authority.
0 commit comments