18
18
*/
19
19
//! HTTP transport and connection components
20
20
21
- #[ cfg( all( any( feature = "native-tls" , feature = "rustls-tls" ) , not( target_arch = "wasm32" ) ) ) ]
21
+ #[ cfg( all( target_arch = "wasm32" , any( feature = "native-tls" , feature = "rustls-tls" ) ) ) ]
22
+ compile_error ! ( "TLS features are not compatible with the wasm target" ) ;
23
+
24
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
22
25
use crate :: auth:: ClientCertificate ;
23
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
26
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
24
27
use crate :: cert:: CertificateValidation ;
25
28
use crate :: {
26
29
auth:: Credentials ,
@@ -130,6 +133,8 @@ fn build_meta() -> String {
130
133
meta. push_str ( ",tls=n" ) ;
131
134
} else if cfg ! ( feature = "rustls-tls" ) {
132
135
meta. push_str ( ",tls=r" ) ;
136
+ } else if cfg ! ( target_arch = "wasm32" ) {
137
+ meta. push_str ( ",tls=w" ) ;
133
138
}
134
139
135
140
meta
@@ -138,9 +143,9 @@ fn build_meta() -> String {
138
143
/// Builds a HTTP transport to make API calls to Elasticsearch
139
144
pub struct TransportBuilder {
140
145
client_builder : reqwest:: ClientBuilder ,
141
- conn_pool : Box < dyn ConnectionPool > ,
146
+ conn_pool : Arc < dyn ConnectionPool > ,
142
147
credentials : Option < Credentials > ,
143
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
148
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
144
149
cert_validation : Option < CertificateValidation > ,
145
150
#[ cfg( not( target_arch = "wasm32" ) ) ]
146
151
proxy : Option < Url > ,
@@ -150,6 +155,7 @@ pub struct TransportBuilder {
150
155
disable_proxy : bool ,
151
156
headers : HeaderMap ,
152
157
meta_header : bool ,
158
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
153
159
timeout : Option < Duration > ,
154
160
}
155
161
@@ -162,9 +168,9 @@ impl TransportBuilder {
162
168
{
163
169
Self {
164
170
client_builder : reqwest:: ClientBuilder :: new ( ) ,
165
- conn_pool : Box :: new ( conn_pool) ,
171
+ conn_pool : Arc :: new ( conn_pool) ,
166
172
credentials : None ,
167
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
173
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
168
174
cert_validation : None ,
169
175
#[ cfg( not( target_arch = "wasm32" ) ) ]
170
176
proxy : None ,
@@ -174,6 +180,7 @@ impl TransportBuilder {
174
180
disable_proxy : false ,
175
181
headers : HeaderMap :: new ( ) ,
176
182
meta_header : true ,
183
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
177
184
timeout : None ,
178
185
}
179
186
}
@@ -211,7 +218,7 @@ impl TransportBuilder {
211
218
/// Validation applied to the certificate provided to establish a HTTPS connection.
212
219
/// By default, full validation is applied. When using a self-signed certificate,
213
220
/// different validation can be applied.
214
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
221
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
215
222
pub fn cert_validation ( mut self , validation : CertificateValidation ) -> Self {
216
223
self . cert_validation = Some ( validation) ;
217
224
self
@@ -249,6 +256,7 @@ impl TransportBuilder {
249
256
///
250
257
/// The timeout is applied from when the request starts connecting until the response body has finished.
251
258
/// Default is no timeout.
259
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
252
260
pub fn timeout ( mut self , timeout : Duration ) -> Self {
253
261
self . timeout = Some ( timeout) ;
254
262
self
@@ -267,7 +275,7 @@ impl TransportBuilder {
267
275
client_builder = client_builder. timeout ( t) ;
268
276
}
269
277
270
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
278
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
271
279
{
272
280
if let Some ( Credentials :: Certificate ( cert) ) = & self . credentials {
273
281
client_builder = match cert {
@@ -289,7 +297,7 @@ impl TransportBuilder {
289
297
} ;
290
298
}
291
299
292
- #[ cfg( all ( any( feature = "native-tls" , feature = "rustls-tls" ) , not ( target_arch = "wasm32" ) ) ) ]
300
+ #[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
293
301
if let Some ( v) = self . cert_validation {
294
302
client_builder = match v {
295
303
CertificateValidation :: Default => client_builder,
@@ -326,7 +334,7 @@ impl TransportBuilder {
326
334
let client = client_builder. build ( ) ?;
327
335
Ok ( Transport {
328
336
client,
329
- conn_pool : Arc :: new ( self . conn_pool ) ,
337
+ conn_pool : self . conn_pool ,
330
338
credentials : self . credentials ,
331
339
send_meta : self . meta_header ,
332
340
} )
@@ -373,7 +381,7 @@ impl Connection {
373
381
pub struct Transport {
374
382
client : reqwest:: Client ,
375
383
credentials : Option < Credentials > ,
376
- conn_pool : Arc < Box < dyn ConnectionPool > > ,
384
+ conn_pool : Arc < dyn ConnectionPool > ,
377
385
send_meta : bool ,
378
386
}
379
387
@@ -494,23 +502,7 @@ impl Transport {
494
502
// on a specific request, we want it to overwrite.
495
503
if let Some ( c) = & self . credentials {
496
504
request_builder = match c {
497
- Credentials :: Basic ( u, p) => {
498
- #[ cfg( not( target_arch = "wasm32" ) ) ]
499
- {
500
- request_builder. basic_auth ( u, Some ( p) )
501
- }
502
- #[ cfg( target_arch = "wasm32" ) ]
503
- {
504
- // Missing basic_auth in the wasm32 target
505
- let mut header_value = b"Basic " . to_vec ( ) ;
506
- {
507
- let mut encoder = Base64Encoder :: new ( & mut header_value, base64:: STANDARD ) ;
508
- // The unwraps here are fine because Vec::write* is infallible.
509
- write ! ( encoder, "{}:{}" , u, p) . unwrap ( ) ;
510
- }
511
- request_builder. header ( reqwest:: header:: AUTHORIZATION , header_value)
512
- }
513
- } ,
505
+ Credentials :: Basic ( u, p) => request_builder. basic_auth ( u, Some ( p) ) ,
514
506
Credentials :: Bearer ( t) => request_builder. bearer_auth ( t) ,
515
507
#[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
516
508
Credentials :: Certificate ( _) => request_builder,
@@ -592,6 +584,47 @@ impl Transport {
592
584
) ?)
593
585
}
594
586
587
+ async fn reseed ( & self ) {
588
+ // Requests will execute against old connection pool during reseed
589
+ let connection = self . conn_pool . next ( ) ;
590
+
591
+ // Build node info request
592
+ let node_request = self . request_builder (
593
+ & connection,
594
+ Method :: Get ,
595
+ "_nodes/http?filter_path=nodes.*.http" ,
596
+ HeaderMap :: default ( ) ,
597
+ None :: < & ( ) > ,
598
+ None :: < ( ) > ,
599
+ None ,
600
+ ) . unwrap ( ) ;
601
+
602
+ let scheme = connection. url . scheme ( ) ;
603
+ let resp = node_request. send ( ) . await . unwrap ( ) ;
604
+ let json: Value = resp. json ( ) . await . unwrap ( ) ;
605
+ let connections: Vec < Connection > = json[ "nodes" ]
606
+ . as_object ( )
607
+ . unwrap ( )
608
+ . iter ( )
609
+ . map ( |( _, node) | {
610
+ let address = node[ "http" ] [ "publish_address" ]
611
+ . as_str ( )
612
+ . or_else ( || {
613
+ Some (
614
+ node[ "http" ] [ "bound_address" ] . as_array ( ) . unwrap ( ) [ 0 ]
615
+ . as_str ( )
616
+ . unwrap ( ) ,
617
+ )
618
+ } )
619
+ . unwrap ( ) ;
620
+ let url = Self :: parse_to_url ( address, scheme) . unwrap ( ) ;
621
+ Connection :: new ( url)
622
+ } )
623
+ . collect ( ) ;
624
+
625
+ self . conn_pool . reseed ( connections) ;
626
+ }
627
+
595
628
/// Creates an asynchronous request that can be awaited
596
629
pub async fn send < B , Q > (
597
630
& self ,
@@ -606,47 +639,19 @@ impl Transport {
606
639
B : Body ,
607
640
Q : Serialize + ?Sized ,
608
641
{
609
- // Requests will execute against old connection pool during reseed
610
642
if self . conn_pool . reseedable ( ) {
611
- let conn_pool = self . conn_pool . clone ( ) ;
612
- let connection = conn_pool. next ( ) ;
613
-
614
- // Build node info request
615
- let node_request = self . request_builder (
616
- & connection,
617
- Method :: Get ,
618
- "_nodes/http?filter_path=nodes.*.http" ,
619
- headers. clone ( ) ,
620
- None :: < & Q > ,
621
- None :: < B > ,
622
- timeout,
623
- ) ?;
624
-
625
- tokio:: spawn ( async move {
626
- let scheme = connection. url . scheme ( ) ;
627
- let resp = node_request. send ( ) . await . unwrap ( ) ;
628
- let json: Value = resp. json ( ) . await . unwrap ( ) ;
629
- let connections: Vec < Connection > = json[ "nodes" ]
630
- . as_object ( )
631
- . unwrap ( )
632
- . iter ( )
633
- . map ( |( _, node) | {
634
- let address = node[ "http" ] [ "publish_address" ]
635
- . as_str ( )
636
- . or_else ( || {
637
- Some (
638
- node[ "http" ] [ "bound_address" ] . as_array ( ) . unwrap ( ) [ 0 ]
639
- . as_str ( )
640
- . unwrap ( ) ,
641
- )
642
- } )
643
- . unwrap ( ) ;
644
- let url = Self :: parse_to_url ( address, scheme) . unwrap ( ) ;
645
- Connection :: new ( url)
646
- } )
647
- . collect ( ) ;
648
- conn_pool. reseed ( connections) ;
649
- } ) ;
643
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
644
+ {
645
+ let transport = self . clone ( ) ;
646
+ tokio:: spawn ( async move { transport. reseed ( ) . await } ) ;
647
+ }
648
+ #[ cfg( target_arch = "wasm32" ) ]
649
+ {
650
+ // Reseed synchronously (i.e. do not spawn a background task) in WASM.
651
+ // Running in the background is platform-dependent (web-sys / wasi), we'll
652
+ // address this if synchronous reseed is an issue.
653
+ self . reseed ( ) . await
654
+ }
650
655
}
651
656
652
657
let connection = self . conn_pool . next ( ) ;
0 commit comments