From 2029d3d242c2d903264ed1c573b5bb138ff1c235 Mon Sep 17 00:00:00 2001 From: Pavel Kovalenko Date: Mon, 8 Jun 2020 17:15:43 +0300 Subject: [PATCH] HttpResponse return IStream as response body. --- .../include/aws/core/http/HttpResponse.h | 4 +++- .../core/http/standard/StandardHttpResponse.h | 4 +++- .../aws/core/utils/stream/ResponseStream.h | 13 +++++++++---- .../include/aws/core/utils/xml/XmlSerializer.h | 2 +- aws-cpp-sdk-core/source/client/AWSClient.cpp | 16 ++++++++-------- .../source/http/curl/CurlHttpClient.cpp | 7 ++++--- .../source/internal/AWSHttpResourceClient.cpp | 2 +- .../source/utils/stream/ResponseStream.cpp | 18 +++++------------- .../source/utils/xml/XmlSerializer.cpp | 2 +- .../aws/s3/model/GetBucketPolicyResult.h | 2 +- .../include/aws/s3/model/GetObjectResult.h | 2 +- .../aws/s3/model/GetObjectTorrentResult.h | 4 ++-- 12 files changed, 39 insertions(+), 37 deletions(-) diff --git a/aws-cpp-sdk-core/include/aws/core/http/HttpResponse.h b/aws-cpp-sdk-core/include/aws/core/http/HttpResponse.h index aaeb42648ac..c72801963ce 100644 --- a/aws-cpp-sdk-core/include/aws/core/http/HttpResponse.h +++ b/aws-cpp-sdk-core/include/aws/core/http/HttpResponse.h @@ -210,12 +210,14 @@ namespace Aws /** * Gets the response body of the response. */ - virtual Aws::IOStream& GetResponseBody() const = 0; + virtual Aws::IStream& GetResponseBody() const = 0; /** * Gives full control of the memory of the ResponseBody over to the caller. At this point, it is the caller's * responsibility to clean up this object. */ virtual Utils::Stream::ResponseStream&& SwapResponseStreamOwnership() = 0; + + virtual Utils::Stream::ResponseStream & GetResponseStream() = 0; /** * Adds a header to the http response object. */ diff --git a/aws-cpp-sdk-core/include/aws/core/http/standard/StandardHttpResponse.h b/aws-cpp-sdk-core/include/aws/core/http/standard/StandardHttpResponse.h index acca2366da3..4a5deee3239 100644 --- a/aws-cpp-sdk-core/include/aws/core/http/standard/StandardHttpResponse.h +++ b/aws-cpp-sdk-core/include/aws/core/http/standard/StandardHttpResponse.h @@ -67,12 +67,14 @@ namespace Aws /** * Gets the response body of the response. */ - inline Aws::IOStream& GetResponseBody() const { return bodyStream.GetUnderlyingStream(); } + inline Aws::IStream& GetResponseBody() const { return bodyStream.GetUnderlyingStream(); } /** * Gives full control of the memory of the ResponseBody over to the caller. At this point, it is the caller's * responsibility to clean up this object. */ inline Utils::Stream::ResponseStream&& SwapResponseStreamOwnership() { return std::move(bodyStream); } + + inline Utils::Stream::ResponseStream& GetResponseStream() { return bodyStream; } /** * Adds a header to the http response object. */ diff --git a/aws-cpp-sdk-core/include/aws/core/utils/stream/ResponseStream.h b/aws-cpp-sdk-core/include/aws/core/utils/stream/ResponseStream.h index 8b7ec042f9c..57cc77f91ec 100644 --- a/aws-cpp-sdk-core/include/aws/core/utils/stream/ResponseStream.h +++ b/aws-cpp-sdk-core/include/aws/core/utils/stream/ResponseStream.h @@ -19,6 +19,8 @@ #include #include +#include + namespace Aws { namespace Utils @@ -47,6 +49,7 @@ namespace Aws * Takes ownership of an underlying stream. */ ResponseStream(IOStream* underlyingStreamToManage); + ResponseStream(IStream* underlyingStreamToManage); ResponseStream(const ResponseStream&) = delete; ~ResponseStream(); @@ -59,12 +62,14 @@ namespace Aws /** * Gives access to underlying stream, but keep in mind that this changes state of the stream */ - inline Aws::IOStream& GetUnderlyingStream() const { return *m_underlyingStream; } + inline Aws::IStream & GetUnderlyingStream() const { return *m_underlyingStream; } + /** + * Set underlying stream + */ + void SetUnderlyingStream(std::shared_ptr stream) { m_underlyingStream = std::move(stream); } private: - void ReleaseStream(); - - Aws::IOStream* m_underlyingStream; + std::shared_ptr m_underlyingStream; }; class AWS_CORE_API DefaultUnderlyingStream : public Aws::IOStream diff --git a/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h b/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h index 07a543a64df..f044764e09f 100644 --- a/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h +++ b/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h @@ -193,7 +193,7 @@ namespace Aws /** * Parses the stream into an XMLDocument */ - static XmlDocument CreateFromXmlStream(Aws::IOStream&); + static XmlDocument CreateFromXmlStream(Aws::IStream&); /** * Parses the string into an XMLDocument */ diff --git a/aws-cpp-sdk-core/source/client/AWSClient.cpp b/aws-cpp-sdk-core/source/client/AWSClient.cpp index 2e1606713f4..9f9c00dc5ad 100644 --- a/aws-cpp-sdk-core/source/client/AWSClient.cpp +++ b/aws-cpp-sdk-core/source/client/AWSClient.cpp @@ -695,7 +695,7 @@ JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, return JsonOutcome(httpOutcome.GetError()); } - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + if (httpOutcome.GetResult()->GetResponseBody().peek() != EOF) //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. return JsonOutcome(AmazonWebServiceResult(JsonValue(httpOutcome.GetResult()->GetResponseBody()), httpOutcome.GetResult()->GetHeaders(), @@ -717,7 +717,7 @@ JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, return JsonOutcome(httpOutcome.GetError()); } - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + if (httpOutcome.GetResult()->GetResponseBody().peek() != EOF) { JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); if (!jsonValue.WasParseSuccessful()) @@ -750,7 +750,7 @@ JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptrGetResponseBody().tellp() > 0) + if (httpOutcome.GetResult()->GetResponseBody().peek() != EOF) { JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); if (!jsonValue.WasParseSuccessful()) @@ -776,7 +776,7 @@ AWSError AWSJsonClient::BuildAWSError( bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; error = AWSError(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); } - else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) + else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().eof()) { auto responseCode = httpResponse->GetResponseCode(); auto errorCode = GuessBodylessErrorType(responseCode); @@ -830,7 +830,7 @@ XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, return XmlOutcome(httpOutcome.GetError()); } - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + if (httpOutcome.GetResult()->GetResponseBody().peek() != EOF) { XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()); @@ -859,7 +859,7 @@ XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, return XmlOutcome(httpOutcome.GetError()); } - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + if (httpOutcome.GetResult()->GetResponseBody().peek() != EOF) { return XmlOutcome(AmazonWebServiceResult( XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()), @@ -877,7 +877,7 @@ AWSError AWSXMLClient::BuildAWSError(const std::shared_ptrGetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; error = AWSError(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); } - else if (httpResponse->GetResponseBody().tellp() < 1) + else if (httpResponse->GetResponseBody().eof()) { auto responseCode = httpResponse->GetResponseCode(); auto errorCode = GuessBodylessErrorType(responseCode); @@ -892,7 +892,7 @@ AWSError AWSXMLClient::BuildAWSError(const std::shared_ptrGetResponseBody().tellp() > 0) + if ((httpResponse->GetResponseBody()) && (httpResponse->GetResponseBody().tellg() > 0)) { httpResponse->GetResponseBody().seekg(0); diff --git a/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp index 53075526cc9..915f08430ef 100644 --- a/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp +++ b/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp @@ -184,7 +184,10 @@ static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata) context->m_rateLimiter->ApplyAndPayForCost(static_cast(sizeToWrite)); } - response->GetResponseBody().write(ptr, static_cast(sizeToWrite)); + auto stream = std::make_shared(); + stream->write(ptr, static_cast(sizeToWrite)); + stream->flush(); + response->GetResponseStream().SetUnderlyingStream(stream); auto& receivedHandler = context->m_request->GetDataReceivedEventHandler(); if (receivedHandler) { @@ -703,8 +706,6 @@ void CurlHttpClient::MakeRequestInternal(HttpRequest& request, { m_curlHandleContainer.ReleaseCurlHandle(connectionHandle); } - //go ahead and flush the response body stream - response->GetResponseBody().flush(); request.AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::RequestLatency), (DateTime::Now() - startTransmissionTime).count()); } diff --git a/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp b/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp index 62f9029fd5c..eeeb014ea40 100644 --- a/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp +++ b/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp @@ -144,7 +144,7 @@ AmazonWebServiceResult AWSHttpResourceClient::GetResourceWithAWSWeb } const Aws::Client::AWSError error = [this, &response]() { - if (response->HasClientError() || response->GetResponseBody().tellp() < 1) + if (response->HasClientError() || response->GetResponseBody().eof()) { AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Http request to retrieve credentials failed"); return AWSError(CoreErrors::NETWORK_CONNECTION, true); // Retryable diff --git a/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp b/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp index 3123bb6b27f..83480bd1d2d 100644 --- a/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp +++ b/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp @@ -35,6 +35,11 @@ ResponseStream::ResponseStream(Aws::IOStream* underlyingStreamToManage) : { } +ResponseStream::ResponseStream(Aws::IStream* underlyingStreamToManage) : + m_underlyingStream(underlyingStreamToManage) +{ +} + ResponseStream::ResponseStream(const Aws::IOStreamFactory& factory) : m_underlyingStream(factory()) { @@ -52,7 +57,6 @@ ResponseStream& ResponseStream::operator=(ResponseStream&& toMove) return *this; } - ReleaseStream(); m_underlyingStream = toMove.m_underlyingStream; toMove.m_underlyingStream = nullptr; @@ -61,18 +65,6 @@ ResponseStream& ResponseStream::operator=(ResponseStream&& toMove) ResponseStream::~ResponseStream() { - ReleaseStream(); -} - -void ResponseStream::ReleaseStream() -{ - if (m_underlyingStream) - { - m_underlyingStream->flush(); - Aws::Delete(m_underlyingStream); - } - - m_underlyingStream = nullptr; } static const char *DEFAULT_STREAM_TAG = "DefaultUnderlyingStream"; diff --git a/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp b/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp index a1e0a25cfec..1cd758efbfb 100644 --- a/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp +++ b/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp @@ -205,7 +205,7 @@ Aws::String XmlDocument::ConvertToString() const return printer.CStr(); } -XmlDocument XmlDocument::CreateFromXmlStream(Aws::IOStream& xmlStream) +XmlDocument XmlDocument::CreateFromXmlStream(Aws::IStream& xmlStream) { Aws::String xmlString((Aws::IStreamBufIterator(xmlStream)), Aws::IStreamBufIterator()); return CreateFromXmlString(xmlString); diff --git a/aws-cpp-sdk-s3/include/aws/s3/model/GetBucketPolicyResult.h b/aws-cpp-sdk-s3/include/aws/s3/model/GetBucketPolicyResult.h index 6e7245454c3..13c03d05393 100644 --- a/aws-cpp-sdk-s3/include/aws/s3/model/GetBucketPolicyResult.h +++ b/aws-cpp-sdk-s3/include/aws/s3/model/GetBucketPolicyResult.h @@ -49,7 +49,7 @@ namespace Model /** *

