Fix namespace case and file formating (#98)
This commit is contained in:
parent
6b7b428e71
commit
5350d1dbf8
@ -1,23 +1,42 @@
|
||||
BasedOnStyle: LLVM
|
||||
ColumnLimit: 100
|
||||
UseTab: Never
|
||||
TabWidth: 2
|
||||
IndentWidth: 2
|
||||
IncludeBlocks: Preserve
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
Language: Cpp
|
||||
BasedOnStyle: Microsoft
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
PenaltyReturnTypeOnItsOwnLine: 300
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
IndentCaseLabels: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Allman
|
||||
Cpp11BracedListStyle: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
ColumnLimit: 100
|
||||
CompactNamespaces: true
|
||||
Cpp11BracedListStyle: true
|
||||
FixNamespaceComments: true
|
||||
IndentWidth: 2
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseLabels: true
|
||||
NamespaceIndentation: Inner
|
||||
PointerAlignment: Left
|
||||
PenaltyReturnTypeOnItsOwnLine: 300
|
||||
TabWidth: 2
|
||||
UseTab: Never
|
||||
|
||||
@ -18,4 +18,4 @@ add_library (
|
||||
target_include_directories (azure-core 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 azure-core)
|
||||
|
||||
@ -5,10 +5,6 @@
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace Azure { namespace Core {
|
||||
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
}} // namespace Azure::Core
|
||||
|
||||
@ -8,91 +8,85 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace credentials
|
||||
{
|
||||
namespace Azure { namespace Core { namespace Credentials {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class CredentialTest;
|
||||
}
|
||||
namespace Details {
|
||||
class CredentialTest;
|
||||
}
|
||||
|
||||
class Credential
|
||||
{
|
||||
virtual void SetScopes(std::string const& scopes) { (void)scopes; }
|
||||
class Credential {
|
||||
virtual void SetScopes(std::string const& scopes)
|
||||
{
|
||||
(void)scopes;
|
||||
}
|
||||
|
||||
public:
|
||||
class Internal;
|
||||
virtual ~Credential() noexcept = default;
|
||||
public:
|
||||
class Internal;
|
||||
virtual ~Credential() noexcept = default;
|
||||
|
||||
protected:
|
||||
Credential() = default;
|
||||
protected:
|
||||
Credential() = default;
|
||||
|
||||
Credential(Credential const& other) = default;
|
||||
Credential& operator=(Credential const& other) = default;
|
||||
};
|
||||
Credential(Credential const& other) = default;
|
||||
Credential& operator=(Credential const& other) = default;
|
||||
};
|
||||
|
||||
class TokenCredential : public Credential
|
||||
{
|
||||
friend class detail::CredentialTest;
|
||||
class Token;
|
||||
class TokenCredential : public Credential {
|
||||
friend class Details::CredentialTest;
|
||||
class Token;
|
||||
|
||||
std::shared_ptr<Token> m_token;
|
||||
std::mutex m_mutex;
|
||||
std::shared_ptr<Token> m_token;
|
||||
std::mutex m_mutex;
|
||||
|
||||
std::string UpdateTokenNonThreadSafe(Token& token);
|
||||
std::string UpdateTokenNonThreadSafe(Token& token);
|
||||
|
||||
virtual bool IsTokenExpired(std::chrono::system_clock::time_point const& tokenExpiration) const;
|
||||
virtual bool IsTokenExpired(std::chrono::system_clock::time_point const& tokenExpiration) const;
|
||||
|
||||
virtual void RefreshToken(
|
||||
std::string& newTokenString,
|
||||
std::chrono::system_clock::time_point& newExpiration)
|
||||
= 0;
|
||||
virtual void RefreshToken(
|
||||
std::string& newTokenString,
|
||||
std::chrono::system_clock::time_point& newExpiration)
|
||||
= 0;
|
||||
|
||||
public:
|
||||
class Internal;
|
||||
public:
|
||||
class Internal;
|
||||
|
||||
TokenCredential(TokenCredential const& other);
|
||||
TokenCredential& operator=(TokenCredential const& other);
|
||||
TokenCredential(TokenCredential const& other);
|
||||
TokenCredential& operator=(TokenCredential const& other);
|
||||
|
||||
protected:
|
||||
TokenCredential() = default;
|
||||
TokenCredential(TokenCredential const& other, int) : Credential(other) {}
|
||||
protected:
|
||||
TokenCredential() = default;
|
||||
TokenCredential(TokenCredential const& other, int) : Credential(other)
|
||||
{
|
||||
}
|
||||
|
||||
void Init(TokenCredential const& other);
|
||||
virtual std::string GetToken();
|
||||
void ResetToken();
|
||||
};
|
||||
void Init(TokenCredential const& other);
|
||||
virtual std::string GetToken();
|
||||
void ResetToken();
|
||||
};
|
||||
|
||||
class ClientSecretCredential : public TokenCredential
|
||||
{
|
||||
friend class detail::CredentialTest;
|
||||
class ClientSecret;
|
||||
class ClientSecretCredential : public TokenCredential {
|
||||
friend class Details::CredentialTest;
|
||||
class ClientSecret;
|
||||
|
||||
std::shared_ptr<ClientSecret> m_clientSecret;
|
||||
std::mutex m_mutex;
|
||||
std::shared_ptr<ClientSecret> m_clientSecret;
|
||||
std::mutex m_mutex;
|
||||
|
||||
void SetScopes(std::string const& scopes) override;
|
||||
void SetScopes(std::string const& scopes) override;
|
||||
|
||||
std::string GetToken() override;
|
||||
std::string GetToken() override;
|
||||
|
||||
void RefreshToken(
|
||||
std::string& newTokenString,
|
||||
std::chrono::system_clock::time_point& newExpiration) override;
|
||||
void RefreshToken(
|
||||
std::string& newTokenString,
|
||||
std::chrono::system_clock::time_point& newExpiration) override;
|
||||
|
||||
public:
|
||||
ClientSecretCredential(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret);
|
||||
public:
|
||||
ClientSecretCredential(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret);
|
||||
|
||||
ClientSecretCredential(ClientSecretCredential const& other);
|
||||
ClientSecretCredential& operator=(ClientSecretCredential const& other);
|
||||
};
|
||||
ClientSecretCredential(ClientSecretCredential const& other);
|
||||
ClientSecretCredential& operator=(ClientSecretCredential const& other);
|
||||
};
|
||||
|
||||
} // namespace credentials
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
}}} // namespace Azure::Core::Credentials
|
||||
|
||||
@ -12,231 +12,229 @@
|
||||
|
||||
#include <internal/contract.hpp>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace Azure { namespace Core { namespace Http {
|
||||
|
||||
// BodyStream is used to read data to/from a service
|
||||
class BodyStream
|
||||
{
|
||||
public:
|
||||
static BodyStream* null;
|
||||
// BodyStream is used to read data to/from a service
|
||||
class BodyStream {
|
||||
public:
|
||||
static BodyStream* null;
|
||||
|
||||
// Returns the length of the data; used with the HTTP Content-Length header
|
||||
virtual uint64_t Length() = 0;
|
||||
// Returns the length of the data; used with the HTTP Content-Length header
|
||||
virtual uint64_t Length() = 0;
|
||||
|
||||
// Resets the stream back to the beginning (for retries)
|
||||
// Derived classes that send data in an HTTP request MUST override this and implement it properly.
|
||||
virtual void Rewind()
|
||||
{
|
||||
throw "Not Implemented"; // TODO: Replace with best practice as defined by guideline
|
||||
// Resets the stream back to the beginning (for retries)
|
||||
// Derived classes that send data in an HTTP request MUST override this and implement it
|
||||
// properly.
|
||||
virtual void Rewind()
|
||||
{
|
||||
throw "Not Implemented"; // TODO: Replace with best practice as defined by guideline
|
||||
};
|
||||
|
||||
// Reads more data; EOF if return < count; throws if error/canceled
|
||||
virtual uint64_t Read(/*Context& context, */ uint8_t* buffer, uint64_t offset, uint64_t count)
|
||||
= 0;
|
||||
|
||||
// Closes the stream; typically called after all data read or if an error occurs.
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
// Reads more data; EOF if return < count; throws if error/canceled
|
||||
virtual uint64_t Read(/*Context& context, */ uint8_t* buffer, uint64_t offset, uint64_t count)
|
||||
= 0;
|
||||
class BodyBuffer {
|
||||
public:
|
||||
static BodyBuffer* null;
|
||||
|
||||
// Closes the stream; typically called after all data read or if an error occurs.
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
class BodyBuffer
|
||||
{
|
||||
public:
|
||||
static BodyBuffer* null;
|
||||
|
||||
uint8_t const* _bodyBuffer;
|
||||
uint64_t _bodyBufferSize;
|
||||
BodyBuffer(uint8_t const* bodyBuffer, uint64_t bodyBufferSize)
|
||||
: _bodyBuffer(bodyBuffer), _bodyBufferSize(bodyBufferSize)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
enum class HttpMethod
|
||||
{
|
||||
Get,
|
||||
Head,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
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())
|
||||
uint8_t const* _bodyBuffer;
|
||||
uint64_t _bodyBufferSize;
|
||||
BodyBuffer(uint8_t const* bodyBuffer, uint64_t bodyBufferSize)
|
||||
: _bodyBuffer(bodyBuffer), _bodyBufferSize(bodyBufferSize)
|
||||
{
|
||||
return url; // not query parameters
|
||||
}
|
||||
};
|
||||
|
||||
enum class HttpMethod
|
||||
{
|
||||
Get,
|
||||
Head,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
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;
|
||||
}
|
||||
|
||||
auto position = firstPosition; // position of symbol ?
|
||||
while (position != url.end())
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
++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)
|
||||
|
||||
const auto firstPosition = std::find(url.begin(), url.end(), '?');
|
||||
if (firstPosition == url.end())
|
||||
{
|
||||
++valueStart; // skip = symbol
|
||||
return url; // not query parameters
|
||||
}
|
||||
|
||||
// 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)));
|
||||
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
|
||||
}
|
||||
|
||||
position = nextPosition;
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
{
|
||||
// TODO: parse url
|
||||
}
|
||||
|
||||
public:
|
||||
Request(HttpMethod httpMethod, std::string const& url)
|
||||
: Request(httpMethod, url, BodyStream::null, BodyBuffer::null)
|
||||
const char* what() const throw()
|
||||
{
|
||||
return "couldnt resolve host";
|
||||
}
|
||||
};
|
||||
struct ErrorWhileWrittingResponse : public std::exception
|
||||
{
|
||||
}
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyBuffer* bodyBuffer)
|
||||
: Request(httpMethod, url, BodyStream::null, bodyBuffer)
|
||||
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";
|
||||
}
|
||||
};
|
||||
|
||||
Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
|
||||
: Request(httpMethod, url, bodyStream, BodyBuffer::null)
|
||||
{
|
||||
}
|
||||
class Response {
|
||||
|
||||
// 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
|
||||
private:
|
||||
uint16_t m_statusCode;
|
||||
std::string m_reasonPhrase;
|
||||
std::map<std::string, std::string> m_headers;
|
||||
|
||||
// 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 can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
Http::BodyBuffer* m_bodyBuffer;
|
||||
Http::BodyStream* m_bodyStream;
|
||||
|
||||
/*
|
||||
* 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"; }
|
||||
};
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
class Response
|
||||
{
|
||||
public:
|
||||
Response(uint16_t statusCode, std::string const& reasonPhrase)
|
||||
: Response(statusCode, reasonPhrase, Http::BodyBuffer::null, Http::BodyStream::null)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t m_statusCode;
|
||||
std::string m_reasonPhrase;
|
||||
std::map<std::string, std::string> m_headers;
|
||||
// Methods used to build HTTP response
|
||||
void addHeader(std::string const& name, std::string const& value);
|
||||
void setBody(BodyBuffer* bodyBuffer);
|
||||
void setBody(BodyStream* bodyStream);
|
||||
|
||||
// Response can contain no body, or either of next bodies (_bodyBuffer plus size or bodyStream)
|
||||
http::BodyBuffer* m_bodyBuffer;
|
||||
http::BodyStream* m_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();
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
class Client {
|
||||
public:
|
||||
static Response send(Request& request);
|
||||
};
|
||||
|
||||
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
|
||||
}}} // namespace Azure::Core::Http
|
||||
|
||||
@ -10,67 +10,59 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace azure
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace credentials
|
||||
{
|
||||
namespace Azure { namespace Core { namespace Credentials {
|
||||
|
||||
class Credential::Internal
|
||||
{
|
||||
public:
|
||||
static void SetScopes(Credential& credential, std::string const& scopes)
|
||||
{
|
||||
credential.SetScopes(scopes);
|
||||
}
|
||||
};
|
||||
class Credential::Internal {
|
||||
public:
|
||||
static void SetScopes(Credential& credential, std::string const& scopes)
|
||||
{
|
||||
credential.SetScopes(scopes);
|
||||
}
|
||||
};
|
||||
|
||||
class TokenCredential::Token
|
||||
{
|
||||
friend class TokenCredential;
|
||||
friend class detail::CredentialTest;
|
||||
class TokenCredential::Token {
|
||||
friend class TokenCredential;
|
||||
friend class Details::CredentialTest;
|
||||
|
||||
std::string m_tokenString;
|
||||
std::chrono::system_clock::time_point m_expiresAt;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
std::string m_tokenString;
|
||||
std::chrono::system_clock::time_point m_expiresAt;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
class TokenCredential::Internal
|
||||
{
|
||||
public:
|
||||
static std::string GetToken(TokenCredential& credential) { return credential.GetToken(); }
|
||||
};
|
||||
class TokenCredential::Internal {
|
||||
public:
|
||||
static std::string GetToken(TokenCredential& credential)
|
||||
{
|
||||
return credential.GetToken();
|
||||
}
|
||||
};
|
||||
|
||||
class ClientSecretCredential::ClientSecret
|
||||
{
|
||||
friend class ClientSecretCredential;
|
||||
friend class detail::CredentialTest;
|
||||
class ClientSecretCredential::ClientSecret {
|
||||
friend class ClientSecretCredential;
|
||||
friend class Details::CredentialTest;
|
||||
|
||||
std::string m_tenantId;
|
||||
std::string m_clientId;
|
||||
std::string m_clientSecret;
|
||||
std::string m_scopes;
|
||||
std::string m_tenantId;
|
||||
std::string m_clientId;
|
||||
std::string m_clientSecret;
|
||||
std::string m_scopes;
|
||||
|
||||
public:
|
||||
ClientSecret(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret)
|
||||
: m_tenantId(tenantId), m_clientId(clientId), m_clientSecret(clientSecret)
|
||||
{
|
||||
}
|
||||
public:
|
||||
ClientSecret(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret)
|
||||
: m_tenantId(tenantId), m_clientId(clientId), m_clientSecret(clientSecret)
|
||||
{
|
||||
}
|
||||
|
||||
ClientSecret(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret,
|
||||
std::string const& scopes)
|
||||
: m_tenantId(tenantId), m_clientId(clientId), m_clientSecret(clientSecret), m_scopes(scopes)
|
||||
{
|
||||
}
|
||||
};
|
||||
ClientSecret(
|
||||
std::string const& tenantId,
|
||||
std::string const& clientId,
|
||||
std::string const& clientSecret,
|
||||
std::string const& scopes)
|
||||
: m_tenantId(tenantId), m_clientId(clientId), m_clientSecret(clientSecret), m_scopes(scopes)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace credentials
|
||||
} // namespace core
|
||||
} // namespace azure
|
||||
}}} // namespace Azure::Core::Credentials
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#include <credentials/credentials.hpp>
|
||||
#include <internal/credentials_internal.hpp>
|
||||
|
||||
using namespace azure::core::credentials;
|
||||
using namespace Azure::Core::Credentials;
|
||||
|
||||
std::string TokenCredential::UpdateTokenNonThreadSafe(Token& token)
|
||||
{
|
||||
@ -55,7 +55,8 @@ std::string TokenCredential::GetToken()
|
||||
|
||||
std::lock_guard<std::mutex> const tokenLock(this->m_token->m_mutex);
|
||||
Token& token = *this->m_token;
|
||||
return this->IsTokenExpired(token.m_expiresAt) ? UpdateTokenNonThreadSafe(token) : token.m_tokenString;
|
||||
return this->IsTokenExpired(token.m_expiresAt) ? UpdateTokenNonThreadSafe(token)
|
||||
: token.m_tokenString;
|
||||
}
|
||||
|
||||
void TokenCredential::ResetToken()
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
BodyStream* BodyStream::null = nullptr;
|
||||
BodyBuffer* BodyBuffer::null = nullptr;
|
||||
|
||||
@ -7,9 +7,12 @@
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
void Request::addPath(std::string const& path) { this->_url += "/" + path; }
|
||||
void Request::addPath(std::string const& path)
|
||||
{
|
||||
this->_url += "/" + path;
|
||||
}
|
||||
|
||||
void Request::addQueryParameter(std::string const& name, std::string const& value)
|
||||
{
|
||||
@ -43,7 +46,10 @@ void Request::startRetry()
|
||||
this->m_retryHeaders.clear();
|
||||
}
|
||||
|
||||
HttpMethod Request::getMethod() { return this->_method; }
|
||||
HttpMethod Request::getMethod()
|
||||
{
|
||||
return this->_method;
|
||||
}
|
||||
|
||||
std::string Request::getEncodedUrl()
|
||||
{
|
||||
@ -71,6 +77,12 @@ std::map<std::string, std::string> Request::getHeaders()
|
||||
return Request::mergeMaps(this->m_retryHeaders, this->m_headers);
|
||||
}
|
||||
|
||||
BodyStream* Request::getBodyStream() { return m_bodyStream; }
|
||||
BodyStream* Request::getBodyStream()
|
||||
{
|
||||
return m_bodyStream;
|
||||
}
|
||||
|
||||
BodyBuffer* Request::getBodyBuffer() { return m_bodyBuffer; }
|
||||
BodyBuffer* Request::getBodyBuffer()
|
||||
{
|
||||
return m_bodyBuffer;
|
||||
}
|
||||
|
||||
@ -7,14 +7,29 @@
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
uint16_t Response::getStatusCode() { return m_statusCode; }
|
||||
uint16_t Response::getStatusCode()
|
||||
{
|
||||
return m_statusCode;
|
||||
}
|
||||
|
||||
std::string const& Response::getReasonPhrase() { return m_reasonPhrase; }
|
||||
std::string const& Response::getReasonPhrase()
|
||||
{
|
||||
return m_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->m_headers;
|
||||
}
|
||||
|
||||
BodyStream* Response::getBodyStream() { return m_bodyStream; }
|
||||
BodyStream* Response::getBodyStream()
|
||||
{
|
||||
return m_bodyStream;
|
||||
}
|
||||
|
||||
BodyBuffer* Response::getBodyBuffer() { return m_bodyBuffer; }
|
||||
BodyBuffer* Response::getBodyBuffer()
|
||||
{
|
||||
return m_bodyBuffer;
|
||||
}
|
||||
|
||||
@ -9,33 +9,33 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace azure::core;
|
||||
using namespace Azure::Core;
|
||||
|
||||
TEST(Http_Request, getters)
|
||||
{
|
||||
http::HttpMethod httpMethod = http::HttpMethod::Get;
|
||||
Http::HttpMethod httpMethod = Http::HttpMethod::Get;
|
||||
std::string url = "http://test.url.com";
|
||||
http::Request req(httpMethod, url);
|
||||
Http::Request req(httpMethod, url);
|
||||
|
||||
// EXPECT_PRED works better than just EQ because it will print values in log
|
||||
EXPECT_PRED2(
|
||||
[](http::HttpMethod a, http::HttpMethod b) { return a == b; }, req.getMethod(), httpMethod);
|
||||
[](Http::HttpMethod a, Http::HttpMethod b) { return a == b; }, req.getMethod(), httpMethod);
|
||||
EXPECT_PRED2([](std::string a, std::string b) { return a == b; }, req.getEncodedUrl(), url);
|
||||
/* EXPECT_PRED2(
|
||||
[](std::string a, std::string b) { return a == b; },
|
||||
req.getBodyStream(),
|
||||
http::BodyStream::null);
|
||||
Http::BodyStream::null);
|
||||
EXPECT_PRED2(
|
||||
[](std::string a, std::string b) { return a == b; },
|
||||
req.getBodyBuffer(),
|
||||
http::BodyBuffer::null); */
|
||||
Http::BodyBuffer::null); */
|
||||
|
||||
uint8_t buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
auto bufferBody = http::BodyBuffer(buffer, sizeof(buffer));
|
||||
http::Request requestWithBody(httpMethod, url, &bufferBody);
|
||||
auto bufferBody = Http::BodyBuffer(buffer, sizeof(buffer));
|
||||
Http::Request requestWithBody(httpMethod, url, &bufferBody);
|
||||
|
||||
EXPECT_PRED2(
|
||||
[](http::HttpMethod a, http::HttpMethod b) { return a == b; },
|
||||
[](Http::HttpMethod a, Http::HttpMethod b) { return a == b; },
|
||||
requestWithBody.getMethod(),
|
||||
httpMethod);
|
||||
EXPECT_PRED2(
|
||||
@ -43,7 +43,7 @@ TEST(Http_Request, getters)
|
||||
/* EXPECT_PRED2(
|
||||
[](std::string a, std::string b) { return a == b; },
|
||||
requestWithBody.getBodyStream(),
|
||||
http::BodyStream::null); */
|
||||
Http::BodyStream::null); */
|
||||
|
||||
// body with buffer
|
||||
auto body = requestWithBody.getBodyBuffer();
|
||||
@ -90,9 +90,9 @@ TEST(Http_Request, getters)
|
||||
|
||||
TEST(Http_Request, query_parameter)
|
||||
{
|
||||
http::HttpMethod httpMethod = http::HttpMethod::Put;
|
||||
Http::HttpMethod httpMethod = Http::HttpMethod::Put;
|
||||
std::string url = "http://test.com";
|
||||
http::Request req(httpMethod, url);
|
||||
Http::Request req(httpMethod, url);
|
||||
|
||||
EXPECT_NO_THROW(req.addQueryParameter("query", "value"));
|
||||
EXPECT_PRED2(
|
||||
@ -101,7 +101,7 @@ TEST(Http_Request, query_parameter)
|
||||
url + "?query=value");
|
||||
|
||||
std::string url_with_query = "http://test.com?query=1";
|
||||
http::Request req_with_query(httpMethod, url_with_query);
|
||||
Http::Request req_with_query(httpMethod, url_with_query);
|
||||
|
||||
// ignore if adding same query parameter key that is already in url
|
||||
EXPECT_NO_THROW(req_with_query.addQueryParameter("query", "value"));
|
||||
@ -123,9 +123,9 @@ TEST(Http_Request, query_parameter)
|
||||
|
||||
TEST(Http_Request, add_path)
|
||||
{
|
||||
http::HttpMethod httpMethod = http::HttpMethod::Post;
|
||||
Http::HttpMethod httpMethod = Http::HttpMethod::Post;
|
||||
std::string url = "http://test.com";
|
||||
http::Request req(httpMethod, url);
|
||||
Http::Request req(httpMethod, url);
|
||||
|
||||
EXPECT_NO_THROW(req.addPath("path"));
|
||||
EXPECT_PRED2(
|
||||
@ -150,7 +150,7 @@ TEST(Http_Request, add_path)
|
||||
url + "/path/path2/path3?query=value");
|
||||
}
|
||||
|
||||
class azure::core::credentials::detail::CredentialTest : public ClientSecretCredential
|
||||
class Azure::Core::Credentials::Details::CredentialTest : public ClientSecretCredential
|
||||
{
|
||||
public:
|
||||
CredentialTest(
|
||||
@ -213,7 +213,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
std::string const clientId = "clientId";
|
||||
std::string const clientSecret = "clientSecret";
|
||||
|
||||
credentials::detail::CredentialTest clientSecretCredential(tenantId, clientId, clientSecret);
|
||||
Credentials::Details::CredentialTest clientSecretCredential(tenantId, clientId, clientSecret);
|
||||
|
||||
EXPECT_EQ(clientSecretCredential.GetTenantId(), tenantId);
|
||||
EXPECT_EQ(clientSecretCredential.GetClientId(), clientId);
|
||||
@ -233,7 +233,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
// Set scopes
|
||||
std::string const scopes = "scope";
|
||||
{
|
||||
credentials::Credential::Internal::SetScopes(clientSecretCredential, scopes);
|
||||
Credentials::Credential::Internal::SetScopes(clientSecretCredential, scopes);
|
||||
EXPECT_EQ(clientSecretCredential.IsTokenPtrNull(), true);
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
clientSecretCredential.NewExpiration = olderTime;
|
||||
|
||||
auto const tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(clientSecretCredential.IsTokenPtrNull(), false);
|
||||
EXPECT_EQ(tokenReceived, olderToken);
|
||||
@ -266,7 +266,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
clientSecretCredential.NewExpiration = newTime;
|
||||
|
||||
auto const tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(tokenReceived, olderToken);
|
||||
EXPECT_EQ(clientSecretCredential.GetTokenString(), olderToken);
|
||||
@ -279,7 +279,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
clientSecretCredential.IsExpired = true;
|
||||
|
||||
auto const tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(tokenReceived, newToken);
|
||||
EXPECT_EQ(clientSecretCredential.GetTokenString(), newToken);
|
||||
@ -302,14 +302,14 @@ TEST(Credential, ClientSecretCredential)
|
||||
}
|
||||
|
||||
|
||||
credentials::Credential::Internal::SetScopes(clientSecretCredential, scopesCopy);
|
||||
Credentials::Credential::Internal::SetScopes(clientSecretCredential, scopesCopy);
|
||||
|
||||
EXPECT_EQ(clientSecretCredential.GetTenantId(), tenantId);
|
||||
EXPECT_EQ(clientSecretCredential.GetClientId(), clientId);
|
||||
EXPECT_EQ(clientSecretCredential.GetClientSecret(), clientSecret);
|
||||
|
||||
auto const tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(tokenReceived, newToken);
|
||||
EXPECT_EQ(clientSecretCredential.GetTokenString(), newToken);
|
||||
@ -329,14 +329,14 @@ TEST(Credential, ClientSecretCredential)
|
||||
clientSecretCredential.NewExpiration = anotherTime;
|
||||
|
||||
auto tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(tokenReceived, newToken);
|
||||
EXPECT_EQ(clientSecretCredential.GetTokenString(), newToken);
|
||||
EXPECT_EQ(clientSecretCredential.GetScopes(), scopes);
|
||||
EXPECT_EQ(clientSecretCredential.GetExpiration(), newTime);
|
||||
|
||||
credentials::Credential::Internal::SetScopes(
|
||||
Credentials::Credential::Internal::SetScopes(
|
||||
clientSecretCredential, std::string(anotherScopes));
|
||||
|
||||
|
||||
@ -347,7 +347,7 @@ TEST(Credential, ClientSecretCredential)
|
||||
EXPECT_EQ(clientSecretCredential.IsTokenPtrNull(), true);
|
||||
|
||||
tokenReceived
|
||||
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
= Credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
|
||||
|
||||
EXPECT_EQ(clientSecretCredential.IsTokenPtrNull(), false);
|
||||
EXPECT_EQ(tokenReceived, anotherToken);
|
||||
|
||||
@ -24,7 +24,7 @@ add_library (
|
||||
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})
|
||||
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)
|
||||
|
||||
@ -6,10 +6,9 @@
|
||||
#include <curl/curl.h>
|
||||
#include <http/http.hpp>
|
||||
|
||||
class CurlClient
|
||||
{
|
||||
class CurlClient {
|
||||
private:
|
||||
azure::core::http::Request& m_request;
|
||||
Azure::Core::Http::Request& m_request;
|
||||
CURL* m_p_curl;
|
||||
|
||||
// setHeaders()
|
||||
@ -28,12 +27,15 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
CurlClient(azure::core::http::Request& request) : m_request(request)
|
||||
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); }
|
||||
~CurlClient()
|
||||
{
|
||||
curl_easy_cleanup(m_p_curl);
|
||||
}
|
||||
|
||||
azure::core::http::Response send();
|
||||
Azure::Core::Http::Response send();
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#include <curl_client.hpp>
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
// implement send method
|
||||
Response Client::send(Request& request)
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace std;
|
||||
|
||||
Response CurlClient::send()
|
||||
@ -19,15 +19,15 @@ Response CurlClient::send()
|
||||
{
|
||||
case CURLE_COULDNT_RESOLVE_HOST:
|
||||
{
|
||||
throw azure::core::http::CouldNotResolveHostException();
|
||||
throw Azure::Core::Http::CouldNotResolveHostException();
|
||||
}
|
||||
case CURLE_WRITE_ERROR:
|
||||
{
|
||||
throw azure::core::http::ErrorWhileWrittingResponse();
|
||||
throw Azure::Core::Http::ErrorWhileWrittingResponse();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw azure::core::http::TransportException();
|
||||
throw Azure::Core::Http::TransportException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,6 @@ add_library (
|
||||
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})
|
||||
add_library (Azure::nohttp ALIAS ${TARGET_NAME})
|
||||
|
||||
endif()
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <http/http.hpp>
|
||||
|
||||
using namespace azure::core::http;
|
||||
using namespace Azure::Core::Http;
|
||||
|
||||
// implement send method
|
||||
Response Client::send(Request& request)
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace azure::core;
|
||||
using namespace Azure::Core;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
@ -18,18 +18,18 @@ 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);
|
||||
auto request = Http::Request(Http::HttpMethod::Get, host);
|
||||
|
||||
try
|
||||
{
|
||||
auto response = http::Client::send(request);
|
||||
auto response = Http::Client::send(request);
|
||||
cout << response.getReasonPhrase();
|
||||
}
|
||||
catch (http::CouldNotResolveHostException& e)
|
||||
catch (Http::CouldNotResolveHostException& e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
}
|
||||
catch (http::TransportException& e)
|
||||
catch (Http::TransportException& e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user