1
- use crate :: errors:: * ;
1
+ use crate :: errors:: { AzureError , UnexpectedHTTPResult } ;
2
+ #[ allow( unused_imports) ]
3
+ use crate :: Body ;
2
4
use async_trait:: async_trait;
3
5
use bytes:: Bytes ;
6
+ #[ allow( unused_imports) ]
7
+ use futures:: TryStreamExt ;
4
8
use http:: { Request , Response , StatusCode } ;
5
9
#[ cfg( feature = "enable_hyper" ) ]
10
+ #[ allow( unused_imports) ]
6
11
use hyper_rustls:: HttpsConnector ;
7
12
use serde:: Serialize ;
8
13
@@ -14,6 +19,17 @@ pub trait HttpClient: Send + Sync + std::fmt::Debug {
14
19
request : Request < Bytes > ,
15
20
) -> Result < Response < Bytes > , Box < dyn std:: error:: Error + Sync + Send > > ;
16
21
22
+ /// This function will be the only one remaining in the trait as soon as the trait stabilizes.
23
+ /// It will be renamed to `execute_request`. The other helper functions (ie
24
+ /// `execute_request_check_status`) will be removed since the status check will be
25
+ /// responsibility of another policy (not the transport one). It does not consume the request.
26
+ /// Implementors are expected to clone the necessary parts of the request and pass them to the
27
+ /// underlying transport.
28
+ async fn execute_request2 (
29
+ & self ,
30
+ request : & crate :: Request ,
31
+ ) -> Result < crate :: Response , Box < dyn std:: error:: Error + Sync + Send > > ;
32
+
17
33
async fn execute_request_check_status (
18
34
& self ,
19
35
request : Request < Bytes > ,
@@ -62,85 +78,127 @@ pub trait HttpClient: Send + Sync + std::fmt::Debug {
62
78
}
63
79
}
64
80
65
- #[ cfg( feature = "enable_hyper" ) ]
81
+ // TODO: To reimplement once the Request and Response are validated.
82
+ //#[cfg(feature = "enable_hyper")]
83
+ //#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
84
+ //#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
85
+ //impl HttpClient for hyper::Client<HttpsConnector<hyper::client::HttpConnector>> {
86
+ // async fn execute_request(
87
+ // &self,
88
+ // request: Request<Bytes>,
89
+ // ) -> Result<Response<Bytes>, Box<dyn std::error::Error + Sync + Send>> {
90
+ // let mut hyper_request = hyper::Request::builder()
91
+ // .uri(request.uri())
92
+ // .method(request.method());
93
+ //
94
+ // for header in request.headers() {
95
+ // hyper_request = hyper_request.header(header.0, header.1);
96
+ // }
97
+ //
98
+ // let hyper_request = hyper_request.body(hyper::Body::from(request.into_body()))?;
99
+ //
100
+ // let hyper_response = self.request(hyper_request).await?;
101
+ //
102
+ // let mut response = Response::builder()
103
+ // .status(hyper_response.status())
104
+ // .version(hyper_response.version());
105
+ //
106
+ // for (key, value) in hyper_response.headers() {
107
+ // response = response.header(key, value);
108
+ // }
109
+ //
110
+ // let response = response.body(hyper::body::to_bytes(hyper_response.into_body()).await?)?;
111
+ //
112
+ // Ok(response)
113
+ // }
114
+ //}
115
+
116
+ #[ cfg( feature = "enable_reqwest" ) ]
66
117
#[ cfg_attr( target_arch = "wasm32" , async_trait( ?Send ) ) ]
67
118
#[ cfg_attr( not( target_arch = "wasm32" ) , async_trait) ]
68
- impl HttpClient for hyper :: Client < HttpsConnector < hyper :: client :: HttpConnector > > {
119
+ impl HttpClient for reqwest :: Client {
69
120
async fn execute_request (
70
121
& self ,
71
122
request : Request < Bytes > ,
72
123
) -> Result < Response < Bytes > , Box < dyn std:: error:: Error + Sync + Send > > {
73
- let mut hyper_request = hyper :: Request :: builder ( )
74
- . uri ( request . uri ( ) )
75
- . method ( request. method ( ) ) ;
76
-
77
- for header in request. headers ( ) {
78
- hyper_request = hyper_request . header ( header. 0 , header . 1 ) ;
124
+ let mut reqwest_request = self . request (
125
+ request . method ( ) . clone ( ) ,
126
+ url :: Url :: parse ( & request. uri ( ) . to_string ( ) ) . unwrap ( ) ,
127
+ ) ;
128
+ for ( header, value ) in request. headers ( ) {
129
+ reqwest_request = reqwest_request . header ( header, value ) ;
79
130
}
80
131
81
- let hyper_request = hyper_request . body ( hyper :: Body :: from ( request. into_body ( ) ) ) ?;
132
+ let reqwest_request = reqwest_request . body ( request. into_body ( ) ) . build ( ) ?;
82
133
83
- let hyper_response = self . request ( hyper_request ) . await ?;
134
+ let reqwest_response = self . execute ( reqwest_request ) . await ?;
84
135
85
- let mut response = Response :: builder ( )
86
- . status ( hyper_response. status ( ) )
87
- . version ( hyper_response. version ( ) ) ;
136
+ let mut response = Response :: builder ( ) . status ( reqwest_response. status ( ) ) ;
88
137
89
- for ( key, value) in hyper_response . headers ( ) {
138
+ for ( key, value) in reqwest_response . headers ( ) {
90
139
response = response. header ( key, value) ;
91
140
}
92
141
93
- let response = response. body ( hyper :: body :: to_bytes ( hyper_response . into_body ( ) ) . await ?) ?;
142
+ let response = response. body ( reqwest_response . bytes ( ) . await ?) ?;
94
143
95
144
Ok ( response)
96
145
}
97
- }
98
146
99
- #[ cfg( feature = "enable_reqwest" ) ]
100
- #[ cfg_attr( target_arch = "wasm32" , async_trait( ?Send ) ) ]
101
- #[ cfg_attr( not( target_arch = "wasm32" ) , async_trait) ]
102
- impl HttpClient for reqwest:: Client {
103
- async fn execute_request (
147
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
148
+ async fn execute_request2 (
104
149
& self ,
105
- request : Request < Bytes > ,
106
- ) -> Result < Response < Bytes > , Box < dyn std:: error:: Error + Sync + Send > > {
107
- let mut reqwest_request =
108
- self . request ( request. method ( ) . clone ( ) , & request. uri ( ) . to_string ( ) ) ;
150
+ request : & crate :: Request ,
151
+ ) -> Result < crate :: Response , Box < dyn std:: error:: Error + Sync + Send > > {
152
+ let mut reqwest_request = self . request (
153
+ request. method ( ) . clone ( ) ,
154
+ url:: Url :: parse ( & request. uri ( ) . to_string ( ) ) . unwrap ( ) ,
155
+ ) ;
109
156
for header in request. headers ( ) {
110
157
reqwest_request = reqwest_request. header ( header. 0 , header. 1 ) ;
111
158
}
112
159
113
- let reqwest_request = reqwest_request. body ( request. into_body ( ) ) . build ( ) ?;
160
+ // We clone the body since we need to give ownership of it to
161
+ // Reqwest.
162
+ let body = request. clone_body ( ) ;
114
163
115
- let reqwest_response = self . execute ( reqwest_request) . await ?;
164
+ let reqwest_request = match body {
165
+ Body :: Bytes ( bytes) => reqwest_request. body ( bytes) . build ( ) ?,
166
+ Body :: SeekableStream ( mut seekable_stream) => {
167
+ seekable_stream. reset ( ) . await ?;
116
168
117
- let mut response = Response :: builder ( ) . status ( reqwest_response. status ( ) ) ;
169
+ reqwest_request
170
+ . body ( reqwest:: Body :: wrap_stream ( seekable_stream) )
171
+ . build ( ) ?
172
+ }
173
+ } ;
118
174
119
- if let Some ( version) = get_version ( & reqwest_response) {
120
- response = response. version ( version) ;
121
- }
175
+ let reqwest_response = self . execute ( reqwest_request) . await ?;
176
+ let mut response = crate :: ResponseBuilder :: new ( reqwest_response. status ( ) ) ;
122
177
123
178
for ( key, value) in reqwest_response. headers ( ) {
124
- response = response . header ( key, value) ;
179
+ response. with_header ( key, value. clone ( ) ) ;
125
180
}
126
181
127
- let response = response. body ( reqwest_response. bytes ( ) . await ?) ?;
182
+ let response = response. with_pinned_stream ( Box :: pin (
183
+ reqwest_response. bytes_stream ( ) . map_err ( |err| err. into ( ) ) ,
184
+ ) ) ;
128
185
129
186
Ok ( response)
130
187
}
131
- }
132
188
133
- // wasm can not get the http version
134
- #[ cfg( feature = "enable_reqwest" ) ]
135
- #[ cfg( target_arch = "wasm32" ) ]
136
- fn get_version ( _response : & reqwest:: Response ) -> Option < http:: Version > {
137
- None
138
- }
189
+ #[ cfg( target_arch = "wasm32" ) ]
190
+ /// Stub implementation. Will remove as soon as reqwest starts
191
+ /// supporting wasm.
192
+ async fn execute_request2 (
193
+ & self ,
194
+ _request : & crate :: Request ,
195
+ ) -> Result < crate :: Response , Box < dyn std:: error:: Error + Sync + Send > > {
196
+ let response = crate :: ResponseBuilder :: new ( http:: StatusCode :: OK ) ;
139
197
140
- # [ cfg ( feature = "enable_reqwest" ) ]
141
- # [ cfg ( not ( target_arch = "wasm32" ) ) ]
142
- fn get_version ( response : & reqwest :: Response ) -> Option < http :: Version > {
143
- Some ( response . version ( ) )
198
+ let response = response . with_pinned_stream ( Box :: pin ( crate :: BytesStream :: new_empty ( ) ) ) ;
199
+
200
+ Ok ( response )
201
+ }
144
202
}
145
203
146
204
/// Serialize to json
0 commit comments