@@ -226,9 +226,14 @@ class winhttp_request_context : public request_context
226
226
227
227
std::char_traits<uint8_t >::pos_type m_readbuf_pos;
228
228
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
+ }
232
237
233
238
memory_holder m_body_data;
234
239
@@ -261,7 +266,8 @@ class winhttp_request_context : public request_context
261
266
m_body_data(),
262
267
m_remaining_to_write(0 ),
263
268
m_proxy_authentication_tried(false ),
264
- m_server_authentication_tried(false )
269
+ m_server_authentication_tried(false ),
270
+ m_readStream(request.body())
265
271
{
266
272
}
267
273
};
@@ -614,10 +620,10 @@ class winhttp_client : public _http_client_communicator
614
620
return ;
615
621
}
616
622
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 ( ))
619
625
{
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 > >>();
621
627
}
622
628
623
629
_start_request_send (winhttp_context, content_length);
@@ -661,7 +667,7 @@ class winhttp_client : public _http_client_communicator
661
667
return ;
662
668
}
663
669
664
- // Capure the current read position of the stream.
670
+ // Capture the current read position of the stream.
665
671
auto rbuf = winhttp_context->_get_readbuffer ();
666
672
if ( !_check_streambuf (winhttp_context, rbuf, _XPLATSTR (" Input stream is not open" )) )
667
673
{
@@ -708,19 +714,10 @@ class winhttp_client : public _http_client_communicator
708
714
try
709
715
{
710
716
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 )
713
719
{
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 ();
724
721
}
725
722
}
726
723
catch (...)
@@ -737,18 +734,11 @@ class winhttp_client : public _http_client_communicator
737
734
if (bytes_read == 0 )
738
735
{
739
736
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 )
742
738
{
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 ();
752
742
}
753
743
}
754
744
@@ -764,24 +754,11 @@ class winhttp_client : public _http_client_communicator
764
754
}
765
755
};
766
756
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" )))
777
758
{
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 ;
784
760
}
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);
785
762
}
786
763
787
764
static void _multiple_segment_write_data (_In_ winhttp_request_context * p_request_context)
@@ -1333,7 +1310,7 @@ class winhttp_client : public _http_client_communicator
1333
1310
http_network_handler::http_network_handler (uri base_uri, http_client_config client_config) :
1334
1311
m_http_client_impl(std::make_shared<details::winhttp_client>(std::move(base_uri), std::move(client_config)))
1335
1312
{
1336
- }
1313
+ }
1337
1314
1338
1315
pplx::task<http_response> http_network_handler::propagate (http_request request)
1339
1316
{
0 commit comments