@@ -5,7 +5,7 @@ use spin_core::async_trait;
5
5
use spin_outbound_networking:: { AllowedHostsConfig , OutboundUrl } ;
6
6
use spin_world:: v1:: {
7
7
http as outbound_http,
8
- http_types:: { Headers , HttpError , Method , Request , Response } ,
8
+ http_types:: { self , Headers , HttpError , Method , Request , Response } ,
9
9
} ;
10
10
use tracing:: { field:: Empty , instrument, Level } ;
11
11
@@ -42,72 +42,75 @@ impl outbound_http::Host for OutboundHttp {
42
42
#[ instrument( name = "spin_outbound_http.send_request" , skip_all, err( level = Level :: INFO ) ,
43
43
fields( otel. kind = "client" , url. full = Empty , http. request. method = Empty ,
44
44
http. response. status_code = Empty , otel. name = Empty , server. address = Empty , server. port = Empty ) ) ]
45
- async fn send_request ( & mut self , req : Request ) -> Result < Result < Response , HttpError > > {
46
- Ok ( async {
47
- let current_span = tracing:: Span :: current ( ) ;
48
- let method = format ! ( "{:?}" , req. method)
49
- . strip_prefix ( "Method::" )
50
- . unwrap_or ( "_OTHER" )
51
- . to_uppercase ( ) ;
52
- current_span. record ( "otel.name" , method. clone ( ) ) ;
53
- current_span. record ( "url.full" , req. uri . clone ( ) ) ;
54
- current_span. record ( "http.request.method" , method) ;
55
- if let Ok ( uri) = req. uri . parse :: < Uri > ( ) {
56
- if let Some ( authority) = uri. authority ( ) {
57
- current_span. record ( "server.address" , authority. host ( ) ) ;
58
- if let Some ( port) = authority. port ( ) {
59
- current_span. record ( "server.port" , port. as_u16 ( ) ) ;
60
- }
45
+ async fn send_request ( & mut self , req : Request ) -> Result < Response , HttpError > {
46
+ let current_span = tracing:: Span :: current ( ) ;
47
+ let method = format ! ( "{:?}" , req. method)
48
+ . strip_prefix ( "Method::" )
49
+ . unwrap_or ( "_OTHER" )
50
+ . to_uppercase ( ) ;
51
+ current_span. record ( "otel.name" , method. clone ( ) ) ;
52
+ current_span. record ( "url.full" , req. uri . clone ( ) ) ;
53
+ current_span. record ( "http.request.method" , method) ;
54
+ if let Ok ( uri) = req. uri . parse :: < Uri > ( ) {
55
+ if let Some ( authority) = uri. authority ( ) {
56
+ current_span. record ( "server.address" , authority. host ( ) ) ;
57
+ if let Some ( port) = authority. port ( ) {
58
+ current_span. record ( "server.port" , port. as_u16 ( ) ) ;
61
59
}
62
60
}
61
+ }
63
62
64
- tracing:: log:: trace!( "Attempting to send outbound HTTP request to {}" , req. uri) ;
65
- if !self
66
- . is_allowed ( & req. uri )
67
- . map_err ( |_| HttpError :: RuntimeError ) ?
68
- {
69
- tracing:: log:: info!( "Destination not allowed: {}" , req. uri) ;
70
- if let Some ( ( scheme, host_and_port) ) = scheme_host_and_port ( & req. uri ) {
71
- terminal:: warn!( "A component tried to make a HTTP request to non-allowed host '{host_and_port}'." ) ;
72
- eprintln ! ( "To allow requests, add 'allowed_outbound_hosts = [\" {scheme}://{host_and_port}\" ]' to the manifest component section." ) ;
73
- }
74
- return Err ( HttpError :: DestinationNotAllowed ) ;
63
+ tracing:: log:: trace!( "Attempting to send outbound HTTP request to {}" , req. uri) ;
64
+ if !self
65
+ . is_allowed ( & req. uri )
66
+ . map_err ( |_| HttpError :: RuntimeError ) ?
67
+ {
68
+ tracing:: log:: info!( "Destination not allowed: {}" , req. uri) ;
69
+ if let Some ( ( scheme, host_and_port) ) = scheme_host_and_port ( & req. uri ) {
70
+ terminal:: warn!( "A component tried to make a HTTP request to non-allowed host '{host_and_port}'." ) ;
71
+ eprintln ! ( "To allow requests, add 'allowed_outbound_hosts = [\" {scheme}://{host_and_port}\" ]' to the manifest component section." ) ;
75
72
}
73
+ return Err ( HttpError :: DestinationNotAllowed ) ;
74
+ }
76
75
77
- let method = method_from ( req. method ) ;
78
-
79
- let abs_url = if req. uri . starts_with ( '/' ) {
80
- format ! ( "{}{}" , self . origin, req. uri)
81
- } else {
82
- req. uri . clone ( )
83
- } ;
76
+ let method = method_from ( req. method ) ;
84
77
85
- let req_url = reqwest:: Url :: parse ( & abs_url) . map_err ( |_| HttpError :: InvalidUrl ) ?;
78
+ let abs_url = if req. uri . starts_with ( '/' ) {
79
+ format ! ( "{}{}" , self . origin, req. uri)
80
+ } else {
81
+ req. uri . clone ( )
82
+ } ;
86
83
87
- let mut headers = request_headers ( req. headers ) . map_err ( |_| HttpError :: RuntimeError ) ?;
88
- spin_telemetry:: inject_trace_context ( & mut headers) ;
89
- let body = req. body . unwrap_or_default ( ) . to_vec ( ) ;
84
+ let req_url = reqwest:: Url :: parse ( & abs_url) . map_err ( |_| HttpError :: InvalidUrl ) ?;
90
85
91
- if ! req. params . is_empty ( ) {
92
- tracing :: log :: warn! ( "HTTP params field is deprecated" ) ;
93
- }
86
+ let mut headers = request_headers ( req. headers ) . map_err ( |_| HttpError :: RuntimeError ) ? ;
87
+ spin_telemetry :: inject_trace_context ( & mut headers ) ;
88
+ let body = req . body . unwrap_or_default ( ) . to_vec ( ) ;
94
89
95
- // Allow reuse of Client's internal connection pool for multiple requests
96
- // in a single component execution
97
- let client = self . client . get_or_insert_with ( Default :: default) ;
98
-
99
- let resp = client
100
- . request ( method, req_url)
101
- . headers ( headers)
102
- . body ( body)
103
- . send ( )
104
- . await
105
- . map_err ( log_reqwest_error) ?;
106
- tracing:: log:: trace!( "Returning response from outbound request to {}" , req. uri) ;
107
- current_span. record ( "http.response.status_code" , resp. status ( ) . as_u16 ( ) ) ;
108
- response_from_reqwest ( resp) . await
90
+ if !req. params . is_empty ( ) {
91
+ tracing:: log:: warn!( "HTTP params field is deprecated" ) ;
109
92
}
110
- . await )
93
+
94
+ // Allow reuse of Client's internal connection pool for multiple requests
95
+ // in a single component execution
96
+ let client = self . client . get_or_insert_with ( Default :: default) ;
97
+
98
+ let resp = client
99
+ . request ( method, req_url)
100
+ . headers ( headers)
101
+ . body ( body)
102
+ . send ( )
103
+ . await
104
+ . map_err ( log_reqwest_error) ?;
105
+ tracing:: log:: trace!( "Returning response from outbound request to {}" , req. uri) ;
106
+ current_span. record ( "http.response.status_code" , resp. status ( ) . as_u16 ( ) ) ;
107
+ response_from_reqwest ( resp) . await
108
+ }
109
+ }
110
+
111
+ impl http_types:: Host for OutboundHttp {
112
+ fn convert_http_error ( & mut self , error : HttpError ) -> Result < HttpError > {
113
+ Ok ( error)
111
114
}
112
115
}
113
116
0 commit comments