Skip to content

Commit e1a8e0e

Browse files
author
Valtteri Heikkila
committed
Merge remote-tracking branch 'upstream/development' into cancellation
2 parents e3bbfbf + 6004394 commit e1a8e0e

File tree

7 files changed

+105
-74
lines changed

7 files changed

+105
-74
lines changed

Release/include/cpprest/http_client.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class http_client_config
9898
http_client_config() :
9999
m_guarantee_order(false),
100100
m_timeout(utility::seconds(30)),
101-
m_chunksize(64 * 1024)
101+
m_chunksize(0)
102102
#if !defined(__cplusplus_winrt)
103103
, m_validate_certificates(true)
104104
#endif
@@ -227,7 +227,7 @@ class http_client_config
227227
/// <returns>The internal buffer size used by the http client when sending and receiving data from the network.</returns>
228228
size_t chunksize() const
229229
{
230-
return m_chunksize;
230+
return m_chunksize == 0 ? 64 * 1024 : m_chunksize;
231231
}
232232

233233
/// <summary>
@@ -240,6 +240,16 @@ class http_client_config
240240
m_chunksize = size;
241241
}
242242

243+
/// <summary>
244+
/// Returns true if the default chunk size is in use.
245+
/// <remarks>If true, implementations are allowed to choose whatever size is best.</remarks>
246+
/// </summary>
247+
/// <returns>True if default, false if set by user.</returns>
248+
bool is_default_chunksize() const
249+
{
250+
return m_chunksize == 0;
251+
}
252+
243253
#if !defined(__cplusplus_winrt)
244254
/// <summary>
245255
/// Gets the server certificate validation property.

