Http/moving DownloadViaStream option to request (#362)
* move DownloadViaStream option to Request * Fix credentials request * Fix unit tests * use constructor instead of set method * fix tests
This commit is contained in:
parent
2d507e7e4a
commit
d9e39a0e6e
@ -220,6 +220,7 @@ namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
// flag to know where to insert header
|
||||
bool m_retryModeEnabled;
|
||||
bool m_isDownloadViaStream;
|
||||
|
||||
// returns left map plus all items in right
|
||||
// when duplicates, left items are preferred
|
||||
@ -234,15 +235,30 @@ namespace Azure { namespace Core { namespace Http {
|
||||
std::string GetQueryString() const;
|
||||
|
||||
public:
|
||||
explicit Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
|
||||
explicit Request(
|
||||
HttpMethod httpMethod,
|
||||
std::string const& url,
|
||||
BodyStream* bodyStream,
|
||||
bool downloadViaStream)
|
||||
: m_method(std::move(httpMethod)), m_url(url), m_bodyStream(bodyStream),
|
||||
m_retryModeEnabled(false)
|
||||
m_retryModeEnabled(false), m_isDownloadViaStream(downloadViaStream)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
|
||||
: Request(httpMethod, url, bodyStream, false)
|
||||
{
|
||||
}
|
||||
|
||||
// Typically used for GET with no request body that can return bodyStream
|
||||
explicit Request(HttpMethod httpMethod, std::string const& url, bool downloadViaStream)
|
||||
: Request(httpMethod, url, NullBodyStream::GetNullBodyStream(), downloadViaStream)
|
||||
{
|
||||
}
|
||||
|
||||
// Typically used for GET with no request body.
|
||||
explicit Request(HttpMethod httpMethod, std::string const& url)
|
||||
: Request(httpMethod, url, NullBodyStream::GetNullBodyStream())
|
||||
: Request(httpMethod, url, NullBodyStream::GetNullBodyStream(), false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -259,6 +275,7 @@ namespace Azure { namespace Core { namespace Http {
|
||||
std::map<std::string, std::string> GetHeaders() const;
|
||||
BodyStream* GetBodyStream() { return this->m_bodyStream; }
|
||||
std::string GetHTTPMessagePreBody() const;
|
||||
bool IsDownloadViaStream() { return m_isDownloadViaStream; }
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -13,10 +13,6 @@
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
namespace Details {
|
||||
constexpr static const char* c_GetStreamForBody = "no-download";
|
||||
} // namespace Details
|
||||
|
||||
class NextHttpPolicy;
|
||||
|
||||
class HttpPolicy {
|
||||
@ -58,19 +54,6 @@ namespace Azure { namespace Core { namespace Http {
|
||||
std::shared_ptr<HttpTransport> m_transport;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a context with the required configuration to avoid transport policy to
|
||||
* download a body payload from http response and return a BodyStream to read from the wire
|
||||
* instead.
|
||||
*
|
||||
* @param ctx parent context to be used to create a context with specific settings
|
||||
* @return Azure::Core::Context
|
||||
*/
|
||||
static Azure::Core::Context DownloadViaStream(Azure::Core::Context& ctx)
|
||||
{
|
||||
return ctx.WithValue(Details::c_GetStreamForBody, true);
|
||||
}
|
||||
|
||||
explicit TransportPolicy(std::shared_ptr<HttpTransport> transport)
|
||||
: m_transport(std::move(transport))
|
||||
{
|
||||
|
||||
@ -103,16 +103,8 @@ AccessToken ClientSecretCredential::GetToken(
|
||||
throw AuthenticationException(errorMsg.str());
|
||||
}
|
||||
|
||||
auto const responseStream = response->GetBodyStream();
|
||||
auto const responseStreamLength = responseStream->Length();
|
||||
|
||||
std::string responseBody(static_cast<std::string::size_type>(responseStreamLength), 0);
|
||||
|
||||
Azure::Core::Http::BodyStream::ReadToCount(
|
||||
context,
|
||||
*responseStream,
|
||||
static_cast<std::uint8_t*>(static_cast<void*>(&responseBody[0])),
|
||||
responseStreamLength);
|
||||
auto const responseBodyVector = response->GetBody();
|
||||
std::string responseBody(responseBodyVector.begin(), responseBodyVector.end());
|
||||
|
||||
// TODO: use JSON parser.
|
||||
auto const responseBodySize = responseBody.size();
|
||||
|
||||
@ -16,7 +16,7 @@ std::unique_ptr<RawResponse> TransportPolicy::Send(
|
||||
* Call the transport and return
|
||||
*/
|
||||
auto response = m_transport->Send(ctx, request);
|
||||
if (ctx.HasKey(Details::c_GetStreamForBody))
|
||||
if (request. IsDownloadViaStream())
|
||||
{ // special case to return a response with BodyStream to read directly from socket
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "transport_adapter.hpp"
|
||||
#include <context.hpp>
|
||||
#include <iostream>
|
||||
#include <response.hpp>
|
||||
#include <string>
|
||||
|
||||
@ -24,6 +25,16 @@ namespace Azure { namespace Core { namespace Test {
|
||||
Azure::Core::Http::HttpPipeline TransportAdapter::pipeline(policies);
|
||||
Azure::Core::Context TransportAdapter::context = Azure::Core::GetApplicationContext();
|
||||
|
||||
static void checkResponseCode(Azure::Core::Http::HttpStatusCode code)
|
||||
{
|
||||
if (code != Azure::Core::Http::HttpStatusCode::Ok)
|
||||
{
|
||||
std::cout << static_cast<typename std::underlying_type<Http::HttpStatusCode>::type>(code);
|
||||
return;
|
||||
}
|
||||
EXPECT_TRUE(code == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
}
|
||||
|
||||
void TransportAdapter::CheckBodyFromBuffer(
|
||||
Azure::Core::Http::RawResponse& response,
|
||||
int64_t size,
|
||||
@ -77,14 +88,14 @@ namespace Azure { namespace Core { namespace Test {
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
|
||||
// Add a header and send again. RawResponse should return that header in the body
|
||||
request.AddHeader("123", "456");
|
||||
response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
// header length is 6 (data) + 13 (formating) -> ` "123": "456"\r\n,`
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize + 6 + 13);
|
||||
}
|
||||
@ -100,7 +111,7 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
auto response = pipeline.Send(context, request);
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
}
|
||||
}
|
||||
@ -112,7 +123,7 @@ namespace Azure { namespace Core { namespace Test {
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, host);
|
||||
auto response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
|
||||
// Check content-length header to be greater than 0
|
||||
@ -124,13 +135,13 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/put");
|
||||
|
||||
// PUT 1MB
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024 * 1024, 'x');
|
||||
// PUT 1K
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024, 'x');
|
||||
auto bodyRequest = Azure::Core::Http::MemoryBodyStream(requestBodyVector);
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, host, &bodyRequest);
|
||||
auto response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
@ -140,13 +151,13 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/delete");
|
||||
|
||||
// Delete with 1MB payload
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024 * 1024, 'x');
|
||||
// Delete with 1k payload
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024, 'x');
|
||||
auto bodyRequest = Azure::Core::Http::MemoryBodyStream(requestBodyVector);
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Delete, host, &bodyRequest);
|
||||
auto response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
@ -162,7 +173,7 @@ namespace Azure { namespace Core { namespace Test {
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Patch, host, &bodyRequest);
|
||||
auto response = pipeline.Send(context, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize);
|
||||
@ -182,7 +193,7 @@ namespace Azure { namespace Core { namespace Test {
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto response = pipeline.Send(context, request);
|
||||
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromBuffer(*response, expectedResponseBodySize, expectedChunkResponse);
|
||||
}
|
||||
|
||||
@ -194,17 +205,16 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/get");
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
|
||||
// Add a header and send again. Response should return that header in the body
|
||||
request.AddHeader("123", "456");
|
||||
response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
// header length is 6 (data) + 13 (formating) -> ` "123": "456"\r\n,`
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize + 6 + 13);
|
||||
}
|
||||
@ -213,15 +223,14 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/get");
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host, true);
|
||||
|
||||
// loop sending request
|
||||
for (auto i = 0; i < 20; i++)
|
||||
{
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
auto response = pipeline.Send(context, request);
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
}
|
||||
}
|
||||
@ -231,10 +240,9 @@ namespace Azure { namespace Core { namespace Test {
|
||||
std::string host("http://httpbin.org/get");
|
||||
auto expectedResponseBodySize = 0;
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, host);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, host, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
|
||||
// Check content-length header to be greater than 0
|
||||
@ -246,14 +254,13 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/put");
|
||||
|
||||
// PUT 1MB
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024 * 1024, 'x');
|
||||
// PUT 1k
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024, 'x');
|
||||
auto bodyRequest = Azure::Core::Http::MemoryBodyStream(requestBodyVector);
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, host, &bodyRequest);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, host, &bodyRequest, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
@ -263,14 +270,13 @@ namespace Azure { namespace Core { namespace Test {
|
||||
{
|
||||
std::string host("http://httpbin.org/delete");
|
||||
|
||||
// Delete with 1MB payload
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024 * 1024, 'x');
|
||||
// Delete with 1k payload
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024, 'x');
|
||||
auto bodyRequest = Azure::Core::Http::MemoryBodyStream(requestBodyVector);
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Delete, host, &bodyRequest);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
auto request = Azure::Core::Http::Request(
|
||||
Azure::Core::Http::HttpMethod::Delete, host, &bodyRequest, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
@ -283,11 +289,10 @@ namespace Azure { namespace Core { namespace Test {
|
||||
// Patch with 1kb payload
|
||||
auto requestBodyVector = std::vector<uint8_t>(1024, 'x');
|
||||
auto bodyRequest = Azure::Core::Http::MemoryBodyStream(requestBodyVector);
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Patch, host, &bodyRequest);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
auto request = Azure::Core::Http::Request(
|
||||
Azure::Core::Http::HttpMethod::Patch, host, &bodyRequest, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
|
||||
auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length"));
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize);
|
||||
@ -304,11 +309,10 @@ namespace Azure { namespace Core { namespace Test {
|
||||
"response after 1 second. The server should not close the stream before all chunks are "
|
||||
"sent to a client.</h5></body></html>");
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto ctx = Azure::Core::Http::TransportPolicy::DownloadViaStream(context);
|
||||
auto response = pipeline.Send(ctx, request);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host, true);
|
||||
auto response = pipeline.Send(context, request);
|
||||
|
||||
EXPECT_TRUE(response->GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok);
|
||||
checkResponseCode(response->GetStatusCode());
|
||||
CheckBodyFromStream(*response, expectedResponseBodySize, expectedChunkResponse);
|
||||
}
|
||||
|
||||
@ -317,7 +321,7 @@ namespace Azure { namespace Core { namespace Test {
|
||||
std::string host("http://httpbin.org/get");
|
||||
std::string expectedType("This is the Response Type");
|
||||
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host, false);
|
||||
auto response = pipeline.Send(context, request);
|
||||
|
||||
Azure::Core::Response<std::string> responseT(expectedType, std::move(response));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user