@@ -5,7 +5,7 @@ use http::{header::HOST, Request};
5
5
use http_body_util:: BodyExt ;
6
6
use ip_network:: IpNetwork ;
7
7
use rustls:: ClientConfig ;
8
- use spin_factor_outbound_networking:: OutboundAllowedHosts ;
8
+ use spin_factor_outbound_networking:: { ComponentTlsConfigs , OutboundAllowedHosts } ;
9
9
use spin_factors:: { wasmtime:: component:: ResourceTable , RuntimeFactorsInstanceState } ;
10
10
use tokio:: { net:: TcpStream , time:: timeout} ;
11
11
use tracing:: { field:: Empty , instrument, Instrument } ;
@@ -19,7 +19,7 @@ use wasmtime_wasi_http::{
19
19
20
20
use crate :: {
21
21
wasi_2023_10_18, wasi_2023_11_10, InstanceState , InterceptOutcome , OutboundHttpFactor ,
22
- SelfRequestOrigin ,
22
+ OutboundHttpInterceptor , SelfRequestOrigin ,
23
23
} ;
24
24
25
25
pub ( crate ) fn add_to_linker < T : Send + ' static > (
@@ -74,7 +74,7 @@ impl<'a> WasiHttpView for WasiHttpImplInner<'a> {
74
74
skip_all,
75
75
fields(
76
76
otel. kind = "client" ,
77
- url. full = %request . uri ( ) ,
77
+ url. full = Empty ,
78
78
http. request. method = %request. method( ) ,
79
79
otel. name = %request. method( ) ,
80
80
http. response. status_code = Empty ,
@@ -84,46 +84,18 @@ impl<'a> WasiHttpView for WasiHttpImplInner<'a> {
84
84
) ]
85
85
fn send_request (
86
86
& mut self ,
87
- mut request : Request < wasmtime_wasi_http:: body:: HyperOutgoingBody > ,
88
- mut config : wasmtime_wasi_http:: types:: OutgoingRequestConfig ,
87
+ request : Request < wasmtime_wasi_http:: body:: HyperOutgoingBody > ,
88
+ config : wasmtime_wasi_http:: types:: OutgoingRequestConfig ,
89
89
) -> wasmtime_wasi_http:: HttpResult < wasmtime_wasi_http:: types:: HostFutureIncomingResponse > {
90
- // wasmtime-wasi-http fills in scheme and authority for relative URLs
91
- // (e.g. https://:443/<path>), which makes them hard to reason about.
92
- // Undo that here.
93
- let uri = request. uri_mut ( ) ;
94
- if uri
95
- . authority ( )
96
- . is_some_and ( |authority| authority. host ( ) . is_empty ( ) )
97
- {
98
- let mut builder = http:: uri:: Builder :: new ( ) ;
99
- if let Some ( paq) = uri. path_and_query ( ) {
100
- builder = builder. path_and_query ( paq. clone ( ) ) ;
101
- }
102
- * uri = builder. build ( ) . unwrap ( ) ;
103
- }
104
-
105
- if let Some ( interceptor) = & self . state . request_interceptor {
106
- match interceptor. intercept ( & mut request, & mut config) {
107
- InterceptOutcome :: Continue => ( ) ,
108
- InterceptOutcome :: Complete ( res) => return res,
109
- }
110
- }
111
-
112
- let host = request. uri ( ) . host ( ) . unwrap_or_default ( ) ;
113
- let tls_client_config = self
114
- . state
115
- . component_tls_configs
116
- . get_client_config ( host)
117
- . clone ( ) ;
118
-
119
90
Ok ( HostFutureIncomingResponse :: Pending (
120
91
wasmtime_wasi:: runtime:: spawn (
121
92
send_request_impl (
122
93
request,
123
94
config,
124
95
self . state . allowed_hosts . clone ( ) ,
96
+ self . state . component_tls_configs . clone ( ) ,
97
+ self . state . request_interceptor . clone ( ) ,
125
98
self . state . self_request_origin . clone ( ) ,
126
- tls_client_config,
127
99
self . state . allow_private_ips ,
128
100
)
129
101
. in_current_span ( ) ,
@@ -136,10 +108,47 @@ async fn send_request_impl(
136
108
mut request : Request < wasmtime_wasi_http:: body:: HyperOutgoingBody > ,
137
109
mut config : wasmtime_wasi_http:: types:: OutgoingRequestConfig ,
138
110
outbound_allowed_hosts : OutboundAllowedHosts ,
111
+ component_tls_configs : ComponentTlsConfigs ,
112
+ request_interceptor : Option < Arc < dyn OutboundHttpInterceptor > > ,
139
113
self_request_origin : Option < SelfRequestOrigin > ,
140
- tls_client_config : Arc < ClientConfig > ,
141
114
allow_private_ips : bool ,
142
115
) -> anyhow:: Result < Result < IncomingResponse , ErrorCode > > {
116
+ // wasmtime-wasi-http fills in scheme and authority for relative URLs
117
+ // (e.g. https://:443/<path>), which makes them hard to reason about.
118
+ // Undo that here.
119
+ let uri = request. uri_mut ( ) ;
120
+ if uri
121
+ . authority ( )
122
+ . is_some_and ( |authority| authority. host ( ) . is_empty ( ) )
123
+ {
124
+ let mut builder = http:: uri:: Builder :: new ( ) ;
125
+ if let Some ( paq) = uri. path_and_query ( ) {
126
+ builder = builder. path_and_query ( paq. clone ( ) ) ;
127
+ }
128
+ * uri = builder. build ( ) . unwrap ( ) ;
129
+ }
130
+ let span = tracing:: Span :: current ( ) ;
131
+ span. record ( "url.full" , uri. to_string ( ) ) ;
132
+
133
+ spin_telemetry:: inject_trace_context ( & mut request) ;
134
+
135
+ if let Some ( interceptor) = request_interceptor {
136
+ match interceptor. intercept ( & mut request) . await ? {
137
+ InterceptOutcome :: Continue => ( ) ,
138
+ InterceptOutcome :: Complete ( resp) => {
139
+ let resp = IncomingResponse {
140
+ resp,
141
+ worker : None ,
142
+ between_bytes_timeout : config. between_bytes_timeout ,
143
+ } ;
144
+ return Ok ( Ok ( resp) ) ;
145
+ }
146
+ }
147
+ }
148
+
149
+ let host = request. uri ( ) . host ( ) . unwrap_or_default ( ) ;
150
+ let tls_client_config = component_tls_configs. get_client_config ( host) . clone ( ) ;
151
+
143
152
if request. uri ( ) . authority ( ) . is_some ( ) {
144
153
// Absolute URI
145
154
let is_allowed = outbound_allowed_hosts
@@ -167,17 +176,15 @@ async fn send_request_impl(
167
176
config. use_tls = origin. use_tls ( ) ;
168
177
169
178
request. headers_mut ( ) . insert ( HOST , origin. host_header ( ) ) ;
170
- spin_telemetry:: inject_trace_context ( & mut request) ;
171
179
172
180
let path_and_query = request. uri ( ) . path_and_query ( ) . cloned ( ) ;
173
181
* request. uri_mut ( ) = origin. into_uri ( path_and_query) ;
174
182
}
175
183
176
184
let authority = request. uri ( ) . authority ( ) . context ( "authority not set" ) ?;
177
- let current_span = tracing:: Span :: current ( ) ;
178
- current_span. record ( "server.address" , authority. host ( ) ) ;
185
+ span. record ( "server.address" , authority. host ( ) ) ;
179
186
if let Some ( port) = authority. port ( ) {
180
- current_span . record ( "server.port" , port. as_u16 ( ) ) ;
187
+ span . record ( "server.port" , port. as_u16 ( ) ) ;
181
188
}
182
189
183
190
Ok ( send_request_handler ( request, config, tls_client_config, allow_private_ips) . await )
@@ -317,6 +324,8 @@ async fn send_request_handler(
317
324
. map_err ( hyper_request_error) ?
318
325
. map ( |body| body. map_err ( hyper_request_error) . boxed ( ) ) ;
319
326
327
+ tracing:: Span :: current ( ) . record ( "http.response.status_code" , resp. status ( ) . as_u16 ( ) ) ;
328
+
320
329
Ok ( wasmtime_wasi_http:: types:: IncomingResponse {
321
330
resp,
322
331
worker : Some ( worker) ,
0 commit comments