Skip to content

Commit

Permalink
Merge pull request #1051 from garethsb-sony/garethsb-http-ssl_context…
Browse files Browse the repository at this point in the history
…_callback

Fix http_client_asio "https" with a proxy
  • Loading branch information
BillyONeal authored Mar 20, 2019
2 parents a917bd4 + 6225905 commit 0387cb9
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 15 deletions.
22 changes: 22 additions & 0 deletions Release/include/cpprest/http_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,28 @@ class http_exception : public std::exception
m_msg = m_errorCode.message();
}

/// <summary>
/// Creates an <c>http_exception</c> with from a error code with a category, and a string message.
/// </summary>
/// <param name="errorCode">Error code value.</param>
/// <param name="whatArg">Error message string.</param>
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
/// <summary>
/// Creates an <c>http_exception</c> with from a error code with a category, and a string message.
/// </summary>
/// <param name="errorCode">Error code value.</param>
/// <param name="whatArg">Error message string.</param>
http_exception(std::error_code errorCode, std::string whatArg)
: m_errorCode(std::move(errorCode)), m_msg(std::move(whatArg))
{
}
#endif

/// <summary>
/// Gets a string identifying the cause of the exception.
/// </summary>
Expand Down
66 changes: 51 additions & 15 deletions Release/src/http/client/http_client_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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<asio_connection_pool>())
, m_start_with_ssl(base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified())
{
}

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

std::shared_ptr<asio_connection> 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<asio_connection> conn = m_pool->try_acquire(cn_host);
if (conn == nullptr)
{
// Pool was empty. Create a new connection
conn = std::make_shared<asio_connection>(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());
}
Expand All @@ -499,13 +497,10 @@ class asio_client final : public _http_client_communicator

virtual pplx::task<http_response> 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<asio_connection_pool> m_pool;
const bool m_start_with_ssl;
};

class asio_context final : public request_context, public std::enable_shared_from_this<asio_context>
Expand Down Expand Up @@ -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<asio_client>(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,
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -925,7 +936,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
void upgrade_to_ssl()
{
auto& client = static_cast<asio_client&>(*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());
}

Expand Down Expand Up @@ -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<asio_client>(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(
Expand Down Expand Up @@ -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<request_context> 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
Expand Down Expand Up @@ -1940,7 +1968,15 @@ void asio_client::send_request(const std::shared_ptr<request_context>& request_c
pplx::task<http_response> 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<request_context> context;
try
{
context = details::asio_context::create_request_context(self, request);
}
catch (...)
{
return pplx::task_from_exception<http_response>(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);
Expand Down

0 comments on commit 0387cb9

Please sign in to comment.