@@ -8,11 +8,12 @@ use std::time::Duration;
88
99use bytes:: Bytes ;
1010use h2:: client:: SendRequest ;
11- use http:: Request ;
11+ use h2:: server:: SendResponse ;
12+ use http:: { Request , Response , StatusCode } ;
1213
1314use vey_h2:: {
14- H2StreamFromChunkedTransfer , H2StreamFromChunkedTransferError , H2StreamToChunkedTransfer ,
15- H2StreamToChunkedTransferError , RequestExt ,
15+ H2ResponseHeaderReceiver , H2StreamFromChunkedTransfer , H2StreamFromChunkedTransferError ,
16+ H2StreamToChunkedTransfer , H2StreamToChunkedTransferError , RequestExt ,
1617} ;
1718use vey_http:: server:: HttpAdaptedRequest ;
1819use vey_io_ext:: { IdleCheck , LimitedBufReadExt , StreamCopyConfig } ;
@@ -110,7 +111,9 @@ impl<I: IdleCheck> BidirectionalRecvHttpRequest<'_, I> {
110111 state : & mut ReqmodAdaptationRunState ,
111112 mut clt_body_transfer : & mut H2StreamToChunkedTransfer < ' _ , IcapClientWriter > ,
112113 orig_http_request : Request < ( ) > ,
113- mut ups_send_request : SendRequest < Bytes > ,
114+ mut ups_send_req : SendRequest < Bytes > ,
115+ clt_send_rsp : & mut SendResponse < Bytes > ,
116+ mut allow_continue : bool ,
114117 ) -> Result < ReqmodAdaptationEndState , H2ReqmodAdaptationError > {
115118 let http_req = HttpAdaptedRequest :: parse (
116119 self . icap_reader ,
@@ -120,7 +123,7 @@ impl<I: IdleCheck> BidirectionalRecvHttpRequest<'_, I> {
120123 . await ?;
121124
122125 let final_req = orig_http_request. adapt_to ( & http_req) ;
123- let ( mut ups_recv_rsp , mut ups_send_stream) = ups_send_request
126+ let ( rsp_fut , mut ups_send_stream) = ups_send_req
124127 . send_request ( final_req, false )
125128 . map_err ( H2ReqmodAdaptationError :: HttpUpstreamSendHeadFailed ) ?;
126129 state. mark_ups_send_header ( ) ;
@@ -133,22 +136,51 @@ impl<I: IdleCheck> BidirectionalRecvHttpRequest<'_, I> {
133136 self . http_trailer_max_size ,
134137 ) ;
135138
139+ let mut ups_recv_rsp = H2ResponseHeaderReceiver :: new ( rsp_fut) ;
140+
136141 let mut idle_interval = self . idle_checker . interval_timer ( ) ;
137142 let mut idle_count = 0 ;
138143
139144 loop {
140145 tokio:: select! {
141- r = & mut ups_recv_rsp => {
142- return match r {
146+ r = ups_recv_rsp. recv_header ( ) => {
147+ match r {
143148 Ok ( ups_rsp) => {
144- state. mark_ups_recv_header( ) ;
145- if ups_body_transfer. finished( ) {
146- self . icap_read_finished = true ;
149+ match ups_rsp. status( ) {
150+ StatusCode :: CONTINUE => {
151+ if allow_continue {
152+ clt_send_rsp
153+ . send_informational( ups_rsp)
154+ . map_err( H2ReqmodAdaptationError :: HttpClientSendResponseFailed ) ?;
155+ allow_continue = false ;
156+ } else {
157+ return Err ( H2ReqmodAdaptationError :: InvalidUpstreamContinueResponse ) ;
158+ }
159+ }
160+ StatusCode :: EARLY_HINTS => {
161+ clt_send_rsp
162+ . send_informational( ups_rsp)
163+ . map_err( H2ReqmodAdaptationError :: HttpClientSendResponseFailed ) ?;
164+ }
165+ status => {
166+ state. mark_ups_recv_header( ) ;
167+ return if let Some ( body) = ups_recv_rsp. take_body( ) {
168+ let ( headers, _) = ups_rsp. into_parts( ) ;
169+ if ups_body_transfer. finished( ) {
170+ self . icap_read_finished = true ;
171+ }
172+ let ups_rsp = Response :: from_parts( headers, body) ;
173+ Ok ( ReqmodAdaptationEndState :: AdaptedTransferred ( http_req, ups_rsp) )
174+ } else {
175+ Err ( H2ReqmodAdaptationError :: UnsupportedInformationalResponse (
176+ status,
177+ ) )
178+ } ;
179+ }
147180 }
148- Ok ( ReqmodAdaptationEndState :: AdaptedTransferred ( http_req, ups_rsp) )
149181 }
150- Err ( e) => Err ( H2ReqmodAdaptationError :: HttpUpstreamRecvResponseFailed ( e) ) ,
151- } ;
182+ Err ( e) => return Err ( H2ReqmodAdaptationError :: HttpUpstreamRecvResponseFailed ( e) ) ,
183+ }
152184 }
153185 r = & mut clt_body_transfer => {
154186 return match r {
@@ -157,7 +189,7 @@ impl<I: IdleCheck> BidirectionalRecvHttpRequest<'_, I> {
157189 Ok ( _) => {
158190 state. mark_ups_send_all( ) ;
159191 self . icap_read_finished = true ;
160- let ups_rsp = recv_ups_response_head_after_transfer( ups_recv_rsp, self . http_rsp_head_recv_timeout) . await ?;
192+ let ups_rsp = recv_ups_response_head_after_transfer( & mut ups_recv_rsp, clt_send_rsp , allow_continue , self . http_rsp_head_recv_timeout) . await ?;
161193 Ok ( ReqmodAdaptationEndState :: AdaptedTransferred ( http_req, ups_rsp) )
162194 }
163195 Err ( H2StreamFromChunkedTransferError :: ReadError ( e) ) => Err ( H2ReqmodAdaptationError :: IcapServerReadFailed ( e) ) ,
@@ -176,7 +208,7 @@ impl<I: IdleCheck> BidirectionalRecvHttpRequest<'_, I> {
176208 Ok ( _) => {
177209 state. mark_ups_send_all( ) ;
178210 self . icap_read_finished = true ;
179- let ups_rsp = recv_ups_response_head_after_transfer( ups_recv_rsp, self . http_rsp_head_recv_timeout) . await ?;
211+ let ups_rsp = recv_ups_response_head_after_transfer( & mut ups_recv_rsp, clt_send_rsp , allow_continue , self . http_rsp_head_recv_timeout) . await ?;
180212 Ok ( ReqmodAdaptationEndState :: AdaptedTransferred ( http_req, ups_rsp) )
181213 }
182214 Err ( H2StreamFromChunkedTransferError :: ReadError ( e) ) => Err ( H2ReqmodAdaptationError :: IcapServerReadFailed ( e) ) ,
0 commit comments