From e1e88b398415acab5b43465f3ad548c937b6791c Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Mon, 22 Jun 2020 18:38:35 -0700 Subject: [PATCH] Support for requests with no body (#202) * avoid fail if no body in request * request with no body * fix for win86 * Update sdk/samples/http_client/curl/src/azure_core_with_curl_bodyBuffer.cpp Co-authored-by: Rick Winter Co-authored-by: Rick Winter --- sdk/core/azure-core/src/http/curl/curl.cpp | 14 +++- sdk/core/azure-core/src/http/response.cpp | 9 ++- .../src/azure_core_with_curl_bodyBuffer.cpp | 74 +++++++++++++++++-- 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/sdk/core/azure-core/src/http/curl/curl.cpp b/sdk/core/azure-core/src/http/curl/curl.cpp index cacce1a55..230a81188 100644 --- a/sdk/core/azure-core/src/http/curl/curl.cpp +++ b/sdk/core/azure-core/src/http/curl/curl.cpp @@ -204,13 +204,15 @@ CURLcode CurlSession::HttpRawSend() uint64_t rawRequestLen = rawRequest.size(); CURLcode sendResult = SendBuffer((uint8_t*)rawRequest.data(), (size_t)rawRequestLen); - if (this->m_request.GetMethod() == HttpMethod::Get) + + auto streamBody = this->m_request.GetBodyStream(); + if (streamBody == nullptr) { + // Finish request with no body uint8_t endOfRequest[] = "0"; return SendBuffer(endOfRequest, 1); // need one more byte to end request } - auto streamBody = this->m_request.GetBodyStream(); // Send body 64k at a time (libcurl default) // NOTE: if stream is on top a contiguous memory, we can avoid allocating this copying buffer std::unique_ptr unique_buffer(new uint8_t[UploadSstreamPageSize]); @@ -245,6 +247,14 @@ CURLcode CurlSession::ReadStatusLineAndHeadersFromRawResponse() } this->m_response = parser.GetResponse(); + + // For Head request, set the length of body response to 0. + if (this->m_request.GetMethod() == HttpMethod::Head) + { + this->m_response->SetBodyStream(new CurlBodyStream(0, this)); + return CURLE_OK; + } + // TODO: tolower ContentLength auto headers = this->m_response->GetHeaders(); auto bodySize = atoi(headers.at("Content-Length").data()); diff --git a/sdk/core/azure-core/src/http/response.cpp b/sdk/core/azure-core/src/http/response.cpp index 06dc208d9..85ce7e648 100644 --- a/sdk/core/azure-core/src/http/response.cpp +++ b/sdk/core/azure-core/src/http/response.cpp @@ -57,8 +57,13 @@ std::unique_ptr> Response::ConstructBodyBufferFromStream( return nullptr; } - uint8_t const bodySize = (uint8_t)stream->Length(); - std::unique_ptr> unique_buffer(new std::vector(bodySize)); + auto const bodySize = stream->Length(); + if (bodySize <= 0) + { + // no body to get + return nullptr; + } + std::unique_ptr> unique_buffer(new std::vector((size_t)bodySize)); auto buffer = unique_buffer.get()->data(); stream->Read(buffer, bodySize); diff --git a/sdk/samples/http_client/curl/src/azure_core_with_curl_bodyBuffer.cpp b/sdk/samples/http_client/curl/src/azure_core_with_curl_bodyBuffer.cpp index 177088c59..ca322e3b4 100644 --- a/sdk/samples/http_client/curl/src/azure_core_with_curl_bodyBuffer.cpp +++ b/sdk/samples/http_client/curl/src/azure_core_with_curl_bodyBuffer.cpp @@ -22,6 +22,9 @@ constexpr auto BufferSize = 50; std::vector buffer(BufferSize); Http::Request createGetRequest(); Http::Request createPutRequest(); +Http::Request createHeadRequest(); +Http::Request createDeleteRequest(); +Http::Request createPatchRequest(); void printRespose(std::unique_ptr response); int main() @@ -31,6 +34,9 @@ int main() // Both requests uses a body buffer to be uploaded that would produce responses with bodyBuffer auto getRequest = createGetRequest(); auto putRequest = createPutRequest(); + auto headRequest = createHeadRequest(); + auto deleteRequest = createDeleteRequest(); + auto patchRequest = createPatchRequest(); // Create the Transport std::shared_ptr transport = std::make_unique(); @@ -43,11 +49,26 @@ int main() auto httpPipeline = Http::HttpPipeline(policies); auto context = Context(); - std::unique_ptr getResponse = httpPipeline.Send(context, getRequest); - std::unique_ptr putResponse = httpPipeline.Send(context, putRequest); + cout << endl << "GET:"; + std::unique_ptr getResponse = httpPipeline.Send(context, getRequest); printRespose(std::move(getResponse)); + + cout << endl << "PUT:"; + std::unique_ptr putResponse = httpPipeline.Send(context, putRequest); printRespose(std::move(putResponse)); + + cout << endl << "HEAD:"; + std::unique_ptr headResponse = httpPipeline.Send(context, headRequest); + printRespose(std::move(headResponse)); + + cout << endl << "DELETE:"; + std::unique_ptr deleteResponse = httpPipeline.Send(context, deleteRequest); + printRespose(std::move(deleteResponse)); + + cout << endl << "PATCH:"; + std::unique_ptr patchResponse = httpPipeline.Send(context, patchRequest); + printRespose(std::move(patchResponse)); } catch (Http::CouldNotResolveHostException& e) { @@ -110,8 +131,9 @@ void printRespose(std::unique_ptr response) throw; } - cout << static_cast::type>( - response->GetStatusCode()) + cout << endl + << static_cast::type>( + response->GetStatusCode()) << endl; cout << response->GetReasonPhrase() << endl; cout << "headers:" << endl; @@ -120,8 +142,48 @@ void printRespose(std::unique_ptr response) cout << header.first << " : " << header.second << endl; } cout << "Body (buffer):" << endl; - auto bodyVector = *Http::Response::ConstructBodyBufferFromStream(response->GetBodyStream()).get(); - cout << std::string(bodyVector.begin(), bodyVector.end()); + auto responseBodyVector + = Http::Response::ConstructBodyBufferFromStream(response->GetBodyStream()); + if (responseBodyVector != nullptr) + { + // print body only if response has a body. Head Response won't have body + auto bodyVector = *responseBodyVector.get(); + cout << std::string(bodyVector.begin(), bodyVector.end()) << endl; + } + std::cin.ignore(); return; } + +Http::Request createPatchRequest() +{ + string host("https://httpbin.org/patch"); + cout << "Creating an PATCH request to" << endl << "Host: " << host << endl; + + auto request = Http::Request(Http::HttpMethod::Patch, host); + request.AddHeader("Host", "httpbin.org"); + + return request; +} + +Http::Request createDeleteRequest() +{ + string host("https://httpbin.org/delete"); + cout << "Creating an DELETE request to" << endl << "Host: " << host << endl; + + auto request = Http::Request(Http::HttpMethod::Delete, host); + request.AddHeader("Host", "httpbin.org"); + + return request; +} + +Http::Request createHeadRequest() +{ + string host("https://httpbin.org/get"); + cout << "Creating an HEAD request to" << endl << "Host: " << host << endl; + + auto request = Http::Request(Http::HttpMethod::Head, host); + request.AddHeader("Host", "httpbin.org"); + + return request; +}