Skip to content

Commit 0387cb9

Browse files
authored
Merge pull request #1051 from garethsb-sony/garethsb-http-ssl_context_callback
Fix http_client_asio "https" with a proxy
2 parents a917bd4 + 6225905 commit 0387cb9

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

Release/include/cpprest/http_msg.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,28 @@ class http_exception : public std::exception
248248
m_msg = m_errorCode.message();
249249
}
250250

251+
/// <summary>
252+
/// Creates an <c>http_exception</c> with from a error code with a category, and a string message.
253+
/// </summary>
254+
/// <param name="errorCode">Error code value.</param>
255+
/// <param name="whatArg">Error message string.</param>
256+
http_exception(std::error_code errorCode, const utility::string_t& whatArg)
257+
: m_errorCode(std::move(errorCode)), m_msg(utility::conversions::to_utf8string(whatArg))
258+
{
259+
}
260+
261+
#ifdef _WIN32
262+
/// <summary>
263+
/// Creates an <c>http_exception</c> with from a error code with a category, and a string message.
264+
/// </summary>
265+
/// <param name="errorCode">Error code value.</param>
266+
/// <param name="whatArg">Error message string.</param>
267+
http_exception(std::error_code errorCode, std::string whatArg)
268+
: m_errorCode(std::move(errorCode)), m_msg(std::move(whatArg))
269+
{
270+
}
271+
#endif
272+
251273
/// <summary>
252274
/// Gets a string identifying the cause of the exception.
253275
/// </summary>

Release/src/http/client/http_client_asio.cpp

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,11 @@ namespace
8787
{
8888
const std::string CRLF("\r\n");
8989

90-
std::string calc_cn_host(const bool secure,
91-
const web::http::uri& baseUri,
90+
std::string calc_cn_host(const web::http::uri& baseUri,
9291
const web::http::http_headers& requestHeaders)
9392
{
9493
std::string result;
95-
if (secure)
94+
if (baseUri.scheme() == U("https"))
9695
{
9796
const utility::string_t* encResult;
9897
const auto hostHeader = requestHeaders.find(_XPLATSTR("Host"));
@@ -472,7 +471,6 @@ class asio_client final : public _http_client_communicator
472471
: _http_client_communicator(std::move(address), std::move(client_config))
473472
, m_resolver(crossplat::threadpool::shared_instance().service())
474473
, m_pool(std::make_shared<asio_connection_pool>())
475-
, m_start_with_ssl(base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified())
476474
{
477475
}
478476

@@ -482,13 +480,13 @@ class asio_client final : public _http_client_communicator
482480

483481
std::shared_ptr<asio_connection> obtain_connection(const http_request& req)
484482
{
485-
std::string cn_host = calc_cn_host(m_start_with_ssl, base_uri(), req.headers());
483+
std::string cn_host = calc_cn_host(base_uri(), req.headers());
486484
std::shared_ptr<asio_connection> conn = m_pool->try_acquire(cn_host);
487485
if (conn == nullptr)
488486
{
489487
// Pool was empty. Create a new connection
490488
conn = std::make_shared<asio_connection>(crossplat::threadpool::shared_instance().service());
491-
if (m_start_with_ssl)
489+
if (base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified())
492490
{
493491
conn->upgrade_to_ssl(std::move(cn_host), this->client_config().get_ssl_context_callback());
494492
}
@@ -499,13 +497,10 @@ class asio_client final : public _http_client_communicator
499497

500498
virtual pplx::task<http_response> propagate(http_request request) override;
501499

502-
bool start_with_ssl() const CPPREST_NOEXCEPT { return m_start_with_ssl; }
503-
504500
tcp::resolver m_resolver;
505501

506502
private:
507503
const std::shared_ptr<asio_connection_pool> m_pool;
508-
const bool m_start_with_ssl;
509504
};
510505

511506
class asio_context final : public request_context, public std::enable_shared_from_this<asio_context>
@@ -631,7 +626,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
631626
m_context->m_timer.reset();
632627
//// Replace the connection. This causes old connection object to go out of scope.
633628
auto client = std::static_pointer_cast<asio_client>(m_context->m_http_client);
634-
m_context->m_connection = client->obtain_connection(m_context->m_request);
629+
try
630+
{
631+
m_context->m_connection = client->obtain_connection(m_context->m_request);
632+
}
633+
catch (...)
634+
{
635+
m_context->report_exception(std::current_exception());
636+
return;
637+
}
635638

636639
auto endpoint = *endpoints;
637640
m_context->m_connection->async_connect(endpoint,
@@ -688,7 +691,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
688691
return;
689692
}
690693

691-
m_context->upgrade_to_ssl();
694+
try
695+
{
696+
m_context->upgrade_to_ssl();
697+
}
698+
catch (...)
699+
{
700+
m_context->report_exception(std::current_exception());
701+
return;
702+
}
692703

693704
m_ssl_tunnel_established(m_context);
694705
}
@@ -925,7 +936,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
925936
void upgrade_to_ssl()
926937
{
927938
auto& client = static_cast<asio_client&>(*m_http_client);
928-
m_connection->upgrade_to_ssl(calc_cn_host(client.start_with_ssl(), client.base_uri(), m_request.headers()),
939+
m_connection->upgrade_to_ssl(calc_cn_host(client.base_uri(), m_request.headers()),
929940
client.client_config().get_ssl_context_callback());
930941
}
931942

@@ -1009,7 +1020,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
10091020
{
10101021
// Replace the connection. This causes old connection object to go out of scope.
10111022
auto client = std::static_pointer_cast<asio_client>(m_http_client);
1012-
m_connection = client->obtain_connection(m_request);
1023+
try
1024+
{
1025+
m_connection = client->obtain_connection(m_request);
1026+
}
1027+
catch (...)
1028+
{
1029+
request_context::report_exception(std::current_exception());
1030+
return;
1031+
}
10131032

10141033
auto endpoint = *endpoints;
10151034
m_connection->async_connect(
@@ -1330,7 +1349,16 @@ class asio_context final : public request_context, public std::enable_shared_fro
13301349
// Create a new context and copy the request object, completion event and
13311350
// cancellation registration to maintain the old state.
13321351
// This also obtains a new connection from pool.
1333-
auto new_ctx = create_request_context(m_http_client, m_request);
1352+
std::shared_ptr<request_context> new_ctx;
1353+
try
1354+
{
1355+
new_ctx = create_request_context(m_http_client, m_request);
1356+
}
1357+
catch (...)
1358+
{
1359+
report_exception(std::current_exception());
1360+
return;
1361+
}
13341362

13351363
// If the request contains a valid instream, we try to rewind it to
13361364
// replay the just-failed request. Otherwise we assume that no data
@@ -1940,7 +1968,15 @@ void asio_client::send_request(const std::shared_ptr<request_context>& request_c
19401968
pplx::task<http_response> asio_client::propagate(http_request request)
19411969
{
19421970
auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this());
1943-
auto context = details::asio_context::create_request_context(self, request);
1971+
std::shared_ptr<request_context> context;
1972+
try
1973+
{
1974+
context = details::asio_context::create_request_context(self, request);
1975+
}
1976+
catch (...)
1977+
{
1978+
return pplx::task_from_exception<http_response>(std::current_exception());
1979+
}
19441980

19451981
// Use a task to externally signal the final result and completion of the task.
19461982
auto result_task = pplx::create_task(context->m_request_completion);

0 commit comments

Comments
 (0)