The bucket policy as a JSON document.

*/ - inline Aws::IOStream& GetPolicy() { return m_policy.GetUnderlyingStream(); } + inline Aws::IStream& GetPolicy() { return m_policy.GetUnderlyingStream(); } /** *

The bucket policy as a JSON document.

diff --git a/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectResult.h b/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectResult.h index dbdd32090a8..ee530dc753a 100644 --- a/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectResult.h +++ b/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectResult.h @@ -58,7 +58,7 @@ namespace Model /** *

Object data.

*/ - inline Aws::IOStream& GetBody() { return m_body.GetUnderlyingStream(); } + inline Aws::IStream& GetBody() { return m_body.GetUnderlyingStream(); } /** *

Object data.

diff --git a/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectTorrentResult.h b/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectTorrentResult.h index 1f1d2a07dcf..33ca0860f45 100644 --- a/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectTorrentResult.h +++ b/aws-cpp-sdk-s3/include/aws/s3/model/GetObjectTorrentResult.h @@ -50,12 +50,12 @@ namespace Model /** *

A Bencoded dictionary as defined by the BitTorrent specification

*/ - inline Aws::IOStream& GetBody() { return m_body.GetUnderlyingStream(); } + inline Aws::IStream& GetBody() { return m_body.GetUnderlyingStream(); } /** *

A Bencoded dictionary as defined by the BitTorrent specification

*/ - inline void ReplaceBody(Aws::IOStream* body) { m_body = Aws::Utils::Stream::ResponseStream(body); } + inline void ReplaceBody(Aws::IStream* body) { m_body = Aws::Utils::Stream::ResponseStream(body); }