Release/include/cpprest/http_client_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class request_context
140140
/// <summary>
141141
/// Completes this request, setting the underlying task completion event, and cleaning up the handles
142142
/// </summary>
143-
void complete_request(size_t body_size)
143+
void complete_request(utility::size64_t body_size)
144144
{
145145
m_response._get_impl()->_complete(body_size);
146146

Release/src/http/client/http_win7.cpp

Lines changed: 88 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ class winhttp_client : public _http_client_communicator
589589
if(!WinHttpAddRequestHeaders(
590590
winhttp_context->m_request_handle,
591591
flattened_headers.c_str(),
592-
(DWORD)flattened_headers.length(),
592+
static_cast<DWORD>(flattened_headers.length()),
593593
WINHTTP_ADDREQ_FLAG_ADD))
594594
{
595595
request->report_error(GetLastError(), _XPLATSTR("Error adding request headers"));
@@ -704,6 +704,44 @@ class winhttp_client : public _http_client_communicator
704704
return has_proxy_credentials || has_server_credentials;
705705
}
706706

707+
// Helper function to query/read next part of response data from winhttp.
708+
static void read_next_response_chunk(winhttp_request_context *pContext, DWORD bytesRead, bool firstRead=false)
709+
{
710+
const bool defaultChunkSize = pContext->m_http_client->client_config().is_default_chunksize();
711+
712+
// If user specified a chunk size then read in chunks instead of using query data avaliable.
713+
if (defaultChunkSize)
714+
{
715+
if (!WinHttpQueryDataAvailable(pContext->m_request_handle, nullptr))
716+
{
717+
pContext->report_error(GetLastError(), _XPLATSTR("Error querying for http body data"));
718+
}
719+
}
720+
else
721+
{
722+
// If bytes read is less than the chunksize this request is done.
723+
const size_t chunkSize = pContext->m_http_client->client_config().chunksize();
724+
if (bytesRead < chunkSize && !firstRead)
725+
{
726+
pContext->complete_request(pContext->m_downloaded);
727+
}
728+
else
729+
{
730+
auto writebuf = pContext->_get_writebuffer();
731+
pContext->allocate_reply_space(writebuf.alloc(chunkSize), chunkSize);
732+
733+
if (!WinHttpReadData(
734+
pContext->m_request_handle,
735+
pContext->m_body_data.get(),
736+
static_cast<DWORD>(chunkSize),
737+
nullptr))
738+
{
739+
pContext->report_error(GetLastError(), _XPLATSTR("Error receiving http response body chunk"));
740+
}
741+
}
742+
}
743+
}
744+
707745
static void _transfer_encoding_chunked_write_data(_In_ winhttp_request_context * p_request_context)
708746
{
709747
const size_t chunk_size = p_request_context->m_http_client->client_config().chunksize();
@@ -751,7 +789,7 @@ class winhttp_client : public _http_client_communicator
751789
if (!WinHttpWriteData(
752790
p_request_context->m_request_handle,
753791
&p_request_context->m_body_data.get()[offset],
754-
(DWORD) length,
792+
static_cast<DWORD>(length),
755793
nullptr))
756794
{
757795
p_request_context->report_error(GetLastError(), _XPLATSTR("Error writing data"));
@@ -804,7 +842,7 @@ class winhttp_client : public _http_client_communicator
804842
if( !WinHttpWriteData(
805843
p_request_context->m_request_handle,
806844
p_request_context->m_body_data.get(),
807-
(DWORD)to_write,
845+
static_cast<DWORD>(to_write),
808846
nullptr))
809847
{
810848
p_request_context->report_error(GetLastError(), _XPLATSTR("Error writing data"));
@@ -846,7 +884,7 @@ class winhttp_client : public _http_client_communicator
846884
if( !WinHttpWriteData(
847885
p_request_context->m_request_handle,
848886
p_request_context->m_body_data.get(),
849-
(DWORD)read,
887+
static_cast<DWORD>(read),
850888
nullptr))
851889
{
852890
p_request_context->report_error(GetLastError(), _XPLATSTR("Error writing data"));
@@ -1072,7 +1110,7 @@ class winhttp_client : public _http_client_communicator
10721110
auto progress = p_request_context->m_request._get_impl()->_progress_handler();
10731111
if ( progress )
10741112
{
1075-
p_request_context->m_uploaded += (size64_t)bytesWritten;
1113+
p_request_context->m_uploaded += bytesWritten;
10761114
try { (*progress)(message_direction::upload, p_request_context->m_uploaded); } catch(...)
10771115
{
10781116
p_request_context->report_exception(std::current_exception());
@@ -1157,11 +1195,7 @@ class winhttp_client : public _http_client_communicator
11571195
// If none of them is specified, the message length should be determined by the server closing the connection.
11581196
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
11591197

1160-
// WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE callback determines whether this function was successful and the value of the parameters.
1161-
if(!WinHttpQueryDataAvailable(hRequestHandle, nullptr))
1162-
{
1163-
p_request_context->report_error(GetLastError(), _XPLATSTR("Error querying for http body data"));
1164-
}
1198+
read_next_response_chunk(p_request_context, 0, true);
11651199
break;
11661200
}
11671201
case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE :
@@ -1172,16 +1206,13 @@ class winhttp_client : public _http_client_communicator
11721206
if(num_bytes > 0)
11731207
{
11741208
auto writebuf = p_request_context->_get_writebuffer();
1175-
if ( !_check_streambuf(p_request_context, writebuf, _XPLATSTR("Output stream is not open")) )
1176-
break;
1177-
11781209
p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes);
11791210

11801211
// Read in body all at once.
11811212
if(!WinHttpReadData(
11821213
hRequestHandle,
1183-
(LPVOID)p_request_context->m_body_data.get(),
1184-
(DWORD)num_bytes,
1214+
p_request_context->m_body_data.get(),
1215+
num_bytes,
11851216
nullptr))
11861217
{
11871218
p_request_context->report_error(GetLastError(), _XPLATSTR("Error receiving http body chunk"));
@@ -1201,75 +1232,65 @@ class winhttp_client : public _http_client_communicator
12011232
}
12021233
}
12031234

1204-
p_request_context->complete_request((size_t)p_request_context->m_downloaded);
1235+
p_request_context->complete_request(p_request_context->m_downloaded);
12051236
}
12061237
break;
12071238
}
12081239
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE :
12091240
{
12101241
// Status information length contains the number of bytes read.
1211-
// WinHTTP will always fill the whole buffer or read nothing.
1212-
// If number of bytes read is zero than we have reached the end.
1242+
const DWORD bytesRead = statusInfoLength;
12131243

1214-
if(statusInfoLength > 0)
1244+
// Report progress about downloaded bytes.
1245+
auto progress = p_request_context->m_request._get_impl()->_progress_handler();
1246+
p_request_context->m_downloaded += statusInfoLength;
1247+
if (progress)
12151248
{
1216-
auto progress = p_request_context->m_request._get_impl()->_progress_handler();
1217-
p_request_context->m_downloaded += (size64_t)statusInfoLength;
1218-
if ( progress )
1249+
try { (*progress)(message_direction::download, p_request_context->m_downloaded); }
1250+
catch (...)
12191251
{
1220-
try { (*progress)(message_direction::download, p_request_context->m_downloaded); } catch(...)
1252+
p_request_context->report_exception(std::current_exception());
1253+
return;
1254+
}
1255+
}
1256+
1257+
// If no bytes have been read, then this is the end of the response.
1258+
if (bytesRead == 0)
1259+
{
1260+
p_request_context->complete_request(p_request_context->m_downloaded);
1261+
break;
1262+
}
1263+
1264+
// If the data was allocated directly from the buffer then commit, otherwise we still
1265+
// need to write to the response stream buffer.
1266+
auto writebuf = p_request_context->_get_writebuffer();
1267+
if (p_request_context->is_externally_allocated())
1268+
{
1269+
writebuf.commit(bytesRead);
1270+
read_next_response_chunk(p_request_context, bytesRead);
1271+
}
1272+
else
1273+
{
1274+
writebuf.putn(p_request_context->m_body_data.get(), bytesRead).then(
1275+
[hRequestHandle, p_request_context, bytesRead] (pplx::task<size_t> op)
1276+
{
1277+
size_t written = 0;
1278+
try { written = op.get(); }
1279+
catch (...)
12211280
{
12221281
p_request_context->report_exception(std::current_exception());
12231282
return;
12241283
}
1225-
}
1226-
1227-
auto writebuf = p_request_context->_get_writebuffer();
1228-
1229-
if ( p_request_context->is_externally_allocated() )
1230-
{
1231-
writebuf.commit(statusInfoLength);
12321284

1233-
// Look for more data
1234-
if (!WinHttpQueryDataAvailable(hRequestHandle, nullptr))
1285+
// If we couldn't write everything, it's time to exit.
1286+
if (written != bytesRead)
12351287
{
1236-
p_request_context->report_error(GetLastError(), _XPLATSTR("Error querying for http body chunk"));
1288+
p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes"));
12371289
return;
12381290
}
1239-
}
1240-
else
1241-
{
1242-
writebuf.putn(p_request_context->m_body_data.get(), statusInfoLength).then(
1243-
[hRequestHandle, p_request_context, statusInfoLength]
1244-
(pplx::task<size_t> op)
1245-
{
1246-
size_t written = 0;
1247-
try { written = op.get(); } catch(...)
1248-
{
1249-
p_request_context->report_exception(std::current_exception());
1250-
return;
1251-
}
1252-
1253-
// If we couldn't write everything, it's time to exit.
1254-
if ( written != statusInfoLength )
1255-
{
1256-
p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes"));
1257-
return;
1258-
}
1259-
1260-
// Look for more data
1261-
if (!WinHttpQueryDataAvailable(hRequestHandle, nullptr))
1262-
{
1263-
p_request_context->report_error(GetLastError(), _XPLATSTR("Error querying for http body chunk"));
1264-
return;
1265-
}
1266-
});
1267-
}
1268-
}
1269-
else
1270-
{
1271-
// Done reading so set task completion event and close the request handle.
1272-
p_request_context->complete_request((size_t)p_request_context->m_downloaded);
1291+
1292+
read_next_response_chunk(p_request_context, bytesRead);
1293+
});
12731294
}
12741295
break;
12751296
}

Release/src/http/client/http_win8.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class HttpRequestCallback :
124124
if (m_request->m_exceptionPtr != nullptr)
125125
m_request->report_exception(m_request->m_exceptionPtr);
126126
else
127-
m_request->complete_request((size_t)m_request->m_downloaded);
127+
m_request->complete_request(m_request->m_downloaded);
128128

129129
// Break the circular reference loop.
130130
// - winrt_request_context holds a reference to IXmlHttpRequest2

Release/src/json/json_parsing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*
1919
* json_parsing.cpp
2020
*
21-
* HTTP Library: JSON parser and writer
21+
* HTTP Library: JSON parser
2222
*
2323
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
2424
*

Release/src/pplx/linux/pplxlinux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace details {
4343
{
4444
_PPLXIMP long GetCurrentThreadId()
4545
{
46-
return static_cast<long>(pthread_self());
46+
return reinterpret_cast<long>(reinterpret_cast<void*>(pthread_self()));
4747
}
4848

4949
_PPLXIMP void YieldExecution()

Release/src/uri/uri_builder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ uri_builder &uri_builder::append_query(const utility::string_t &query, bool is_e
8080
return *this;
8181
}
8282

83-
auto encoded_query = is_encode ? uri::encode_uri(query, uri::components::path) : query;
83+
auto encoded_query = is_encode ? uri::encode_uri(query, uri::components::query) : query;
8484
auto thisQuery = this->query();
8585
if (thisQuery.empty())
8686
{

0 commit comments

Comments
 (0)