From 886855b08c6307e01fa2f69a1dd750c450461bee Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Wed, 27 Feb 2019 17:33:38 +0000 Subject: [PATCH 1/3] Add exception handling for the ssl_context_callback so it has a means to report errors --- Release/src/http/client/http_client_asio.cpp | 51 ++++++++++++++++++-- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 3a5f82800c..b1e036447d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -631,7 +631,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 +696,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); } @@ -1009,7 +1025,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 +1354,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 +1973,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); From bc77da398257e1a1d42c56828a60de0e59da2bba Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Wed, 27 Feb 2019 17:36:59 +0000 Subject: [PATCH 2/3] Fix upgrade to SSL after a proxy connect (hostname is required) --- Release/src/http/client/http_client_asio.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index b1e036447d..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 @@ -941,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()); } From 43773b9858f0672a4d5856a48f79d97193b295d9 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 5 Mar 2019 08:59:54 +0000 Subject: [PATCH 3/3] Add the obvious missing constructor from a std::error_code and 'what' string message; cf. websocket_exception --- Release/include/cpprest/http_msg.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) 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. ///