parent
9631e5978a
commit
61b8cdc3d4
@ -37,3 +37,6 @@ include(global_compile_options)
|
||||
|
||||
# sub-projects
|
||||
add_subdirectory(sdk/core/azure-core)
|
||||
add_subdirectory(sdk/platform/http_client/curl) # will work only if BUILD_CURL_TRANSPORT=ON
|
||||
add_subdirectory(sdk/samples/http_client/curl) # will work only if BUILD_CURL_TRANSPORT=ON
|
||||
add_subdirectory(sdk/platform/http_client/nohttp) # will work only if !BUILD_CURL_TRANSPORT=ON
|
||||
|
||||
@ -12,6 +12,7 @@ add_library (
|
||||
src/credentials/credentials
|
||||
src/http/http
|
||||
src/http/request
|
||||
src/http/response
|
||||
)
|
||||
|
||||
target_include_directories (azure-core PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> $<INSTALL_INTERFACE:include/az_core>)
|
||||
|
||||
@ -4,8 +4,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
@ -63,6 +66,177 @@ enum class HttpMethod
|
||||
PATCH,
|
||||
};
|
||||
|
||||
class Request
|
||||
{
|
||||
|
||||
private:
|
||||
// query needs to be first or at least before url, since url might update it
|
||||
std::map<std::string, std::string> m_queryParameters;
|
||||
|
||||
HttpMethod _method;
|
||||
std::string _url;
|
||||
std::map<std::string, std::string> m_headers;
|
||||
std::map<std::string, std::string> m_retryHeaders;
|
||||
std::map<std::string, std::string> m_retryQueryParameters;
|
||||
// Request can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
BodyStream* m_bodyStream;
|
||||
BodyBuffer* m_bodyBuffer;
|
||||
|
||||
// flag to know where to insert header
|
||||
bool m_retryModeEnabled;
|
||||
|
||||
// returns left map plus all items in right
|
||||
// when duplicates, left items are preferred
|
||||
static std::map<std::string, std::string> mergeMaps(
|
||||
std::map<std::string, std::string> left,
|
||||
std::map<std::string, std::string> const& right)
|
||||
{
|
||||
left.insert(right.begin(), right.end());
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will check if there are any query parameter in url looking for symbol '?'
|
||||
* If it is found, it will insert query parameters to m_queryParameters internal field
|
||||
* and remove it from url
|
||||
*/
|
||||
const std::string parseUrl(std::string const& url)
|
||||
{
|
||||
|
||||
const auto firstPosition = std::find(url.begin(), url.end(), '?');
|
||||
if (firstPosition == url.end())
|
||||
{
|
||||
return url; // not query parameters
|
||||
}
|
||||
|
||||
auto position = firstPosition; // position of symbol ?
|
||||
while (position != url.end())
|
||||
{
|
||||
++position; // skip over the ? or &
|
||||
const auto nextPosition = std::find(position, url.end(), '&');
|
||||
const auto equalChar = std::find(position, nextPosition, '=');
|
||||
auto valueStart = equalChar;
|
||||
if (valueStart != nextPosition)
|
||||
{
|
||||
++valueStart; // skip = symbol
|
||||
}
|
||||
|
||||
// Note: if there is another = symbol before nextPosition, it will be part of the paramenter
|
||||
// value. And if there is not a ? symbol, we add empty string as value
|
||||
m_queryParameters.insert(std::pair<std::string, std::string>(
|
||||
std::string(position, equalChar), std::string(valueStart, nextPosition)));
|
||||
|
||||
position = nextPosition;
|
||||
}
|
||||
|
||||
return std::string(url.begin(), firstPosition);
|
||||
}
|
||||
|
||||
Request(
|
||||
HttpMethod httpMethod,
|
||||
std::string const& url,
|
||||
BodyStream* bodyStream,
|
||||
BodyBuffer* bodyBuffer)
|
||||
: _method(std::move(httpMethod)), _url(parseUrl(url)), m_bodyStream(bodyStream),
|
||||
m_bodyBuffer(bodyBuffer), m_retryModeEnabled(false)
|
||||
{
|
||||
// TODO: parse url
|
||||
}
|
||||
|
||||
public:
|
||||
Request(HttpMethod httpMethod, std::string const& url)
|
||||
: Request(httpMethod, url, BodyStream::null, BodyBuffer::null)
|
||||
{
|
||||
}
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyBuffer* bodyBuffer)
|
||||
: Request(httpMethod, url, BodyStream::null, bodyBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
|
||||
: Request(httpMethod, url, bodyStream, BodyBuffer::null)
|
||||
{
|
||||
}
|
||||
|
||||
// Methods used to build HTTP request
|
||||
void addPath(std::string const& path);
|
||||
void addQueryParameter(std::string const& name, std::string const& value);
|
||||
void addHeader(std::string const& name, std::string const& value);
|
||||
void startRetry(); // only called by retry policy
|
||||
|
||||
// Methods used by transport layer (and logger) to send request
|
||||
HttpMethod getMethod();
|
||||
std::string getEncodedUrl(); // should return encoded url
|
||||
std::map<std::string, std::string> getHeaders();
|
||||
BodyStream* getBodyStream();
|
||||
BodyBuffer* getBodyBuffer();
|
||||
};
|
||||
|
||||
/*
|
||||
* Response exceptions
|
||||
*/
|
||||
struct CouldNotResolveHostException : public std::exception
|
||||
{
|
||||
const char* what() const throw() { return "couldnt resolve host"; }
|
||||
};
|
||||
struct ErrorWhileWrittingResponse : public std::exception
|
||||
{
|
||||
const char* what() const throw() { return "couldnt write response"; }
|
||||
};
|
||||
// Any other excpetion from transport layer without an specific exception defined above
|
||||
struct TransportException : public std::exception
|
||||
{
|
||||
const char* what() const throw() { return "Error on transport layer while sending request"; }
|
||||
};
|
||||
|
||||
class Response
|
||||
{
|
||||
|
||||
private:
|
||||
uint16_t m_statusCode;
|
||||
std::string m_reasonPhrase;
|
||||
std::map<std::string, std::string> m_headers;
|
||||
|
||||
// Response can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
http::BodyBuffer* m_bodyBuffer;
|
||||
http::BodyStream* m_bodyStream;
|
||||
|
||||
Response(
|
||||
uint16_t statusCode,
|
||||
std::string const& reasonPhrase,
|
||||
BodyBuffer* const bodyBuffer,
|
||||
BodyStream* const BodyStream)
|
||||
: m_statusCode(statusCode), m_reasonPhrase(reasonPhrase), m_bodyBuffer(bodyBuffer),
|
||||
m_bodyStream(BodyStream)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Response(uint16_t statusCode, std::string const& reasonPhrase)
|
||||
: Response(statusCode, reasonPhrase, http::BodyBuffer::null, http::BodyStream::null)
|
||||
{
|
||||
}
|
||||
|
||||
// Methods used to build HTTP response
|
||||
void addHeader(std::string const& name, std::string const& value);
|
||||
void setBody(BodyBuffer* bodyBuffer);
|
||||
void setBody(BodyStream* bodyStream);
|
||||
|
||||
// Methods used by transport layer (and logger) to send response
|
||||
uint16_t getStatusCode();
|
||||
std::string const& getReasonPhrase();
|
||||
std::map<std::string, std::string> const& getHeaders();
|
||||
http::BodyStream* getBodyStream();
|
||||
http::BodyBuffer* getBodyBuffer();
|
||||
};
|
||||
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
static Response send(Request& request);
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
|
||||
@ -1,147 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
|
||||
class Request
|
||||
{
|
||||
|
||||
private:
|
||||
Request(Request const&) = delete;
|
||||
void operator=(Request const&) = delete;
|
||||
|
||||
// query needs to be first or at least before url, since url might update it
|
||||
std::map<std::string, std::string> _queryParameters;
|
||||
|
||||
HttpMethod _method;
|
||||
std::string _url;
|
||||
std::map<std::string, std::string> _headers;
|
||||
std::map<std::string, std::string> _retryHeaders;
|
||||
std::map<std::string, std::string> _retryQueryParameters;
|
||||
// Request can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
BodyStream* _bodyStream;
|
||||
BodyBuffer* _bodyBuffer;
|
||||
|
||||
// flag to know where to insert header
|
||||
bool _retryModeEnabled;
|
||||
|
||||
// returns left map plus all items in right
|
||||
// when duplicates, left items are preferred
|
||||
static std::map<std::string, std::string> mergeMaps(
|
||||
std::map<std::string, std::string> const& left,
|
||||
std::map<std::string, std::string> const& right)
|
||||
{
|
||||
auto result = std::map<std::string, std::string>(left);
|
||||
std::for_each(right.begin(), right.end(), [&](auto const& pair) { result.insert(pair); });
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an stream from source string. Then use getline and separator to get as many tokens as
|
||||
* possible and insert each one to result vector
|
||||
*/
|
||||
static std::vector<std::string> split(std::string source, char separator)
|
||||
{
|
||||
auto result = std::vector<std::string>();
|
||||
|
||||
auto stringAsStream = std::stringstream(source);
|
||||
auto token = std::string();
|
||||
|
||||
while (std::getline(stringAsStream, token, separator))
|
||||
{
|
||||
result.push_back(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will check if there are any query parameter in url looking for symbol '?'
|
||||
* If it is found, it will insert query parameters to _queryParameters internal field
|
||||
* and remove it from url
|
||||
*/
|
||||
std::string parseUrl(std::string url)
|
||||
{
|
||||
auto position = url.find('?');
|
||||
|
||||
if (position == std::string::npos)
|
||||
{
|
||||
return url; // no query parameters. Nothing else to do
|
||||
}
|
||||
|
||||
// Get query parameters string and update
|
||||
auto queryParameters = url.substr(position + 1);
|
||||
url = url.substr(0, position);
|
||||
|
||||
// Split all query parameters (should be separated by &)
|
||||
auto queryParametersVector = split(queryParameters, '&');
|
||||
|
||||
// insert each query parameter to internal field
|
||||
std::for_each(queryParametersVector.begin(), queryParametersVector.end(), [&](auto query) {
|
||||
auto parameter = split(query, '=');
|
||||
// Will throw if parameter in query is not valid (i.e. arg:1)
|
||||
_queryParameters.insert(std::pair<std::string, std::string>(parameter[0], parameter[1]));
|
||||
});
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
Request(
|
||||
HttpMethod httpMethod,
|
||||
std::string const& url,
|
||||
BodyStream* bodyStream,
|
||||
BodyBuffer* bodyBuffer)
|
||||
: _method(std::move(httpMethod)), _url(parseUrl(std::move(url))), _bodyStream(bodyStream),
|
||||
_bodyBuffer(bodyBuffer), _retryModeEnabled(false)
|
||||
{
|
||||
// TODO: parse url
|
||||
}
|
||||
|
||||
public:
|
||||
Request(HttpMethod httpMethod, std::string const& url)
|
||||
: Request(httpMethod, url, BodyStream::null, BodyBuffer::null)
|
||||
{
|
||||
}
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyBuffer* bodyBuffer)
|
||||
: Request(httpMethod, url, BodyStream::null, bodyBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
|
||||
: Request(httpMethod, url, bodyStream, BodyBuffer::null)
|
||||
{
|
||||
}
|
||||
|
||||
// Methods used to build HTTP request
|
||||
void addPath(std::string const& path);
|
||||
void addQueryParameter(std::string const& name, std::string const& value);
|
||||
void addHeader(std::string const& name, std::string const& value);
|
||||
void startRetry(); // only called by retry policy
|
||||
|
||||
// Methods used by transport layer (and logger) to send request
|
||||
HttpMethod getMethod();
|
||||
std::string getEncodedUrl(); // should return encoded url
|
||||
std::map<std::string, std::string> getHeaders();
|
||||
BodyStream* getBodyStream();
|
||||
BodyBuffer* getBodyBuffer();
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
|
||||
class Response
|
||||
{
|
||||
|
||||
private:
|
||||
Response(Response const&) = delete;
|
||||
void operator=(Response const&) = delete;
|
||||
|
||||
uint16_t _statusCode;
|
||||
std::string _reasonPhrase;
|
||||
std::map<std::string, std::string> _headers;
|
||||
|
||||
// Response can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
BodyBuffer& _bodyBuffer;
|
||||
BodyStream& _bodyStream;
|
||||
|
||||
Response(
|
||||
uint16_t statusCode,
|
||||
std::string reasonPhrase,
|
||||
BodyBuffer& const bodyBuffer,
|
||||
BodyStream& const BodyStream)
|
||||
: _statusCode(statusCode), _reasonPhrase(reasonPhrase), _bodyBuffer(bodyBuffer),
|
||||
_bodyStream(BodyStream)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Response(uint16_t statusCode, std::string reasonPhrase)
|
||||
: Response(statusCode, reasonPhrase, BodyBuffer::null, BodyStream::null)
|
||||
{
|
||||
}
|
||||
|
||||
// Methods used to build HTTP response
|
||||
void addHeader(std::string const& name, std::string const& value);
|
||||
void setBody(BodyBuffer& const bodyBuffer);
|
||||
void setBody(BodyStream& const bodyStream);
|
||||
|
||||
// Methods used by transport layer (and logger) to send response
|
||||
uint16_t const& getStatusCode();
|
||||
std::string const& getReasonPhrase();
|
||||
std::map<std::string, std::string> const& getHeaders();
|
||||
http::BodyStream& getBodyStream();
|
||||
http::BodyBuffer& getBodyBuffer();
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
@ -6,7 +6,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include <http/request.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
|
||||
@ -14,47 +13,47 @@ void Request::addPath(std::string const& path) { this->_url += "/" + path; }
|
||||
|
||||
void Request::addQueryParameter(std::string const& name, std::string const& value)
|
||||
{
|
||||
if (this->_retryModeEnabled)
|
||||
if (this->m_retryModeEnabled)
|
||||
{
|
||||
// When retry mode is ON, any new value must override previous
|
||||
this->_retryQueryParameters[name] = value;
|
||||
this->m_retryQueryParameters[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_queryParameters.insert(std::pair<std::string, std::string>(name, value));
|
||||
this->m_queryParameters.insert(std::pair<std::string, std::string>(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
void Request::addHeader(std::string const& name, std::string const& value)
|
||||
{
|
||||
if (this->_retryModeEnabled)
|
||||
if (this->m_retryModeEnabled)
|
||||
{
|
||||
// When retry mode is ON, any new value must override previous
|
||||
this->_retryHeaders[name] = value;
|
||||
this->m_retryHeaders[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_headers.insert(std::pair<std::string, std::string>(name, value));
|
||||
this->m_headers.insert(std::pair<std::string, std::string>(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
void Request::startRetry()
|
||||
{
|
||||
this->_retryModeEnabled = true;
|
||||
this->_retryHeaders.clear();
|
||||
this->m_retryModeEnabled = true;
|
||||
this->m_retryHeaders.clear();
|
||||
}
|
||||
|
||||
HttpMethod Request::getMethod() { return this->_method; }
|
||||
|
||||
std::string Request::getEncodedUrl()
|
||||
{
|
||||
if (this->_queryParameters.size() == 0 && this->_retryQueryParameters.size() == 0)
|
||||
if (this->m_queryParameters.size() == 0 && this->m_retryQueryParameters.size() == 0)
|
||||
{
|
||||
return _url; // no query parameters to add
|
||||
}
|
||||
|
||||
// remove query duplicates
|
||||
auto queryParameters = Request::mergeMaps(this->_retryQueryParameters, this->_queryParameters);
|
||||
auto queryParameters = Request::mergeMaps(this->m_retryQueryParameters, this->m_queryParameters);
|
||||
// build url
|
||||
auto queryString = std::string("");
|
||||
for (auto pair : queryParameters)
|
||||
@ -69,9 +68,9 @@ std::map<std::string, std::string> Request::getHeaders()
|
||||
{
|
||||
// create map with retry headers witch are the most important and we don't want
|
||||
// to override them with any duplicate header
|
||||
return Request::mergeMaps(this->_retryHeaders, this->_headers);
|
||||
return Request::mergeMaps(this->m_retryHeaders, this->m_headers);
|
||||
}
|
||||
|
||||
BodyStream* Request::getBodyStream() { return _bodyStream; }
|
||||
BodyStream* Request::getBodyStream() { return m_bodyStream; }
|
||||
|
||||
BodyBuffer* Request::getBodyBuffer() { return _bodyBuffer; }
|
||||
BodyBuffer* Request::getBodyBuffer() { return m_bodyBuffer; }
|
||||
|
||||
@ -6,19 +6,15 @@
|
||||
#include <vector>
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include <http/response.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
|
||||
BodyStream& BodyStream::null = *(BodyStream*)NULL;
|
||||
BodyBuffer& BodyBuffer::null = *(BodyBuffer*)NULL;
|
||||
uint16_t Response::getStatusCode() { return m_statusCode; }
|
||||
|
||||
uint16_t const& Response::getStatusCode() { return _statusCode; }
|
||||
std::string const& Response::getReasonPhrase() { return m_reasonPhrase; }
|
||||
|
||||
std::string const& Response::getReasonPhrase() { return _reasonPhrase; }
|
||||
std::map<std::string, std::string> const& Response::getHeaders() { return this->m_headers; }
|
||||
|
||||
std::map<std::string, std::string> const& Response::getHeaders() { return this->_headers; }
|
||||
BodyStream* Response::getBodyStream() { return m_bodyStream; }
|
||||
|
||||
BodyStream& Response::getBodyStream() { return _bodyStream; }
|
||||
|
||||
BodyBuffer& Response::getBodyBuffer() { return _bodyBuffer; }
|
||||
BodyBuffer* Response::getBodyBuffer() { return m_bodyBuffer; }
|
||||
|
||||
@ -5,15 +5,17 @@ cmake_minimum_required (VERSION 3.12)
|
||||
|
||||
include(AddGoogleTest)
|
||||
|
||||
project (azure-core-test LANGUAGES CXX)
|
||||
set(TARGET_NAME "azure-core-test")
|
||||
|
||||
project (${TARGET_NAME} LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
azure-core-test
|
||||
${TARGET_NAME}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(azure-core-test PRIVATE azure-core)
|
||||
add_gtest(azure-core-test)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core)
|
||||
add_gtest(${TARGET_NAME})
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include <http/request.hpp>
|
||||
#include <internal/credentials_internal.hpp>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
32
sdk/platform/http_client/curl/CMakeLists.txt
Normal file
32
sdk/platform/http_client/curl/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if (BUILD_CURL_TRANSPORT)
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
set(TARGET_NAME "azure-transport-curl")
|
||||
|
||||
project(${TARGET_NAME} LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
find_package(CURL CONFIG)
|
||||
if(NOT CURL_FOUND)
|
||||
find_package(CURL REQUIRED)
|
||||
endif()
|
||||
|
||||
add_library (
|
||||
${TARGET_NAME} STATIC
|
||||
src/azure_transport_curl
|
||||
src/curl_client
|
||||
)
|
||||
|
||||
target_include_directories (${TARGET_NAME} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> $<INSTALL_INTERFACE:include/azure_curl>)
|
||||
|
||||
# make sure that users can consume the project as a library.
|
||||
add_library (azure::curl ALIAS ${TARGET_NAME})
|
||||
|
||||
target_include_directories(${TARGET_NAME} PUBLIC ${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core CURL::libcurl)
|
||||
|
||||
endif()
|
||||
21
sdk/platform/http_client/curl/LICENSE
Normal file
21
sdk/platform/http_client/curl/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
39
sdk/platform/http_client/curl/inc/curl_client.hpp
Normal file
39
sdk/platform/http_client/curl/inc/curl_client.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <http/http.hpp>
|
||||
|
||||
class CurlClient
|
||||
{
|
||||
private:
|
||||
azure::core::http::Request& m_request;
|
||||
CURL* m_p_curl;
|
||||
|
||||
// setHeaders()
|
||||
CURLcode setUrl()
|
||||
{
|
||||
return curl_easy_setopt(m_p_curl, CURLOPT_URL, this->m_request.getEncodedUrl().c_str());
|
||||
}
|
||||
CURLcode perform()
|
||||
{
|
||||
auto settingUp = setUrl();
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
return curl_easy_perform(m_p_curl);
|
||||
}
|
||||
|
||||
public:
|
||||
CurlClient(azure::core::http::Request& request) : m_request(request)
|
||||
{
|
||||
m_p_curl = curl_easy_init();
|
||||
}
|
||||
// client curl struct on destruct
|
||||
~CurlClient() { curl_easy_cleanup(m_p_curl); }
|
||||
|
||||
azure::core::http::Response send();
|
||||
};
|
||||
15
sdk/platform/http_client/curl/src/azure_transport_curl.cpp
Normal file
15
sdk/platform/http_client/curl/src/azure_transport_curl.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <curl_client.hpp>
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
|
||||
// implement send method
|
||||
Response Client::send(Request& request)
|
||||
{
|
||||
CurlClient client(request);
|
||||
// return request response
|
||||
return client.send();
|
||||
}
|
||||
36
sdk/platform/http_client/curl/src/curl_client.cpp
Normal file
36
sdk/platform/http_client/curl/src/curl_client.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <curl_client.hpp>
|
||||
#include <http/http.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace std;
|
||||
|
||||
Response CurlClient::send()
|
||||
{
|
||||
auto performing = perform();
|
||||
|
||||
if (performing != CURLE_OK)
|
||||
{
|
||||
switch (performing)
|
||||
{
|
||||
case CURLE_COULDNT_RESOLVE_HOST:
|
||||
{
|
||||
throw azure::core::http::CouldNotResolveHostException();
|
||||
}
|
||||
case CURLE_WRITE_ERROR:
|
||||
{
|
||||
throw azure::core::http::ErrorWhileWrittingResponse();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw azure::core::http::TransportException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Response(200, "OK\n");
|
||||
}
|
||||
23
sdk/platform/http_client/nohttp/CMakeLists.txt
Normal file
23
sdk/platform/http_client/nohttp/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if (NOT BUILD_CURL_TRANSPORT)
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
set(TARGET_NAME "azure-transport-nothhp")
|
||||
|
||||
project(${TARGET_NAME} LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_library (
|
||||
${TARGET_NAME} STATIC
|
||||
src/azure_transport_nohttp.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core)
|
||||
|
||||
# make sure that users can consume the project as a library.
|
||||
add_library (azure::nohttp ALIAS ${TARGET_NAME})
|
||||
|
||||
endif()
|
||||
21
sdk/platform/http_client/nohttp/LICENSE
Normal file
21
sdk/platform/http_client/nohttp/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
|
||||
// implement send method
|
||||
Response Client::send(Request& request)
|
||||
{
|
||||
(void)request;
|
||||
throw;
|
||||
}
|
||||
20
sdk/samples/http_client/curl/CMakeLists.txt
Normal file
20
sdk/samples/http_client/curl/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if (BUILD_CURL_TRANSPORT)
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
set(TARGET_NAME "azure_core_with_curl")
|
||||
|
||||
project(${TARGET_NAME} LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
${TARGET_NAME}
|
||||
src/azure_core_with_curl
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core azure-transport-curl)
|
||||
|
||||
endif()
|
||||
38
sdk/samples/http_client/curl/src/azure_core_with_curl.cpp
Normal file
38
sdk/samples/http_client/curl/src/azure_core_with_curl.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief Simulates customer application that is linked with azure-core and azure-transport-curl
|
||||
*
|
||||
*/
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace azure::core;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
string host("https://httpbin.org/get");
|
||||
cout << "testing curl from transport" << endl << "Host: " << host << endl;
|
||||
|
||||
auto request = http::Request(http::HttpMethod::GET, host);
|
||||
|
||||
try
|
||||
{
|
||||
auto response = http::Client::send(request);
|
||||
cout << response.getReasonPhrase();
|
||||
}
|
||||
catch (http::CouldNotResolveHostException& e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
}
|
||||
catch (http::TransportException& e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user