diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h
index a2477fd34d..50f05ef213 100644
--- a/Release/include/cpprest/http_msg.h
+++ b/Release/include/cpprest/http_msg.h
@@ -248,6 +248,28 @@ class http_exception : public std::exception
m_msg = m_errorCode.message();
}
+ ///
+ /// Creates an http_exception with from a error code with a category, and a string message.
+ ///
+ /// Error code value.
+ /// Error message string.
+ http_exception(std::error_code errorCode, const utility::string_t& whatArg)
+ : m_errorCode(std::move(errorCode)), m_msg(utility::conversions::to_utf8string(whatArg))
+ {
+ }
+
+#ifdef _WIN32
+ ///
+ /// Creates an http_exception with from a error code with a category, and a string message.
+ ///
+ /// Error code value.
+ /// Error message string.
+ http_exception(std::error_code errorCode, std::string whatArg)
+ : m_errorCode(std::move(errorCode)), m_msg(std::move(whatArg))
+ {
+ }
+#endif
+
///
/// Gets a string identifying the cause of the exception.
///
diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp
index 3a5f82800c..1df332d617 100644
--- a/Release/src/http/client/http_client_asio.cpp
+++ b/Release/src/http/client/http_client_asio.cpp
@@ -87,12 +87,11 @@ namespace
{
const std::string CRLF("\r\n");
-std::string calc_cn_host(const bool secure,
- const web::http::uri& baseUri,
+std::string calc_cn_host(const web::http::uri& baseUri,
const web::http::http_headers& requestHeaders)
{
std::string result;
- if (secure)
+ if (baseUri.scheme() == U("https"))
{
const utility::string_t* encResult;
const auto hostHeader = requestHeaders.find(_XPLATSTR("Host"));
@@ -472,7 +471,6 @@ class asio_client final : public _http_client_communicator
: _http_client_communicator(std::move(address), std::move(client_config))
, m_resolver(crossplat::threadpool::shared_instance().service())
, m_pool(std::make_shared())
- , m_start_with_ssl(base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified())
{
}
@@ -482,13 +480,13 @@ class asio_client final : public _http_client_communicator
std::shared_ptr obtain_connection(const http_request& req)
{
- std::string cn_host = calc_cn_host(m_start_with_ssl, base_uri(), req.headers());
+ std::string cn_host = calc_cn_host(base_uri(), req.headers());
std::shared_ptr conn = m_pool->try_acquire(cn_host);
if (conn == nullptr)
{
// Pool was empty. Create a new connection
conn = std::make_shared(crossplat::threadpool::shared_instance().service());
- if (m_start_with_ssl)
+ if (base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified())
{
conn->upgrade_to_ssl(std::move(cn_host), this->client_config().get_ssl_context_callback());
}
@@ -499,13 +497,10 @@ class asio_client final : public _http_client_communicator
virtual pplx::task propagate(http_request request) override;
- bool start_with_ssl() const CPPREST_NOEXCEPT { return m_start_with_ssl; }
-
tcp::resolver m_resolver;
private:
const std::shared_ptr m_pool;
- const bool m_start_with_ssl;
};
class asio_context final : public request_context, public std::enable_shared_from_this
@@ -631,7 +626,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
m_context->m_timer.reset();
//// Replace the connection. This causes old connection object to go out of scope.
auto client = std::static_pointer_cast(m_context->m_http_client);
- m_context->m_connection = client->obtain_connection(m_context->m_request);
+ try
+ {
+ m_context->m_connection = client->obtain_connection(m_context->m_request);
+ }
+ catch (...)
+ {
+ m_context->report_exception(std::current_exception());
+ return;
+ }
auto endpoint = *endpoints;
m_context->m_connection->async_connect(endpoint,
@@ -688,7 +691,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
return;
}
- m_context->upgrade_to_ssl();
+ try
+ {
+ m_context->upgrade_to_ssl();
+ }
+ catch (...)
+ {
+ m_context->report_exception(std::current_exception());
+ return;
+ }
m_ssl_tunnel_established(m_context);
}
@@ -925,7 +936,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
void upgrade_to_ssl()
{
auto& client = static_cast(*m_http_client);
- m_connection->upgrade_to_ssl(calc_cn_host(client.start_with_ssl(), client.base_uri(), m_request.headers()),
+ m_connection->upgrade_to_ssl(calc_cn_host(client.base_uri(), m_request.headers()),
client.client_config().get_ssl_context_callback());
}
@@ -1009,7 +1020,15 @@ class asio_context final : public request_context, public std::enable_shared_fro
{
// Replace the connection. This causes old connection object to go out of scope.
auto client = std::static_pointer_cast(m_http_client);
- m_connection = client->obtain_connection(m_request);
+ try
+ {
+ m_connection = client->obtain_connection(m_request);
+ }
+ catch (...)
+ {
+ request_context::report_exception(std::current_exception());
+ return;
+ }
auto endpoint = *endpoints;
m_connection->async_connect(
@@ -1330,7 +1349,16 @@ class asio_context final : public request_context, public std::enable_shared_fro
// Create a new context and copy the request object, completion event and
// cancellation registration to maintain the old state.
// This also obtains a new connection from pool.
- auto new_ctx = create_request_context(m_http_client, m_request);
+ std::shared_ptr new_ctx;
+ try
+ {
+ new_ctx = create_request_context(m_http_client, m_request);
+ }
+ catch (...)
+ {
+ report_exception(std::current_exception());
+ return;
+ }
// If the request contains a valid instream, we try to rewind it to
// 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_c
pplx::task asio_client::propagate(http_request request)
{
auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this());
- auto context = details::asio_context::create_request_context(self, request);
+ std::shared_ptr context;
+ try
+ {
+ context = details::asio_context::create_request_context(self, request);
+ }
+ catch (...)
+ {
+ return pplx::task_from_exception(std::current_exception());
+ }
// Use a task to externally signal the final result and completion of the task.
auto result_task = pplx::create_task(context->m_request_completion);