parent
0b1eb288db
commit
602f75744a
@ -1,5 +1,5 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: Microsoft
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
|
||||
@ -37,6 +37,4 @@ 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
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "-DINSTALL_GTEST=OFF -DBUILD_TESTING=ON",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "-DINSTALL_GTEST=OFF -DBUILD_TESTING=OFF -DBUILD_CURL_TRANSPORT=ON",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -9,48 +9,48 @@ jobs:
|
||||
matrix:
|
||||
Linux_x64:
|
||||
vm.image: 'ubuntu-18.04'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[ssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-linux'
|
||||
Win_x86:
|
||||
vm.image: 'windows-2019'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[winssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x86-windows-static'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
CMAKE_GENERATOR_PLATFORM: Win32
|
||||
Win_x64:
|
||||
vm.image: 'windows-2019'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[winssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-windows-static'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
CMAKE_GENERATOR_PLATFORM: x64
|
||||
MacOS_x64:
|
||||
vm.image: 'macOS-10.14'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[ssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-osx'
|
||||
|
||||
# Unit testing ON
|
||||
Linux_x64_with_unit_test:
|
||||
vm.image: 'ubuntu-18.04'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[ssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-linux'
|
||||
build.args: ' -DBUILD_TESTING=ON'
|
||||
Win_x86_with_unit_test:
|
||||
vm.image: 'windows-2019'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[winssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x86-windows-static'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
CMAKE_GENERATOR_PLATFORM: Win32
|
||||
build.args: ' -DBUILD_TESTING=ON'
|
||||
Win_x64_with_unit_test:
|
||||
vm.image: 'windows-2019'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[winssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-windows-static'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
CMAKE_GENERATOR_PLATFORM: x64
|
||||
build.args: ' -DBUILD_TESTING=ON'
|
||||
MacOS_x64_with_unit_test:
|
||||
vm.image: 'macOS-10.14'
|
||||
vcpkg.deps: ''
|
||||
vcpkg.deps: 'curl[ssl]'
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-osx'
|
||||
build.args: ' -DBUILD_TESTING=ON'
|
||||
pool:
|
||||
|
||||
@ -2,20 +2,33 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
set(TARGET_NAME "azure-core")
|
||||
project(${TARGET_NAME} LANGUAGES CXX)
|
||||
|
||||
project (azure-core 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 (
|
||||
azure-core
|
||||
src/credentials/credentials
|
||||
src/http/http
|
||||
src/http/request
|
||||
src/http/response
|
||||
${TARGET_NAME}
|
||||
src/context.cpp
|
||||
src/credentials/credentials.cpp
|
||||
src/http/http.cpp
|
||||
src/http/policy.cpp
|
||||
src/http/request.cpp
|
||||
src/http/response.cpp
|
||||
src/http/curl/curl_transport.cpp
|
||||
src/http/winhttp/win_http_transport.cpp
|
||||
)
|
||||
|
||||
target_include_directories (azure-core PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> $<INSTALL_INTERFACE:include/az_core>)
|
||||
target_include_directories (${TARGET_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> $<INSTALL_INTERFACE:include/az_core>)
|
||||
|
||||
# make sure that users can consume the project as a library.
|
||||
add_library (Azure::Core ALIAS azure-core)
|
||||
add_library (Azure::Core ALIAS ${TARGET_NAME})
|
||||
|
||||
target_include_directories(${TARGET_NAME} PUBLIC ${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE CURL::libcurl)
|
||||
|
||||
@ -5,6 +5,10 @@
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
#define AZURE_UNREFERENCED_PARAMETER(x) ((void) (x));
|
||||
|
||||
namespace Azure { namespace Core {
|
||||
|
||||
|
||||
|
||||
}} // namespace Azure::Core
|
||||
|
||||
210
sdk/core/azure-core/inc/context.hpp
Normal file
210
sdk/core/azure-core/inc/context.hpp
Normal file
@ -0,0 +1,210 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Azure { namespace Core {
|
||||
|
||||
struct ValueBase
|
||||
{
|
||||
virtual ~ValueBase() {}
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief ContextValue exists as a substitute for variant which isn't available until C++17
|
||||
*/
|
||||
class ContextValue {
|
||||
enum class ContextValueType
|
||||
{
|
||||
Undefined,
|
||||
Bool,
|
||||
Int,
|
||||
StdString,
|
||||
UniquePtr
|
||||
};
|
||||
|
||||
ContextValueType m_contextValueType;
|
||||
union
|
||||
{
|
||||
bool m_b; // if m_contextValueType == ContextValueType::Bool
|
||||
int m_i; // if m_contextValueType == ContextValueType::Int
|
||||
std::string m_s; // if m_contextValueType == ContextValueType::StdString
|
||||
std::unique_ptr<ValueBase> m_p; // if m_contextValueType == ContextValueType::UniquePtr
|
||||
};
|
||||
|
||||
public:
|
||||
ContextValue() noexcept : m_contextValueType(ContextValueType::Undefined) {}
|
||||
ContextValue(bool b) noexcept : m_contextValueType(ContextValueType::Bool), m_b(b) {}
|
||||
ContextValue(int i) noexcept : m_contextValueType(ContextValueType::Int), m_i(i) {}
|
||||
ContextValue(const std::string& s) : m_contextValueType(ContextValueType::StdString), m_s(s) {}
|
||||
ContextValue(std::string&& s) noexcept
|
||||
: m_contextValueType(ContextValueType::UniquePtr), m_s(std::move(s))
|
||||
{
|
||||
}
|
||||
template <
|
||||
class DerivedFromValueBase,
|
||||
typename std::
|
||||
enable_if<std::is_convertible<DerivedFromValueBase*, ValueBase*>::value, int>::type
|
||||
= 0>
|
||||
ContextValue(std::unique_ptr<DerivedFromValueBase>&& p) noexcept
|
||||
: m_contextValueType(ContextValueType::UniquePtr), m_p(std::move(p))
|
||||
{
|
||||
}
|
||||
|
||||
ContextValue(ContextValue&& other) noexcept : m_contextValueType(other.m_contextValueType)
|
||||
{
|
||||
switch (m_contextValueType)
|
||||
{
|
||||
case ContextValueType::Bool:
|
||||
m_b = other.m_b;
|
||||
break;
|
||||
case ContextValueType::Int:
|
||||
m_i = other.m_i;
|
||||
break;
|
||||
case ContextValueType::StdString:
|
||||
::new (&m_s) std::string(std::move(other.m_s));
|
||||
break;
|
||||
case ContextValueType::UniquePtr:
|
||||
::new (&m_p) std::unique_ptr<ValueBase>(std::move(other.m_p));
|
||||
break;
|
||||
case ContextValueType::Undefined:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~ContextValue()
|
||||
{
|
||||
switch (m_contextValueType)
|
||||
{
|
||||
case ContextValueType::StdString:
|
||||
m_s.~basic_string();
|
||||
break;
|
||||
case ContextValueType::UniquePtr:
|
||||
m_p.~unique_ptr<ValueBase>();
|
||||
break;
|
||||
case ContextValueType::Bool:
|
||||
case ContextValueType::Int:
|
||||
case ContextValueType::Undefined:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ContextValue& operator=(const ContextValue& other) = delete;
|
||||
|
||||
template <class ExpectedType> const ExpectedType& Get() const noexcept;
|
||||
|
||||
ContextValueType Alternative() const noexcept { return m_contextValueType; }
|
||||
};
|
||||
|
||||
template <> inline const bool& ContextValue::Get() const noexcept
|
||||
{
|
||||
if (m_contextValueType != ContextValueType::Bool)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return m_b;
|
||||
}
|
||||
|
||||
template <> inline const int& ContextValue::Get() const noexcept
|
||||
{
|
||||
if (m_contextValueType != ContextValueType::Int)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return m_i;
|
||||
}
|
||||
|
||||
template <> inline const std::string& ContextValue::Get() const noexcept
|
||||
{
|
||||
if (m_contextValueType != ContextValueType::StdString)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return m_s;
|
||||
}
|
||||
|
||||
template <> inline const std::unique_ptr<ValueBase>& ContextValue::Get() const noexcept
|
||||
{
|
||||
if (m_contextValueType != ContextValueType::UniquePtr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return m_p;
|
||||
}
|
||||
|
||||
class Context {
|
||||
public:
|
||||
using time_point = std::chrono::system_clock::time_point;
|
||||
|
||||
private:
|
||||
struct ContextSharedState
|
||||
{
|
||||
std::shared_ptr<ContextSharedState> Parent;
|
||||
time_point CancelAt;
|
||||
std::string Key;
|
||||
ContextValue Value;
|
||||
|
||||
explicit ContextSharedState() : CancelAt(time_point::max()) {}
|
||||
|
||||
explicit ContextSharedState(
|
||||
const std::shared_ptr<ContextSharedState>& parent,
|
||||
time_point cancelAt,
|
||||
const std::string& key,
|
||||
ContextValue&& value)
|
||||
: Parent(parent), CancelAt(cancelAt), Key(key), Value(std::move(value))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<ContextSharedState> m_contextSharedState;
|
||||
|
||||
explicit Context(std::shared_ptr<ContextSharedState> impl)
|
||||
: m_contextSharedState(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Context() : m_contextSharedState(std::make_shared<ContextSharedState>()) {}
|
||||
|
||||
Context& operator=(const Context&) = default;
|
||||
|
||||
Context WithDeadline(time_point cancelWhen)
|
||||
{
|
||||
return Context{std::make_shared<ContextSharedState>(
|
||||
m_contextSharedState, cancelWhen, std::string(), ContextValue{})};
|
||||
}
|
||||
|
||||
Context WithValue(const std::string& key, ContextValue&& value)
|
||||
{
|
||||
return Context{std::make_shared<ContextSharedState>(
|
||||
m_contextSharedState, time_point::max(), key, std::move(value))};
|
||||
}
|
||||
|
||||
time_point CancelWhen();
|
||||
|
||||
const ContextValue& operator[](const std::string& key)
|
||||
{
|
||||
if (!key.empty())
|
||||
{
|
||||
for (auto ptr = m_contextSharedState; ptr; ptr = ptr->Parent)
|
||||
{
|
||||
if (ptr->Key == key)
|
||||
{
|
||||
return ptr->Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ContextValue empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
void Cancel() { m_contextSharedState->CancelAt = time_point::min(); }
|
||||
};
|
||||
|
||||
}} // namespace Azure::Core
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "azure.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@ -15,10 +17,7 @@ namespace Azure { namespace Core { namespace Credentials {
|
||||
}
|
||||
|
||||
class Credential {
|
||||
virtual void SetScopes(std::string const& scopes)
|
||||
{
|
||||
(void)scopes;
|
||||
}
|
||||
virtual void SetScopes(std::string const& scopes) { AZURE_UNREFERENCED_PARAMETER(scopes); }
|
||||
|
||||
public:
|
||||
class Internal;
|
||||
@ -55,9 +54,7 @@ namespace Azure { namespace Core { namespace Credentials {
|
||||
|
||||
protected:
|
||||
TokenCredential() = default;
|
||||
TokenCredential(TokenCredential const& other, int) : Credential(other)
|
||||
{
|
||||
}
|
||||
TokenCredential(TokenCredential const& other, int) : Credential(other) {}
|
||||
|
||||
void Init(TokenCredential const& other);
|
||||
virtual std::string GetToken();
|
||||
|
||||
90
sdk/core/azure-core/inc/http/curl/curl.hpp
Normal file
90
sdk/core/azure-core/inc/http/curl/curl.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "http/http.hpp"
|
||||
#include "http/policy.hpp"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
class CurlTransport : public HttpTransport {
|
||||
private:
|
||||
CurlTransport(const CurlTransport&) = delete;
|
||||
CurlTransport& operator=(const CurlTransport&) = delete;
|
||||
|
||||
// for every client instance, create a default response
|
||||
std::unique_ptr<Azure::Core::Http::Response> m_response;
|
||||
bool m_firstHeader;
|
||||
|
||||
CURL* m_pCurl;
|
||||
|
||||
static size_t WriteHeadersCallBack(void* contents, size_t size, size_t nmemb, void* userp);
|
||||
static size_t WriteBodyCallBack(void* contents, size_t size, size_t nmemb, void* userp);
|
||||
|
||||
// setHeaders()
|
||||
CURLcode SetUrl(Request& request)
|
||||
{
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_URL, request.GetEncodedUrl().c_str());
|
||||
}
|
||||
|
||||
CURLcode SetHeaders(Request& request)
|
||||
{
|
||||
auto headers = request.GetHeaders();
|
||||
if (headers.size() == 0)
|
||||
{
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
// creates a slist for bulding curl headers
|
||||
struct curl_slist* headerList = NULL;
|
||||
|
||||
// insert headers
|
||||
for (auto header : headers)
|
||||
{
|
||||
// TODO: check result is not null or trow
|
||||
headerList = curl_slist_append(headerList, (header.first + ":" + header.second).c_str());
|
||||
}
|
||||
|
||||
// set all headers from slist
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, headerList);
|
||||
}
|
||||
|
||||
CURLcode SetWriteResponse()
|
||||
{
|
||||
auto settingUp = curl_easy_setopt(m_pCurl, CURLOPT_HEADERFUNCTION, WriteHeadersCallBack);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
settingUp = curl_easy_setopt(m_pCurl, CURLOPT_HEADERDATA, (void*)this);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
// TODO: set up cache size. user should be able to set it up
|
||||
settingUp = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, WriteBodyCallBack);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, (void*)this);
|
||||
}
|
||||
|
||||
CURLcode Perform(Context& context, Request& request);
|
||||
|
||||
public:
|
||||
CurlTransport();
|
||||
~CurlTransport();
|
||||
|
||||
std::unique_ptr<Response> Send(Context& context, Request& request) override;
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Core::Http
|
||||
@ -12,6 +12,13 @@
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
enum class TransportKind
|
||||
{
|
||||
//TODO move this to Factory
|
||||
Curl,
|
||||
WinHttp
|
||||
};
|
||||
|
||||
// BodyStream is used to read data to/from a service
|
||||
class BodyStream {
|
||||
public:
|
||||
@ -306,8 +313,4 @@ namespace Azure { namespace Core { namespace Http {
|
||||
Http::BodyStream* GetBodyStream() { return m_bodyStream; }
|
||||
};
|
||||
|
||||
class Client {
|
||||
public:
|
||||
static std::unique_ptr<Response> Send(Request& request);
|
||||
};
|
||||
}}} // namespace Azure::Core::Http
|
||||
|
||||
49
sdk/core/azure-core/inc/http/pipeline.hpp
Normal file
49
sdk/core/azure-core/inc/http/pipeline.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "context.hpp"
|
||||
#include "http.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
class HttpPipeline {
|
||||
protected:
|
||||
std::vector<std::unique_ptr<HttpPolicy>> m_policies;
|
||||
|
||||
public:
|
||||
HttpPipeline(std::vector<std::unique_ptr<HttpPolicy>>& policies)
|
||||
{
|
||||
m_policies.reserve(policies.size());
|
||||
for (auto&& policy : policies)
|
||||
{
|
||||
m_policies.emplace_back(policy->Clone());
|
||||
}
|
||||
}
|
||||
|
||||
HttpPipeline(const HttpPipeline& other)
|
||||
{
|
||||
m_policies.reserve(other.m_policies.size());
|
||||
for (auto&& policy : m_policies)
|
||||
{
|
||||
m_policies.emplace_back(policy->Clone());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the pipeline
|
||||
* @param ctx A cancellation token. Can also be used to provide overrides to individual policies
|
||||
* @param request The request to be processed
|
||||
* @return unique_ptr<Response>
|
||||
*/
|
||||
std::unique_ptr<Response> Send(Context& ctx, Request& request) const
|
||||
{
|
||||
return m_policies[0]->Send(ctx, request, NextHttpPolicy(0, &m_policies));
|
||||
}
|
||||
};
|
||||
}}} // namespace Azure::Core::Http
|
||||
112
sdk/core/azure-core/inc/http/policy.hpp
Normal file
112
sdk/core/azure-core/inc/http/policy.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "azure.hpp"
|
||||
#include "context.hpp"
|
||||
#include "http.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
class NextHttpPolicy;
|
||||
|
||||
class HttpPolicy {
|
||||
public:
|
||||
// If we get a response that goes up the stack
|
||||
// Any errors in the pipeline throws an exception
|
||||
// At the top of the pipeline we might want to turn certain responses into exceptions
|
||||
virtual std::unique_ptr<Response> Send(
|
||||
Context& context,
|
||||
Request& request,
|
||||
NextHttpPolicy policy) const = 0;
|
||||
virtual ~HttpPolicy() {}
|
||||
virtual HttpPolicy* Clone() const = 0;
|
||||
|
||||
protected:
|
||||
HttpPolicy() = default;
|
||||
HttpPolicy(const HttpPolicy& other) = default;
|
||||
HttpPolicy(HttpPolicy&& other) = default;
|
||||
HttpPolicy& operator=(const HttpPolicy& other) = default;
|
||||
};
|
||||
|
||||
class NextHttpPolicy {
|
||||
const std::size_t m_index;
|
||||
const std::vector<std::unique_ptr<HttpPolicy>>* m_policies;
|
||||
|
||||
public:
|
||||
explicit NextHttpPolicy(
|
||||
std::size_t index,
|
||||
const std::vector<std::unique_ptr<HttpPolicy>>* policies)
|
||||
: m_index(index), m_policies(policies)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Response> Send(Context& ctx, Request& req);
|
||||
};
|
||||
|
||||
class TransportPolicy : public HttpPolicy {
|
||||
private:
|
||||
std::shared_ptr<HttpTransport> m_transport;
|
||||
|
||||
public:
|
||||
explicit TransportPolicy(std::shared_ptr<HttpTransport> transport)
|
||||
: m_transport(std::move(transport))
|
||||
{
|
||||
}
|
||||
|
||||
HttpPolicy* Clone() const override { return new TransportPolicy(m_transport); }
|
||||
|
||||
std::unique_ptr<Response> Send(Context& ctx, Request& request, NextHttpPolicy nextHttpPolicy)
|
||||
const override
|
||||
{
|
||||
AZURE_UNREFERENCED_PARAMETER(nextHttpPolicy);
|
||||
/**
|
||||
* The transport policy is always the last policy.
|
||||
* Call the transport and return
|
||||
*/
|
||||
return m_transport->Send(ctx, request);
|
||||
}
|
||||
};
|
||||
|
||||
struct RetryOptions
|
||||
{
|
||||
int16_t MaxRetries = 5;
|
||||
int32_t RetryDelayMsec = 500;
|
||||
};
|
||||
|
||||
class RetryPolicy : public HttpPolicy {
|
||||
private:
|
||||
RetryOptions m_retryOptions;
|
||||
|
||||
public:
|
||||
explicit RetryPolicy(RetryOptions options) : m_retryOptions(options) {}
|
||||
|
||||
HttpPolicy* Clone() const override { return new RetryPolicy(m_retryOptions); }
|
||||
|
||||
std::unique_ptr<Response> Send(Context& ctx, Request& request, NextHttpPolicy nextHttpPolicy)
|
||||
const override
|
||||
{
|
||||
// Do real work here
|
||||
// nextPolicy->Process(ctx, message, )
|
||||
return nextHttpPolicy.Send(ctx, request);
|
||||
}
|
||||
};
|
||||
|
||||
class RequestIdPolicy : public HttpPolicy {
|
||||
|
||||
public:
|
||||
explicit RequestIdPolicy() {}
|
||||
|
||||
HttpPolicy* Clone() const override { return new RequestIdPolicy(); }
|
||||
|
||||
std::unique_ptr<Response> Send(Context& ctx, Request& request, NextHttpPolicy nextHttpPolicy)
|
||||
const override
|
||||
{
|
||||
// Do real work here
|
||||
return nextHttpPolicy.Send(ctx, request);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Core::Http
|
||||
28
sdk/core/azure-core/inc/http/transport.hpp
Normal file
28
sdk/core/azure-core/inc/http/transport.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "context.hpp"
|
||||
#include "http.hpp"
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
class HttpTransport {
|
||||
public:
|
||||
// If we get a response that goes up the stack
|
||||
// Any errors in the pipeline throws an exception
|
||||
// At the top of the pipeline we might want to turn certain responses into exceptions
|
||||
|
||||
//TODO - Should this be const
|
||||
virtual std::unique_ptr<Response> Send(Context& context, Request& request) = 0;
|
||||
virtual ~HttpTransport() {}
|
||||
|
||||
protected:
|
||||
HttpTransport() = default;
|
||||
HttpTransport(const HttpTransport& other) = default;
|
||||
HttpTransport(HttpTransport&& other) = default;
|
||||
HttpTransport& operator=(const HttpTransport& other) = default;
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Core::Http
|
||||
26
sdk/core/azure-core/inc/http/winhttp/win_http_client.hpp
Normal file
26
sdk/core/azure-core/inc/http/winhttp/win_http_client.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "http/http.hpp"
|
||||
#include "http/policy.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
class WinHttpTansport : public HttpTransport {
|
||||
private:
|
||||
|
||||
public:
|
||||
WinHttpTansport();
|
||||
~WinHttpTansport();
|
||||
|
||||
virtual std::unique_ptr<Response> Send(Context& context, Request& request) ;
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Core::Http
|
||||
27
sdk/core/azure-core/src/context.cpp
Normal file
27
sdk/core/azure-core/src/context.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <context.hpp>
|
||||
|
||||
using namespace Azure::Core;
|
||||
using time_point = std::chrono::system_clock::time_point;
|
||||
|
||||
Context& GetApplicationContext()
|
||||
{
|
||||
static Context ctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
time_point Context::CancelWhen()
|
||||
{
|
||||
auto result = time_point::max();
|
||||
for (auto ptr = m_contextSharedState; ptr; ptr = ptr->Parent)
|
||||
{
|
||||
if (result > ptr->CancelAt)
|
||||
{
|
||||
result = ptr->CancelAt;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -98,8 +98,8 @@ void ClientSecretCredential::RefreshToken(
|
||||
std::chrono::system_clock::time_point& newExpiration)
|
||||
{
|
||||
// TODO: get token using scopes, tenantId, clientId, and clientSecretId.
|
||||
(void)newTokenString;
|
||||
(void)newExpiration;
|
||||
AZURE_UNREFERENCED_PARAMETER(newTokenString);
|
||||
AZURE_UNREFERENCED_PARAMETER(newExpiration);
|
||||
}
|
||||
|
||||
ClientSecretCredential::ClientSecretCredential(
|
||||
|
||||
@ -1,52 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <curl_client.hpp>
|
||||
#include <http/http.hpp>
|
||||
#include "azure.hpp"
|
||||
#include "http/curl/curl.hpp"
|
||||
#include "http/http.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace std;
|
||||
|
||||
std::unique_ptr<Response> CurlClient::Send()
|
||||
CurlTransport::CurlTransport() : HttpTransport() { m_pCurl = curl_easy_init(); }
|
||||
|
||||
CurlTransport::~CurlTransport() { curl_easy_cleanup(m_pCurl); }
|
||||
|
||||
std::unique_ptr<Response> CurlTransport::Send(Context& context, Request& request)
|
||||
{
|
||||
auto performing = Perform();
|
||||
auto performing = Perform(context, request);
|
||||
|
||||
if (performing != CURLE_OK)
|
||||
{
|
||||
switch (performing)
|
||||
{
|
||||
case CURLE_COULDNT_RESOLVE_HOST:
|
||||
{
|
||||
case CURLE_COULDNT_RESOLVE_HOST: {
|
||||
throw Azure::Core::Http::CouldNotResolveHostException();
|
||||
}
|
||||
case CURLE_WRITE_ERROR:
|
||||
{
|
||||
case CURLE_WRITE_ERROR: {
|
||||
throw Azure::Core::Http::ErrorWhileWrittingResponse();
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
throw Azure::Core::Http::TransportException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return move(this->m_response);
|
||||
return std::move(m_response);
|
||||
}
|
||||
|
||||
CURLcode CurlClient::Perform()
|
||||
CURLcode CurlTransport::Perform(Context& context, Request& request)
|
||||
{
|
||||
AZURE_UNREFERENCED_PARAMETER(context);
|
||||
|
||||
m_firstHeader = true;
|
||||
|
||||
auto settingUp = SetUrl();
|
||||
auto settingUp = SetUrl(request);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
|
||||
settingUp = SetHeaders();
|
||||
settingUp = SetHeaders(request);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
@ -83,7 +82,7 @@ static std::unique_ptr<Response> ParseAndSetFirstHeader(std::string const& heade
|
||||
// So this memory gets delegated outside Curl Transport as a shared ptr so memory will be
|
||||
// eventually released
|
||||
return std::make_unique<Response>(
|
||||
majorVersion, minorVersion, HttpStatusCode(statusCode), reasonPhrase);
|
||||
(uint16_t)majorVersion, (uint16_t)minorVersion, HttpStatusCode(statusCode), reasonPhrase);
|
||||
}
|
||||
|
||||
static void ParseHeader(std::string const& header, std::unique_ptr<Response>& response)
|
||||
@ -110,13 +109,13 @@ static void ParseHeader(std::string const& header, std::unique_ptr<Response>& re
|
||||
}
|
||||
|
||||
// Callback function for curl. This is called for every header that curl get from network
|
||||
size_t CurlClient::WriteHeadersCallBack(void* contents, size_t size, size_t nmemb, void* userp)
|
||||
size_t CurlTransport::WriteHeadersCallBack(void* contents, size_t size, size_t nmemb, void* userp)
|
||||
{
|
||||
// No need to check for overflow, Curl already allocated this size internally for contents
|
||||
size_t const expected_size = size * nmemb;
|
||||
|
||||
// cast client
|
||||
CurlClient* client = static_cast<CurlClient*>(userp);
|
||||
CurlTransport* client = static_cast<CurlTransport*>(userp);
|
||||
// convert response to standard string
|
||||
std::string const& response = std::string((char*)contents, expected_size);
|
||||
|
||||
@ -140,13 +139,13 @@ size_t CurlClient::WriteHeadersCallBack(void* contents, size_t size, size_t nmem
|
||||
|
||||
// callback function for libcurl. It would be called as many times as need to ready a body from
|
||||
// network
|
||||
size_t CurlClient::WriteBodyCallBack(void* contents, size_t size, size_t nmemb, void* userp)
|
||||
size_t CurlTransport::WriteBodyCallBack(void* contents, size_t size, size_t nmemb, void* userp)
|
||||
{
|
||||
// No need to check for overflow, Curl already allocated this size internally for contents
|
||||
size_t const expected_size = size * nmemb;
|
||||
|
||||
// cast client
|
||||
CurlClient* client = static_cast<CurlClient*>(userp);
|
||||
CurlTransport* client = static_cast<CurlTransport*>(userp);
|
||||
|
||||
if (client->m_response != nullptr) // only if a response has been created
|
||||
{
|
||||
21
sdk/core/azure-core/src/http/policy.cpp
Normal file
21
sdk/core/azure-core/src/http/policy.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include <http/policy.hpp>
|
||||
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
std::unique_ptr<Response> NextHttpPolicy::Send(Context& ctx, Request& req)
|
||||
{
|
||||
if (m_policies == nullptr)
|
||||
throw;
|
||||
|
||||
if (m_index == m_policies->size() - 1)
|
||||
{
|
||||
//All the policies have run without running a transport policy
|
||||
throw;
|
||||
}
|
||||
|
||||
return (*m_policies)[m_index + 1]->Send(ctx, req, NextHttpPolicy{m_index + 1, m_policies});
|
||||
}
|
||||
26
sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Normal file
26
sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure.hpp"
|
||||
#include "http/http.hpp"
|
||||
#include "http/winhttp/win_http_client.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
WinHttpTansport::WinHttpTansport() :
|
||||
HttpTransport()
|
||||
{
|
||||
}
|
||||
|
||||
WinHttpTansport::~WinHttpTansport() {}
|
||||
|
||||
|
||||
std::unique_ptr<Response> WinHttpTansport::Send(Context& context, Request& request)
|
||||
{
|
||||
AZURE_UNREFERENCED_PARAMETER(context);
|
||||
AZURE_UNREFERENCED_PARAMETER(request);
|
||||
|
||||
throw;
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
# 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()
|
||||
@ -1,21 +0,0 @@
|
||||
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.
|
||||
@ -1,86 +0,0 @@
|
||||
// Copyright (c) `Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <http/http.hpp>
|
||||
#include <memory>
|
||||
|
||||
class CurlClient {
|
||||
private:
|
||||
CurlClient(const CurlClient&) = delete;
|
||||
CurlClient& operator=(const CurlClient&) = delete;
|
||||
|
||||
Azure::Core::Http::Request& m_request;
|
||||
// for every client instance, create a default response
|
||||
std::unique_ptr<Azure::Core::Http::Response> m_response;
|
||||
bool m_firstHeader;
|
||||
|
||||
CURL* m_pCurl;
|
||||
|
||||
static size_t WriteHeadersCallBack(void* contents, size_t size, size_t nmemb, void* userp);
|
||||
static size_t WriteBodyCallBack(void* contents, size_t size, size_t nmemb, void* userp);
|
||||
|
||||
// setHeaders()
|
||||
CURLcode SetUrl()
|
||||
{
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_URL, this->m_request.GetEncodedUrl().c_str());
|
||||
}
|
||||
|
||||
CURLcode SetHeaders()
|
||||
{
|
||||
auto headers = this->m_request.GetHeaders();
|
||||
if (headers.size() == 0)
|
||||
{
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
// creates a slist for bulding curl headers
|
||||
struct curl_slist* headerList = NULL;
|
||||
|
||||
// insert headers
|
||||
for (auto header : headers)
|
||||
{
|
||||
// TODO: check result is not null or trow
|
||||
headerList = curl_slist_append(headerList, (header.first + ":" + header.second).c_str());
|
||||
}
|
||||
|
||||
// set all headers from slist
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, headerList);
|
||||
}
|
||||
|
||||
CURLcode SetWriteResponse()
|
||||
{
|
||||
auto settingUp = curl_easy_setopt(m_pCurl, CURLOPT_HEADERFUNCTION, WriteHeadersCallBack);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
settingUp = curl_easy_setopt(m_pCurl, CURLOPT_HEADERDATA, (void*)this);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
// TODO: set up cache size. user should be able to set it up
|
||||
settingUp = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, WriteBodyCallBack);
|
||||
if (settingUp != CURLE_OK)
|
||||
{
|
||||
return settingUp;
|
||||
}
|
||||
|
||||
return curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, (void*)this);
|
||||
}
|
||||
|
||||
CURLcode Perform();
|
||||
|
||||
public:
|
||||
CurlClient(Azure::Core::Http::Request& request) : m_request(request)
|
||||
{
|
||||
m_pCurl = curl_easy_init();
|
||||
}
|
||||
// client curl struct on destruct
|
||||
~CurlClient() { curl_easy_cleanup(m_pCurl); }
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::Response> Send();
|
||||
};
|
||||
@ -1,15 +0,0 @@
|
||||
// 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
|
||||
std::unique_ptr<Response> Client::Send(Request& request)
|
||||
{
|
||||
CurlClient client(request);
|
||||
// return request response
|
||||
return client.Send();
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
# 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()
|
||||
@ -1,21 +0,0 @@
|
||||
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.
|
||||
@ -1,14 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include <memory>
|
||||
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
// implement send method
|
||||
std::unique_ptr<Response> Client::Send(Request& request)
|
||||
{
|
||||
(void)request;
|
||||
throw;
|
||||
}
|
||||
@ -15,6 +15,6 @@ add_executable (
|
||||
src/azure_core_with_curl
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core azure-transport-curl)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE azure-core)
|
||||
|
||||
endif()
|
||||
|
||||
@ -7,10 +7,14 @@
|
||||
*/
|
||||
|
||||
#include <http/http.hpp>
|
||||
#include "http/pipeline.hpp"
|
||||
#include <http/curl/curl.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
using namespace Azure::Core;
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
@ -18,14 +22,29 @@ 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);
|
||||
request.AddHeader("one", "header");
|
||||
request.AddHeader("other", "header2");
|
||||
request.AddHeader("header", "value");
|
||||
|
||||
try
|
||||
{
|
||||
std::shared_ptr<Http::Response> response = Http::Client::Send(request);
|
||||
auto request = Http::Request(Http::HttpMethod::Get, host);
|
||||
request.AddHeader("one", "header");
|
||||
request.AddHeader("other", "header2");
|
||||
request.AddHeader("header", "value");
|
||||
|
||||
//Create the Transport
|
||||
std::shared_ptr<HttpTransport> transport = std::make_unique<CurlTransport>();
|
||||
|
||||
std::vector<std::unique_ptr<HttpPolicy>> policies;
|
||||
policies.push_back(std::make_unique<RequestIdPolicy>());
|
||||
|
||||
RetryOptions retryOptions;
|
||||
policies.push_back(std::make_unique<RetryPolicy>(retryOptions));
|
||||
|
||||
// Add the transport policy
|
||||
policies.push_back(std::make_unique<TransportPolicy>(std::move(transport)));
|
||||
|
||||
auto httpPipeline = Http::HttpPipeline(policies);
|
||||
|
||||
auto context = Context();
|
||||
std::shared_ptr<Http::Response> response = httpPipeline.Send(context, request);
|
||||
|
||||
if (response == nullptr)
|
||||
{
|
||||
@ -34,7 +53,7 @@ int main()
|
||||
}
|
||||
|
||||
cout << static_cast<typename std::underlying_type<Http::HttpStatusCode>::type>(
|
||||
response->GetStatusCode())
|
||||
response->GetStatusCode())
|
||||
<< endl;
|
||||
cout << response->GetReasonPhrase() << endl;
|
||||
cout << "headers:" << endl;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user