1
1
use bytes:: Bytes ;
2
2
use std:: collections:: HashMap ;
3
3
use std:: future;
4
+ use std:: pin:: Pin ;
4
5
use std:: sync:: mpsc:: { Receiver , TryRecvError } ;
5
6
use std:: sync:: { Arc , Mutex } ;
7
+ use std:: task:: { Context , Poll } ;
6
8
use std:: time:: Duration ;
7
9
use tokio:: sync:: watch;
8
10
use tokio:: time:: Instant ;
@@ -206,7 +208,6 @@ impl PoolClient {
206
208
& mut self ,
207
209
req : Request < Body > ,
208
210
) -> Result < Response < ResponseBody > , BoxError > {
209
- use http_body_util:: { BodyExt , Full } ;
210
211
use hyper:: body:: Body as _;
211
212
212
213
let ( head, req_body) = req. into_parts ( ) ;
@@ -232,14 +233,7 @@ impl PoolClient {
232
233
233
234
let resp = stream. recv_response ( ) . await ?;
234
235
235
- let mut resp_body = Vec :: new ( ) ;
236
- while let Some ( chunk) = stream. recv_data ( ) . await ? {
237
- resp_body. extend ( chunk. chunk ( ) )
238
- }
239
-
240
- let resp_body = Full :: new ( resp_body. into ( ) )
241
- . map_err ( |never| match never { } )
242
- . boxed ( ) ;
236
+ let resp_body = crate :: async_impl:: body:: boxed ( Incoming :: new ( stream, resp. headers ( ) ) ) ;
243
237
244
238
Ok ( resp. map ( |_| resp_body) )
245
239
}
@@ -275,6 +269,52 @@ impl PoolConnection {
275
269
}
276
270
}
277
271
272
+ struct Incoming < S , B > {
273
+ inner : h3:: client:: RequestStream < S , B > ,
274
+ content_length : Option < u64 > ,
275
+ }
276
+
277
+ impl < S , B > Incoming < S , B > {
278
+ fn new ( stream : h3:: client:: RequestStream < S , B > , headers : & http:: header:: HeaderMap ) -> Self {
279
+ Self {
280
+ inner : stream,
281
+ content_length : headers
282
+ . get ( http:: header:: CONTENT_LENGTH )
283
+ . and_then ( |h| h. to_str ( ) . ok ( ) )
284
+ . and_then ( |v| v. parse ( ) . ok ( ) ) ,
285
+ }
286
+ }
287
+ }
288
+
289
+ impl < S , B > http_body:: Body for Incoming < S , B >
290
+ where
291
+ S : h3:: quic:: RecvStream ,
292
+ {
293
+ type Data = Bytes ;
294
+ type Error = crate :: error:: Error ;
295
+
296
+ fn poll_frame (
297
+ mut self : Pin < & mut Self > ,
298
+ cx : & mut Context ,
299
+ ) -> Poll < Option < Result < hyper:: body:: Frame < Self :: Data > , Self :: Error > > > {
300
+ match futures_core:: ready!( self . inner. poll_recv_data( cx) ) {
301
+ Ok ( Some ( mut b) ) => Poll :: Ready ( Some ( Ok ( hyper:: body:: Frame :: data (
302
+ b. copy_to_bytes ( b. remaining ( ) ) ,
303
+ ) ) ) ) ,
304
+ Ok ( None ) => Poll :: Ready ( None ) ,
305
+ Err ( e) => Poll :: Ready ( Some ( Err ( crate :: error:: body ( e) ) ) ) ,
306
+ }
307
+ }
308
+
309
+ fn size_hint ( & self ) -> hyper:: body:: SizeHint {
310
+ if let Some ( content_length) = self . content_length {
311
+ hyper:: body:: SizeHint :: with_exact ( content_length)
312
+ } else {
313
+ hyper:: body:: SizeHint :: default ( )
314
+ }
315
+ }
316
+ }
317
+
278
318
pub ( crate ) fn extract_domain ( uri : & mut Uri ) -> Result < Key , Error > {
279
319
let uri_clone = uri. clone ( ) ;
280
320
match ( uri_clone. scheme ( ) , uri_clone. authority ( ) ) {
0 commit comments