From 08d04232666ff2ae4700c3fca0c0283e73260e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Tue, 15 Jan 2019 16:29:42 +0100 Subject: [PATCH 1/5] FIX: check whether instream() is valid before trying to rewind --- Release/src/http/client/http_client_asio.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 3292447061..1eeabd5102 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1322,7 +1322,24 @@ class asio_context final : public request_context, public std::enable_shared_fro // 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); - new_ctx->m_request._get_impl()->instream().seek(0); + + // If the request contains a valid instream, we try to rewind it to + // replay the just-failed request. Otherwise we assume that no data + // was sent in the first place. + const auto& instream = new_ctx->m_request._get_impl()->instream(); + if (instream) { + try { + // As stated in the commit message of f4f2348, we might + // encounter streams that are not capable of rewinding. In + // case there is an exception we report it to the user and + // give up. + instream.seek(0); + } catch (const std::exception &ex) { + report_error(std::string("failed to rewind input stream: ") + ex.what(), + ec, httpclient_errorcode_context::readheader); + } + } + new_ctx->m_request_completion = m_request_completion; new_ctx->m_cancellationRegistration = m_cancellationRegistration; From 67d3ab43e56c8791d7f67622ce7d81dbc765522e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Tue, 15 Jan 2019 17:39:11 +0100 Subject: [PATCH 2/5] add .can_seek() as a second line of defense --- Release/src/http/client/http_client_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 1eeabd5102..160f325871 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1327,7 +1327,7 @@ class asio_context final : public request_context, public std::enable_shared_fro // replay the just-failed request. Otherwise we assume that no data // was sent in the first place. const auto& instream = new_ctx->m_request._get_impl()->instream(); - if (instream) { + if (instream && instream.can_seek()) { try { // As stated in the commit message of f4f2348, we might // encounter streams that are not capable of rewinding. In From ffc06a31b3f69321b6709e6c4444349c1e7cf921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Tue, 15 Jan 2019 17:41:26 +0100 Subject: [PATCH 3/5] apply clang-format --- Release/src/http/client/http_client_asio.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 160f325871..0259efe28c 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1327,16 +1327,21 @@ class asio_context final : public request_context, public std::enable_shared_fro // replay the just-failed request. Otherwise we assume that no data // was sent in the first place. const auto& instream = new_ctx->m_request._get_impl()->instream(); - if (instream && instream.can_seek()) { - try { + if (instream && instream.can_seek()) + { + try + { // As stated in the commit message of f4f2348, we might // encounter streams that are not capable of rewinding. In // case there is an exception we report it to the user and // give up. instream.seek(0); - } catch (const std::exception &ex) { + } + catch (const std::exception& ex) + { report_error(std::string("failed to rewind input stream: ") + ex.what(), - ec, httpclient_errorcode_context::readheader); + ec, + httpclient_errorcode_context::readheader); } } From 223cffa6e94fe9a2b5d57bd05c3131ab8b42a946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Wed, 16 Jan 2019 09:12:35 +0100 Subject: [PATCH 4/5] improve error reporting for unrewindable streams --- Release/src/http/client/http_client_asio.cpp | 28 +++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 0259efe28c..ec4edd6995 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1327,21 +1327,31 @@ class asio_context final : public request_context, public std::enable_shared_fro // replay the just-failed request. Otherwise we assume that no data // was sent in the first place. const auto& instream = new_ctx->m_request._get_impl()->instream(); - if (instream && instream.can_seek()) + if (instream) { + // As stated in the commit message of f4f2348, we might encounter + // streams that are not capable of rewinding and hence resending the + // request is not possible. We cannot recover from this condition and + // need to escalate it to the using code. + if (!instream.can_seek()) + { + report_error("cannot rewind input stream for connection re-establishment", + ec, + httpclient_errorcode_context::readheader); + return; + } + try { - // As stated in the commit message of f4f2348, we might - // encounter streams that are not capable of rewinding. In - // case there is an exception we report it to the user and - // give up. + // Rewinding the stream might throw, in which case we cannot do the + // connection re-establishment transparently. I.e. report the exception + // to the calling code. instream.seek(0); } - catch (const std::exception& ex) + catch (...) { - report_error(std::string("failed to rewind input stream: ") + ex.what(), - ec, - httpclient_errorcode_context::readheader); + report_exception(std::current_exception()); + return; } } From b4aa08c4f0d6ee74b332a2a94d8be641595f472f Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 16 Jan 2019 12:09:27 -0800 Subject: [PATCH 5/5] =?UTF-8?q?Add=20Ren=C3=A9=20Meusel=20(reneme)=20to=20?= =?UTF-8?q?CONTRIBUTORS.txt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 0dc78ed38f..845ecd85c0 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -53,3 +53,4 @@ Christian Deneke (chris0x44) leetal Benjamin Lee (mobileben) +René Meusel (reneme)