@@ -226,9 +226,14 @@ class winhttp_request_context : public request_context
226226
227227 std::char_traits<uint8_t >::pos_type m_readbuf_pos;
228228
229- // The read-write buffer used to save the outgoing body data,
230- // if the authentication challenges failed, resend the body data from this buffer.
231- std::shared_ptr<streams::producer_consumer_buffer<uint8_t >> m_rwbuf_copy;
229+ // If the user specified that to guarantee data buffering of request data, in case of challenged authentication requests, etc...
230+ // Then if the request stream buffer doesn't support seeking we need to copy the body chunks as it is sent.
231+ concurrency::streams::istream m_readStream;
232+ std::unique_ptr<concurrency::streams::container_buffer<std::vector<uint8_t >>> m_readBufferCopy;
233+ virtual concurrency::streams::streambuf<uint8_t > _get_readbuffer ()
234+ {
235+ return m_readStream.streambuf ();
236+ }
232237
233238 memory_holder m_body_data;
234239
@@ -261,7 +266,8 @@ class winhttp_request_context : public request_context
261266 m_body_data(),
262267 m_remaining_to_write(0 ),
263268 m_proxy_authentication_tried(false ),
264- m_server_authentication_tried(false )
269+ m_server_authentication_tried(false ),
270+ m_readStream(request.body())
265271 {
266272 }
267273};
@@ -614,10 +620,10 @@ class winhttp_client : public _http_client_communicator
614620 return ;
615621 }
616622
617- // Initialize the local producer_consumer buffer .
618- if (winhttp_context->m_bodyType == transfer_encoding_chunked && !winhttp_context-> _get_readbuffer ().can_seek () && has_credentials ( winhttp_context))
623+ // Only need to cache the request body if user specified and the request stream doesn't support seeking .
624+ if (winhttp_context->m_bodyType != no_body && client_config ().buffer_request () && ! winhttp_context-> _get_readbuffer (). can_seek ( ))
619625 {
620- winhttp_context->m_rwbuf_copy = std::make_shared< streams::producer_consumer_buffer< uint8_t >>();
626+ winhttp_context->m_readBufferCopy = ::utility::details::make_unique<::concurrency:: streams::container_buffer<std::vector< uint8_t > >>();
621627 }
622628
623629 _start_request_send (winhttp_context, content_length);
@@ -661,7 +667,7 @@ class winhttp_client : public _http_client_communicator
661667 return ;
662668 }
663669
664- // Capure the current read position of the stream.
670+ // Capture the current read position of the stream.
665671 auto rbuf = winhttp_context->_get_readbuffer ();
666672 if ( !_check_streambuf (winhttp_context, rbuf, _XPLATSTR (" Input stream is not open" )) )
667673 {
@@ -708,19 +714,10 @@ class winhttp_client : public _http_client_communicator
708714 try
709715 {
710716 bytes_read = op.get ();
711- if (!p_request_context-> _get_readbuffer (). can_seek () && has_credentials (p_request_context)
712- && ! p_request_context->m_server_authentication_tried && !p_request_context-> m_proxy_authentication_tried )
717+ // If the read buffer for copying exists then write to it.
718+ if ( p_request_context->m_readBufferCopy )
713719 {
714- // If the user buffer is not seekable, the credentials are provided and the authentication challenges are not tried,
715- // copy the user buffer to a local producer_consumer buffer for resending if authentication failed.
716- try
717- {
718- p_request_context->m_rwbuf_copy ->putn (&p_request_context->m_body_data .get ()[http::details::chunked_encoding::data_offset], bytes_read).wait ();
719- }
720- catch (...)
721- {
722- p_request_context->report_exception (std::current_exception ());
723- }
720+ p_request_context->m_readBufferCopy ->putn (&p_request_context->m_body_data .get ()[http::details::chunked_encoding::data_offset], bytes_read).wait ();
724721 }
725722 }
726723 catch (...)
@@ -737,18 +734,11 @@ class winhttp_client : public _http_client_communicator
737734 if (bytes_read == 0 )
738735 {
739736 p_request_context->m_bodyType = no_body;
740- if (!p_request_context->_get_readbuffer ().can_seek () && has_credentials (p_request_context)
741- && !p_request_context->m_server_authentication_tried && !p_request_context->m_proxy_authentication_tried )
737+ if (p_request_context->m_readBufferCopy )
742738 {
743- try
744- {
745- p_request_context->m_rwbuf_copy ->close (std::ios_base::out).wait ();
746-
747- }
748- catch (...)
749- {
750- p_request_context->report_exception (std::current_exception ());
751- }
739+ // Move the saved buffer into the read buffer.
740+ p_request_context->m_readStream = concurrency::streams::container_stream<std::vector<uint8_t >>::open_istream (std::move (p_request_context->m_readBufferCopy ->collection ()));
741+ p_request_context->m_readBufferCopy .reset ();
752742 }
753743 }
754744
@@ -764,24 +754,11 @@ class winhttp_client : public _http_client_communicator
764754 }
765755 };
766756
767- if ((!p_request_context->m_server_authentication_tried && !p_request_context->m_proxy_authentication_tried ) || p_request_context->_get_readbuffer ().can_seek ())
768- {
769- if (!_check_streambuf (p_request_context, p_request_context->_get_readbuffer (), _XPLATSTR (" Input stream is not open" )))
770- {
771- return ;
772- }
773-
774- p_request_context->_get_readbuffer ().getn (&p_request_context->m_body_data .get ()[http::details::chunked_encoding::data_offset], chunk_size).then (after_read);
775- }
776- else
757+ if (!_check_streambuf (p_request_context, p_request_context->_get_readbuffer (), _XPLATSTR (" Input stream is not open" )))
777758 {
778- if (!_check_streambuf (p_request_context, *p_request_context->m_rwbuf_copy , _XPLATSTR (" Locally copied input stream is not open" )))
779- {
780- return ;
781- }
782- // Resending the request after authentication failed, we need to read the body data from the copied buffer.
783- p_request_context->m_rwbuf_copy ->getn (&p_request_context->m_body_data .get ()[http::details::chunked_encoding::data_offset], chunk_size).then (after_read);
759+ return ;
784760 }
761+ p_request_context->_get_readbuffer ().getn (&p_request_context->m_body_data .get ()[http::details::chunked_encoding::data_offset], chunk_size).then (after_read);
785762 }
786763
787764 static void _multiple_segment_write_data (_In_ winhttp_request_context * p_request_context)
@@ -1333,7 +1310,7 @@ class winhttp_client : public _http_client_communicator
13331310http_network_handler::http_network_handler (uri base_uri, http_client_config client_config) :
13341311 m_http_client_impl(std::make_shared<details::winhttp_client>(std::move(base_uri), std::move(client_config)))
13351312{
1336- }
1313+ }
13371314
13381315pplx::task<http_response> http_network_handler::propagate (http_request request)
13391316{
0 commit comments