diff --git a/src/oatpp/web/client/HttpRequestExecutor.cpp b/src/oatpp/web/client/HttpRequestExecutor.cpp index 446a5028..810eb9d5 100644 --- a/src/oatpp/web/client/HttpRequestExecutor.cpp +++ b/src/oatpp/web/client/HttpRequestExecutor.cpp @@ -36,6 +36,42 @@ namespace oatpp { namespace web { namespace client { +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HttpRequestExecutor::HttpConnectionHandle + +HttpRequestExecutor::HttpConnectionHandle::HttpConnectionHandle(const std::shared_ptr& connectionProvider, + const std::shared_ptr& stream) + : m_connectionProvider(connectionProvider) + , m_connection(stream) + , m_valid(true) + , m_invalidateOnDestroy(false) +{} + +HttpRequestExecutor::HttpConnectionHandle::~HttpConnectionHandle() { + if(m_invalidateOnDestroy) { + invalidate(); + } +} + + +std::shared_ptr HttpRequestExecutor::HttpConnectionHandle::getConnection() { + return m_connection; +} + +void HttpRequestExecutor::HttpConnectionHandle::invalidate() { + if(m_valid) { + m_connectionProvider->invalidate(m_connection); + m_valid = false; + } +} + +void HttpRequestExecutor::HttpConnectionHandle::setInvalidateOnDestroy(bool invalidateOnDestroy) { + m_invalidateOnDestroy = invalidateOnDestroy; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HttpRequestExecutor + HttpRequestExecutor::HttpRequestExecutor(const std::shared_ptr& connectionProvider, const std::shared_ptr& retryPolicy, const std::shared_ptr& bodyDecoder) @@ -58,7 +94,7 @@ std::shared_ptr HttpRequestExecutor::getC throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_CONNECT, "[oatpp::web::client::HttpRequestExecutor::getConnection()]: ConnectionProvider failed to provide Connection"); } - return std::make_shared(connection); + return std::make_shared(m_connectionProvider, connection); } oatpp::async::CoroutineStarterForResult&> @@ -78,7 +114,7 @@ HttpRequestExecutor::getConnectionAsync() { } Action onConnectionReady(const std::shared_ptr& connection) { - return _return(std::make_shared(connection)); + return _return(std::make_shared(m_connectionProvider, connection)); } }; @@ -90,8 +126,8 @@ HttpRequestExecutor::getConnectionAsync() { void HttpRequestExecutor::invalidateConnection(const std::shared_ptr& connectionHandle) { if(connectionHandle) { - auto connection = static_cast(connectionHandle.get())->connection; - m_connectionProvider->invalidate(connection); + auto handle = static_cast(connectionHandle.get()); + handle->invalidate(); } } @@ -104,8 +140,9 @@ HttpRequestExecutor::executeOnce(const String& method, const std::shared_ptr& connectionHandle) { std::shared_ptr connection; - if(connectionHandle) { - connection = static_cast(connectionHandle.get())->connection; + std::shared_ptr httpCH = std::static_pointer_cast(connectionHandle); + if(httpCH) { + connection = httpCH->getConnection(); } if(!connection){ @@ -131,21 +168,20 @@ HttpRequestExecutor::executeOnce(const String& method, const auto& result = headerReader.readHeaders(connection, error); if(error.status.code != 0) { - invalidateConnection(connectionHandle); + httpCH->invalidate(); throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_PARSE_STARTING_LINE, "[oatpp::web::client::HttpRequestExecutor::executeOnce()]: Failed to parse response. Invalid response headers"); } if(error.ioStatus < 0) { - invalidateConnection(connectionHandle); + httpCH->invalidate(); throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_PARSE_STARTING_LINE, "[oatpp::web::client::HttpRequestExecutor::executeOnce()]: Failed to read response."); } - auto con_hdr = result.headers.getAsMemoryLabel("Connection"); - if (con_hdr == "close") - { - invalidateConnection(connectionHandle); + auto connectionHeader = result.headers.getAsMemoryLabel(Header::CONNECTION); + if (connectionHeader == "close") { + httpCH->setInvalidateOnDestroy(true); } auto bodyStream = oatpp::data::stream::InputStreamBufferedProxy::createShared(connection, @@ -179,7 +215,7 @@ HttpRequestExecutor::executeOnceAsync(const String& method, Headers m_headers; std::shared_ptr m_body; std::shared_ptr m_bodyDecoder; - std::shared_ptr m_connectionHandle; + std::shared_ptr m_connectionHandle; oatpp::data::share::MemoryLabel m_buffer; ResponseHeadersReader m_headersReader; std::shared_ptr m_upstream; @@ -193,7 +229,7 @@ HttpRequestExecutor::executeOnceAsync(const String& method, const Headers& headers, const std::shared_ptr& body, const std::shared_ptr& bodyDecoder, - const std::shared_ptr& connectionHandle) + const std::shared_ptr& connectionHandle) : m_this(_this) , m_method(method) , m_path(path) @@ -208,7 +244,7 @@ HttpRequestExecutor::executeOnceAsync(const String& method, Action act() override { if(m_connectionHandle) { - m_connection = static_cast(m_connectionHandle.get())->connection; + m_connection = m_connectionHandle->getConnection(); } if(!m_connection) { @@ -232,7 +268,12 @@ HttpRequestExecutor::executeOnceAsync(const String& method, } Action onHeadersParsed(const ResponseHeadersReader::Result& result) { - + + auto connectionHeader = result.headers.getAsMemoryLabel(Header::CONNECTION); + if (connectionHeader == "close") { + m_connectionHandle->setInvalidateOnDestroy(true); + } + auto bodyStream = oatpp::data::stream::InputStreamBufferedProxy::createShared(m_connection, m_buffer, result.bufferPosStart, @@ -248,7 +289,7 @@ HttpRequestExecutor::executeOnceAsync(const String& method, Action handleError(oatpp::async::Error* error) override { if(m_connectionHandle) { - m_this->invalidateConnection(m_connectionHandle); + m_connectionHandle->invalidate(); } return error; @@ -256,8 +297,9 @@ HttpRequestExecutor::executeOnceAsync(const String& method, } }; - - return ExecutorCoroutine::startForResult(this, method, path, headers, body, m_bodyDecoder, connectionHandle); + + auto httpCH = std::static_pointer_cast(connectionHandle); + return ExecutorCoroutine::startForResult(this, method, path, headers, body, m_bodyDecoder, httpCH); } diff --git a/src/oatpp/web/client/HttpRequestExecutor.hpp b/src/oatpp/web/client/HttpRequestExecutor.hpp index aed2520c..69172ad7 100644 --- a/src/oatpp/web/client/HttpRequestExecutor.hpp +++ b/src/oatpp/web/client/HttpRequestExecutor.hpp @@ -51,20 +51,44 @@ public: * For more details see &id:oatpp::web::client::RequestExecutor::ConnectionHandle;. */ class HttpConnectionHandle : public ConnectionHandle { + private: + /* provider which created this connection */ + std::shared_ptr m_connectionProvider; + std::shared_ptr m_connection; + bool m_valid; + bool m_invalidateOnDestroy; public: /** * Constructor. + * @param connectionProvider - connection provider which created this connection. * @param stream - &id:oatpp::data::stream::IOStream;. */ - HttpConnectionHandle(const std::shared_ptr& stream) - : connection(stream) - {} + HttpConnectionHandle(const std::shared_ptr& connectionProvider, + const std::shared_ptr& stream); /** - * Connection. + * Destructor. */ - std::shared_ptr connection; + ~HttpConnectionHandle() override; + + /** + * Get connection I/O stream. + * @return + */ + std::shared_ptr getConnection(); + + /** + * Invalidate this connection. + */ + void invalidate(); + + /** + * Set if connection should be invalidated on destroy of ConnectionHandle. + * @param invalidateOnDestroy + */ + void setInvalidateOnDestroy(bool invalidateOnDestroy); + }; public: