From 05f9b1c4be056e6fbca84e8cb4509996123fbfc9 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Mon, 28 Jan 2019 16:38:19 +0000 Subject: [PATCH] Fix HTTP/1.0 'Keep-Alive' handling in http_client --- Release/include/cpprest/http_msg.h | 11 +++++------ Release/src/http/client/http_client_asio.cpp | 20 ++++++++++++++++---- Release/src/http/common/http_msg.cpp | 8 +++++--- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 41b495c712..a2477fd34d 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -281,6 +281,8 @@ class http_msg_base virtual ~http_msg_base() {} + http::http_version http_version() const { return m_http_version; } + http_headers& headers() { return m_headers; } _ASYNCRTIMP void set_body(const concurrency::streams::istream& instream, const utf8string& contentType); @@ -419,6 +421,8 @@ class http_msg_base /// _ASYNCRTIMP size_t _get_content_length_and_set_compression(); + void _set_http_version(const http::http_version& http_version) { m_http_version = http_version; } + protected: std::unique_ptr m_compressor; std::unique_ptr m_decompressor; @@ -444,6 +448,7 @@ class http_msg_base /// concurrency::streams::ostream m_outStream; + http::http_version m_http_version; http_headers m_headers; bool m_default_outstream; @@ -838,8 +843,6 @@ class _http_request final : public http::details::http_msg_base, public std::ena _ASYNCRTIMP void set_request_uri(const uri&); - http::http_version http_version() const { return m_http_version; } - const utility::string_t& remote_address() const { return m_remote_address; } const pplx::cancellation_token& cancellation_token() const { return m_cancellationToken; } @@ -876,8 +879,6 @@ class _http_request final : public http::details::http_msg_base, public std::ena void _set_base_uri(const http::uri& base_uri) { m_base_uri = base_uri; } - void _set_http_version(const http::http_version& http_version) { m_http_version = http_version; } - void _set_remote_address(const utility::string_t& remote_address) { m_remote_address = remote_address; } private: @@ -906,8 +907,6 @@ class _http_request final : public http::details::http_msg_base, public std::ena pplx::task_completion_event m_response; - http::http_version m_http_version; - utility::string_t m_remote_address; }; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ec4edd6995..3a5f82800c 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1301,6 +1301,15 @@ class asio_context final : public request_context, public std::enable_shared_fro return; } + web::http::http_version parsed_version = web::http::http_version::from_string(http_version); + m_response._get_impl()->_set_http_version(parsed_version); + + // if HTTP version is 1.0 then disable 'Keep-Alive' by default + if (parsed_version == web::http::http_versions::HTTP_1_0) + { + m_connection->set_keep_alive(false); + } + read_headers(); } else @@ -1391,11 +1400,14 @@ class asio_context final : public request_context, public std::enable_shared_fro if (boost::iequals(name, header_names::connection)) { - // This assumes server uses HTTP/1.1 so that 'Keep-Alive' is the default, + // If the server uses HTTP/1.1, then 'Keep-Alive' is the default, // so connection is explicitly closed only if we get "Connection: close". - // We don't handle HTTP/1.0 server here. HTTP/1.0 server would need - // to respond using 'Connection: Keep-Alive' every time. - m_connection->set_keep_alive(!boost::iequals(value, U("close"))); + // If the server uses HTTP/1.0, it would need to respond using + // 'Connection: Keep-Alive' every time. + if (m_response._get_impl()->http_version() != web::http::http_versions::HTTP_1_0) + m_connection->set_keep_alive(!boost::iequals(value, U("close"))); + else + m_connection->set_keep_alive(boost::iequals(value, U("Keep-Alive"))); } m_response.headers().add(utility::conversions::to_string_t(std::move(name)), diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index acc84fa54f..50ab8ed82c 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -287,7 +287,11 @@ static const utility::char_t* stream_was_set_explicitly = static const utility::char_t* unsupported_charset = _XPLATSTR("Charset must be iso-8859-1, utf-8, utf-16, utf-16le, or utf-16be to be extracted."); -http_msg_base::http_msg_base() : m_headers(), m_default_outstream(false) {} +http_msg_base::http_msg_base() + : m_http_version(http::http_version{ 0, 0 }) + , m_headers() + , m_default_outstream(false) +{} void http_msg_base::_prepare_to_receive_data() { @@ -1122,7 +1126,6 @@ details::_http_request::_http_request(http::method mtd) , m_initiated_response(0) , m_server_context() , m_cancellationToken(pplx::cancellation_token::none()) - , m_http_version(http::http_version {0, 0}) { if (m_method.empty()) { @@ -1134,7 +1137,6 @@ details::_http_request::_http_request(std::unique_ptr