@@ -2,6 +2,8 @@ use std::collections::HashMap;
22
33use async_trait:: async_trait;
44
5+ use crate :: wit:: wasi:: io:: streams;
6+
57use super :: { Headers , IncomingRequest , IncomingResponse , OutgoingRequest , OutgoingResponse } ;
68
79use super :: { responses, NonUtf8BodyError , Request , Response } ;
@@ -61,12 +63,12 @@ impl TryFromIncomingRequest for Request {
6163 . method ( request. method ( ) )
6264 . uri ( request. uri ( ) )
6365 . headers ( request. headers ( ) )
64- . body (
65- request
66- . into_body ( )
67- . await
68- . map_err ( IncomingRequestError :: BodyConversionError ) ? ,
69- )
66+ . body ( request . into_body ( ) . await . map_err ( |e| {
67+ IncomingRequestError :: BodyConversionError ( anyhow :: anyhow! (
68+ "{}" ,
69+ e . to_debug_string ( )
70+ ) )
71+ } ) ? )
7072 . build ( ) )
7173 }
7274}
@@ -482,37 +484,59 @@ where
482484 }
483485}
484486
485- impl TryFrom < Request > for OutgoingRequest {
487+ /// A trait for converting a type into an `OutgoingRequest`
488+ pub trait TryIntoOutgoingRequest {
489+ /// The error if the conversion fails
490+ type Error ;
491+
492+ /// Turn the type into an `OutgoingRequest`
493+ ///
494+ /// If the implementor can be sure that the `OutgoingRequest::write` has not been called they
495+ /// can return a buffer as the second element of the returned tuple and `send` will send
496+ /// that as the request body.
497+ fn try_into_outgoing_request ( self ) -> Result < ( OutgoingRequest , Option < Vec < u8 > > ) , Self :: Error > ;
498+ }
499+
500+ impl TryIntoOutgoingRequest for OutgoingRequest {
501+ type Error = std:: convert:: Infallible ;
502+
503+ fn try_into_outgoing_request ( self ) -> Result < ( OutgoingRequest , Option < Vec < u8 > > ) , Self :: Error > {
504+ Ok ( ( self , None ) )
505+ }
506+ }
507+
508+ impl TryIntoOutgoingRequest for Request {
486509 type Error = std:: convert:: Infallible ;
487510
488- fn try_from ( req : Request ) -> Result < Self , Self :: Error > {
489- let headers = req
511+ fn try_into_outgoing_request ( self ) -> Result < ( OutgoingRequest , Option < Vec < u8 > > ) , Self :: Error > {
512+ let headers = self
490513 . headers ( )
491514 . map ( |( k, v) | ( k. to_owned ( ) , v. as_bytes ( ) . to_owned ( ) ) )
492515 . collect :: < Vec < _ > > ( ) ;
493- Ok ( OutgoingRequest :: new (
494- req . method ( ) ,
495- req . path_and_query ( ) ,
496- Some ( if req . is_https ( ) {
516+ let request = OutgoingRequest :: new (
517+ self . method ( ) ,
518+ self . path_and_query ( ) ,
519+ Some ( if self . is_https ( ) {
497520 & super :: Scheme :: Https
498521 } else {
499522 & super :: Scheme :: Http
500523 } ) ,
501- req . authority ( ) ,
524+ self . authority ( ) ,
502525 & Headers :: new ( & headers) ,
503- ) )
526+ ) ;
527+ Ok ( ( request, Some ( self . into_body ( ) ) ) )
504528 }
505529}
506530
507531#[ cfg( feature = "http" ) ]
508- impl < B > TryFrom < hyperium:: Request < B > > for OutgoingRequest
532+ impl < B > TryIntoOutgoingRequest for hyperium:: Request < B >
509533where
510534 B : TryIntoBody ,
511535 B :: Error : std:: error:: Error + Send + Sync + ' static ,
512536{
513537 type Error = anyhow:: Error ;
514- fn try_from ( req : hyperium :: Request < B > ) -> Result < Self , Self :: Error > {
515- let method = match req . method ( ) {
538+ fn try_into_outgoing_request ( self ) -> Result < ( OutgoingRequest , Option < Vec < u8 > > ) , Self :: Error > {
539+ let method = match self . method ( ) {
516540 & hyperium:: Method :: GET => super :: Method :: Get ,
517541 & hyperium:: Method :: POST => super :: Method :: Post ,
518542 & hyperium:: Method :: PUT => super :: Method :: Put ,
@@ -522,34 +546,36 @@ where
522546 & hyperium:: Method :: OPTIONS => super :: Method :: Options ,
523547 m => anyhow:: bail!( "Unsupported method: {m}" ) ,
524548 } ;
525- let headers = req
549+ let headers = self
526550 . headers ( )
527551 . into_iter ( )
528552 . map ( |( n, v) | ( n. as_str ( ) . to_owned ( ) , v. as_bytes ( ) . to_owned ( ) ) )
529553 . collect :: < Vec < _ > > ( ) ;
530- Ok ( OutgoingRequest :: new (
554+ let request = OutgoingRequest :: new (
531555 & method,
532- req . uri ( ) . path_and_query ( ) . map ( |p| p. as_str ( ) ) ,
533- req . uri ( )
556+ self . uri ( ) . path_and_query ( ) . map ( |p| p. as_str ( ) ) ,
557+ self . uri ( )
534558 . scheme ( )
535559 . map ( |s| match s. as_str ( ) {
536560 "http" => super :: Scheme :: Http ,
537561 "https" => super :: Scheme :: Https ,
538562 s => super :: Scheme :: Other ( s. to_owned ( ) ) ,
539563 } )
540564 . as_ref ( ) ,
541- req . uri ( ) . authority ( ) . map ( |a| a. as_str ( ) ) ,
565+ self . uri ( ) . authority ( ) . map ( |a| a. as_str ( ) ) ,
542566 & Headers :: new ( & headers) ,
543- ) )
567+ ) ;
568+ let buffer = TryIntoBody :: try_into_body ( self . into_body ( ) ) ?;
569+ Ok ( ( request, Some ( buffer) ) )
544570 }
545571}
546572
573+ /// A trait for converting from an `IncomingRequest`
547574#[ async_trait]
548- /// TODO
549575pub trait TryFromIncomingResponse {
550- /// TODO
576+ /// The error if conversion fails
551577 type Error ;
552- /// TODO
578+ /// Turn the `IncomingResponse` into the type
553579 async fn try_from_incoming_response ( resp : IncomingResponse ) -> Result < Self , Self :: Error >
554580 where
555581 Self : Sized ;
@@ -563,6 +589,18 @@ impl TryFromIncomingResponse for IncomingResponse {
563589 }
564590}
565591
592+ #[ async_trait]
593+ impl TryFromIncomingResponse for Response {
594+ type Error = streams:: Error ;
595+ async fn try_from_incoming_response ( resp : IncomingResponse ) -> Result < Self , Self :: Error > {
596+ Ok ( Response :: builder ( )
597+ . status ( resp. status ( ) )
598+ . headers ( resp. headers ( ) )
599+ . body ( resp. into_body ( ) . await ?)
600+ . build ( ) )
601+ }
602+ }
603+
566604#[ cfg( feature = "http" ) ]
567605#[ async_trait]
568606impl < B : TryFromBody > TryFromIncomingResponse for hyperium:: Response < B > {
0 commit comments