Lesson 35 - Get Compute Auth Token Working
This commit is contained in:
@@ -0,0 +1,514 @@
|
||||
#pragma once
|
||||
/**
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0.
|
||||
*/
|
||||
#include <aws/http/connection.h>
|
||||
#include <aws/http/proxy.h>
|
||||
#include <aws/http/request_response.h>
|
||||
|
||||
#include <aws/crt/Types.h>
|
||||
#include <aws/crt/io/Bootstrap.h>
|
||||
#include <aws/crt/io/SocketOptions.h>
|
||||
#include <aws/crt/io/TlsOptions.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace Aws
|
||||
{
|
||||
namespace Crt
|
||||
{
|
||||
namespace Io
|
||||
{
|
||||
class ClientBootstrap;
|
||||
}
|
||||
|
||||
namespace Http
|
||||
{
|
||||
class HttpClientConnection;
|
||||
class HttpStream;
|
||||
class HttpClientStream;
|
||||
class HttpRequest;
|
||||
class HttpProxyStrategy;
|
||||
using HttpHeader = aws_http_header;
|
||||
|
||||
/**
|
||||
* Invoked upon connection setup, whether it was successful or not. If the connection was
|
||||
* successfully established, `connection` will be valid and errorCode will be AWS_ERROR_SUCCESS.
|
||||
* Upon an error, `connection` will not be valid, and errorCode will contain the cause of the connection
|
||||
* failure.
|
||||
*/
|
||||
using OnConnectionSetup =
|
||||
std::function<void(const std::shared_ptr<HttpClientConnection> &connection, int errorCode)>;
|
||||
|
||||
/**
|
||||
* Invoked upon connection shutdown. `connection` will always be a valid pointer. `errorCode` will specify
|
||||
* shutdown reason. A graceful connection close will set `errorCode` to AWS_ERROR_SUCCESS.
|
||||
* Internally, the connection pointer will be unreferenced immediately after this call; if you took a
|
||||
* reference to it in OnConnectionSetup(), you'll need to release your reference before the underlying
|
||||
* memory is released. If you never took a reference to it, the resources for the connection will be
|
||||
* immediately released after completion of this callback.
|
||||
*/
|
||||
using OnConnectionShutdown = std::function<void(HttpClientConnection &connection, int errorCode)>;
|
||||
|
||||
/**
|
||||
* Called as headers are received from the peer. `headersArray` will contain the header value
|
||||
* read from the wire. The number of entries in `headersArray` are specified in `headersCount`.
|
||||
*
|
||||
* Keep in mind that this function will likely be called multiple times until all headers are received.
|
||||
*
|
||||
* On HttpStream, this function must be set.
|
||||
*/
|
||||
using OnIncomingHeaders = std::function<void(
|
||||
HttpStream &stream,
|
||||
enum aws_http_header_block headerBlock,
|
||||
const HttpHeader *headersArray,
|
||||
std::size_t headersCount)>;
|
||||
|
||||
/**
|
||||
* Invoked when the headers portion of the message has been completely received. `hasBody` will indicate
|
||||
* if there is an incoming body.
|
||||
*
|
||||
* On HttpStream, this function can be empty.
|
||||
*/
|
||||
using OnIncomingHeadersBlockDone =
|
||||
std::function<void(HttpStream &stream, enum aws_http_header_block block)>;
|
||||
|
||||
/**
|
||||
* Invoked as chunks of the body are read. `data` contains the data read from the wire. If chunked encoding
|
||||
* was used, it will already be decoded (TBD).
|
||||
*
|
||||
* On HttpStream, this function can be empty if you are not expecting a body (e.g. a HEAD request).
|
||||
*/
|
||||
using OnIncomingBody = std::function<void(HttpStream &stream, const ByteCursor &data)>;
|
||||
|
||||
/**
|
||||
* Invoked upon completion of the stream. This means the request has been sent and a completed response
|
||||
* has been received (in client mode), or the request has been received and the response has been completed.
|
||||
*
|
||||
* In H2, this will mean RST_STREAM state has been reached for the stream.
|
||||
*
|
||||
* On HttpStream, this function must be set.
|
||||
*/
|
||||
using OnStreamComplete = std::function<void(HttpStream &stream, int errorCode)>;
|
||||
|
||||
/**
|
||||
* POD structure used for setting up an Http Request
|
||||
*/
|
||||
struct AWS_CRT_CPP_API HttpRequestOptions
|
||||
{
|
||||
/**
|
||||
* The actual http request
|
||||
*/
|
||||
HttpRequest *request;
|
||||
|
||||
/**
|
||||
* See `OnIncomingHeaders` for more info. This value must be set.
|
||||
*/
|
||||
OnIncomingHeaders onIncomingHeaders;
|
||||
OnIncomingHeadersBlockDone onIncomingHeadersBlockDone;
|
||||
|
||||
/**
|
||||
* See `OnIncomingBody` for more info. This value can be empty if you will not be receiving a body.
|
||||
*/
|
||||
OnIncomingBody onIncomingBody;
|
||||
|
||||
/**
|
||||
* See `OnStreamComplete` for more info. This value can be empty.
|
||||
*/
|
||||
OnStreamComplete onStreamComplete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a single http message exchange (request/response) or in H2, it can also represent
|
||||
* a PUSH_PROMISE followed by the accompanying Response.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpStream : public std::enable_shared_from_this<HttpStream>
|
||||
{
|
||||
public:
|
||||
virtual ~HttpStream();
|
||||
HttpStream(const HttpStream &) = delete;
|
||||
HttpStream(HttpStream &&) = delete;
|
||||
HttpStream &operator=(const HttpStream &) = delete;
|
||||
HttpStream &operator=(HttpStream &&) = delete;
|
||||
|
||||
/**
|
||||
* Get the underlying connection for the stream.
|
||||
*/
|
||||
HttpClientConnection &GetConnection() const noexcept;
|
||||
|
||||
/**
|
||||
* @return request's Http Response Code. Requires response headers to have been processed first. *
|
||||
*/
|
||||
virtual int GetResponseStatusCode() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Updates the read window on the connection. In Http 1.1 this relieves TCP back pressure, in H2
|
||||
* this will trigger two WINDOW_UPDATE frames, one for the connection and one for the stream.
|
||||
*
|
||||
* You do not need to call this unless you utilized the `outWindowUpdateSize` in `OnIncomingBody`.
|
||||
* See `OnIncomingBody` for more information.
|
||||
*
|
||||
* `incrementSize` is the amount to update the read window by.
|
||||
*/
|
||||
void UpdateWindow(std::size_t incrementSize) noexcept;
|
||||
|
||||
protected:
|
||||
aws_http_stream *m_stream;
|
||||
std::shared_ptr<HttpClientConnection> m_connection;
|
||||
HttpStream(const std::shared_ptr<HttpClientConnection> &connection) noexcept;
|
||||
|
||||
private:
|
||||
OnIncomingHeaders m_onIncomingHeaders;
|
||||
OnIncomingHeadersBlockDone m_onIncomingHeadersBlockDone;
|
||||
OnIncomingBody m_onIncomingBody;
|
||||
OnStreamComplete m_onStreamComplete;
|
||||
|
||||
static int s_onIncomingHeaders(
|
||||
struct aws_http_stream *stream,
|
||||
enum aws_http_header_block headerBlock,
|
||||
const struct aws_http_header *headerArray,
|
||||
size_t numHeaders,
|
||||
void *userData) noexcept;
|
||||
static int s_onIncomingHeaderBlockDone(
|
||||
struct aws_http_stream *stream,
|
||||
enum aws_http_header_block headerBlock,
|
||||
void *userData) noexcept;
|
||||
static int s_onIncomingBody(
|
||||
struct aws_http_stream *stream,
|
||||
const struct aws_byte_cursor *data,
|
||||
void *userData) noexcept;
|
||||
static void s_onStreamComplete(struct aws_http_stream *stream, int errorCode, void *userData) noexcept;
|
||||
|
||||
friend class HttpClientConnection;
|
||||
};
|
||||
|
||||
struct ClientStreamCallbackData
|
||||
{
|
||||
ClientStreamCallbackData() : allocator(nullptr), stream(nullptr) {}
|
||||
Allocator *allocator;
|
||||
std::shared_ptr<HttpStream> stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subclass that represents an http client's view of an HttpStream.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientStream final : public HttpStream
|
||||
{
|
||||
public:
|
||||
~HttpClientStream();
|
||||
HttpClientStream(const HttpClientStream &) = delete;
|
||||
HttpClientStream(HttpClientStream &&) = delete;
|
||||
HttpClientStream &operator=(const HttpClientStream &) = delete;
|
||||
HttpClientStream &operator=(HttpClientStream &&) = delete;
|
||||
|
||||
/**
|
||||
* If this stream was initiated as a request, assuming the headers of the response has been
|
||||
* received, this value contains the Http Response Code. *
|
||||
*/
|
||||
virtual int GetResponseStatusCode() const noexcept override;
|
||||
|
||||
/**
|
||||
* Activates the request's outgoing stream processing.
|
||||
*
|
||||
* Returns true on success, false otherwise.
|
||||
*/
|
||||
bool Activate() noexcept;
|
||||
|
||||
private:
|
||||
HttpClientStream(const std::shared_ptr<HttpClientConnection> &connection) noexcept;
|
||||
|
||||
ClientStreamCallbackData m_callbackData;
|
||||
friend class HttpClientConnection;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated enum that designates what kind of authentication, if any, to use when connecting to a
|
||||
* proxy server.
|
||||
*
|
||||
* Here for backwards compatibility. Has been superceded by proxy strategies.
|
||||
*/
|
||||
enum class AwsHttpProxyAuthenticationType
|
||||
{
|
||||
None,
|
||||
Basic,
|
||||
};
|
||||
|
||||
/**
|
||||
* Mirror of aws_http_proxy_connection_type enum. Indicates the basic http proxy behavior of the
|
||||
* proxy we're connecting to.
|
||||
*/
|
||||
enum class AwsHttpProxyConnectionType
|
||||
{
|
||||
/**
|
||||
* Deprecated, but 0-valued for backwards compatibility
|
||||
*
|
||||
* If tls options are provided (for the main connection) then treat the proxy as a tunneling proxy
|
||||
* If tls options are not provided (for the main connection), then treat the proxy as a forwarding
|
||||
* proxy
|
||||
*/
|
||||
Legacy = AWS_HPCT_HTTP_LEGACY,
|
||||
|
||||
/**
|
||||
* Use the proxy to forward http requests. Attempting to use both this mode and TLS to the destination
|
||||
* is a configuration error.
|
||||
*/
|
||||
Forwarding = AWS_HPCT_HTTP_FORWARD,
|
||||
|
||||
/**
|
||||
* Use the proxy to establish an http connection via a CONNECT request to the proxy. Works for both
|
||||
* plaintext and tls connections.
|
||||
*/
|
||||
Tunneling = AWS_HPCT_HTTP_TUNNEL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration structure that holds all proxy-related http connection options
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientConnectionProxyOptions
|
||||
{
|
||||
public:
|
||||
HttpClientConnectionProxyOptions();
|
||||
HttpClientConnectionProxyOptions(const HttpClientConnectionProxyOptions &rhs) = default;
|
||||
HttpClientConnectionProxyOptions(HttpClientConnectionProxyOptions &&rhs) = default;
|
||||
|
||||
HttpClientConnectionProxyOptions &operator=(const HttpClientConnectionProxyOptions &rhs) = default;
|
||||
HttpClientConnectionProxyOptions &operator=(HttpClientConnectionProxyOptions &&rhs) = default;
|
||||
|
||||
~HttpClientConnectionProxyOptions() = default;
|
||||
|
||||
/**
|
||||
* Intended for internal use only. Initializes the C proxy configuration structure,
|
||||
* aws_http_proxy_options, from an HttpClientConnectionProxyOptions instance.
|
||||
*
|
||||
* @param raw_options - output parameter containing low level proxy options to be passed to the C
|
||||
* interface
|
||||
*
|
||||
*/
|
||||
void InitializeRawProxyOptions(struct aws_http_proxy_options &raw_options) const;
|
||||
|
||||
/**
|
||||
* The name of the proxy server to connect through.
|
||||
* Required.
|
||||
*/
|
||||
String HostName;
|
||||
|
||||
/**
|
||||
* The port of the proxy server to connect to.
|
||||
* Required.
|
||||
*/
|
||||
uint32_t Port;
|
||||
|
||||
/**
|
||||
* Sets the TLS options for the connection to the proxy.
|
||||
* Optional.
|
||||
*/
|
||||
Optional<Io::TlsConnectionOptions> TlsOptions;
|
||||
|
||||
/**
|
||||
* What kind of proxy connection to make
|
||||
*/
|
||||
AwsHttpProxyConnectionType ProxyConnectionType;
|
||||
|
||||
/**
|
||||
* Proxy strategy to use while negotiating the connection. Use null for no additional
|
||||
* steps.
|
||||
*/
|
||||
std::shared_ptr<HttpProxyStrategy> ProxyStrategy;
|
||||
|
||||
/**
|
||||
* @deprecated What kind of authentication approach to use when connecting to the proxy
|
||||
* Replaced by proxy strategy
|
||||
*
|
||||
* Backwards compatibility achieved by invoking CreateBasicHttpProxyStrategy if
|
||||
* (1) ProxyStrategy is null
|
||||
* (2) AuthType is AwsHttpProxyAuthenticationType::Basic
|
||||
*/
|
||||
AwsHttpProxyAuthenticationType AuthType;
|
||||
|
||||
/**
|
||||
* @deprecated The username to use if connecting to the proxy via basic authentication
|
||||
* Replaced by using the result of CreateBasicHttpProxyStrategy()
|
||||
*/
|
||||
String BasicAuthUsername;
|
||||
|
||||
/**
|
||||
* @deprecated The password to use if connecting to the proxy via basic authentication
|
||||
* Replaced by using the result of CreateBasicHttpProxyStrategy()
|
||||
*/
|
||||
String BasicAuthPassword;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration structure holding all options relating to http connection establishment
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientConnectionOptions
|
||||
{
|
||||
public:
|
||||
HttpClientConnectionOptions();
|
||||
HttpClientConnectionOptions(const HttpClientConnectionOptions &rhs) = default;
|
||||
HttpClientConnectionOptions(HttpClientConnectionOptions &&rhs) = default;
|
||||
|
||||
~HttpClientConnectionOptions() = default;
|
||||
|
||||
HttpClientConnectionOptions &operator=(const HttpClientConnectionOptions &rhs) = default;
|
||||
HttpClientConnectionOptions &operator=(HttpClientConnectionOptions &&rhs) = default;
|
||||
|
||||
/**
|
||||
* The client bootstrap to use for setting up and tearing down connections.
|
||||
* Note: If null, then the default ClientBootstrap is used
|
||||
* (see Aws::Crt::ApiHandle::GetOrCreateStaticDefaultClientBootstrap)
|
||||
*/
|
||||
Io::ClientBootstrap *Bootstrap;
|
||||
|
||||
/**
|
||||
* The TCP read window allowed for Http 1.1 connections and Initial Windows for H2 connections.
|
||||
*/
|
||||
size_t InitialWindowSize;
|
||||
|
||||
/**
|
||||
* The callback invoked on connection establishment, whether success or failure.
|
||||
* See `OnConnectionSetup` for more info.
|
||||
* Required.
|
||||
*/
|
||||
OnConnectionSetup OnConnectionSetupCallback;
|
||||
|
||||
/**
|
||||
* The callback invoked on connection shutdown.
|
||||
* See `OnConnectionShutdown` for more info.
|
||||
* Required.
|
||||
*/
|
||||
OnConnectionShutdown OnConnectionShutdownCallback;
|
||||
|
||||
/**
|
||||
* The name of the http server to connect to.
|
||||
* Required.
|
||||
*/
|
||||
String HostName;
|
||||
|
||||
/**
|
||||
* The port of the http server to connect to.
|
||||
* Required.
|
||||
*/
|
||||
uint32_t Port;
|
||||
|
||||
/**
|
||||
* The socket options of the connection.
|
||||
* Required.
|
||||
*/
|
||||
Io::SocketOptions SocketOptions;
|
||||
|
||||
/**
|
||||
* The TLS options for the http connection.
|
||||
* Optional.
|
||||
*/
|
||||
Optional<Io::TlsConnectionOptions> TlsOptions;
|
||||
|
||||
/**
|
||||
* The proxy options for the http connection.
|
||||
* Optional.
|
||||
*/
|
||||
Optional<HttpClientConnectionProxyOptions> ProxyOptions;
|
||||
|
||||
/**
|
||||
* If set to true, then the TCP read back pressure mechanism will be enabled. You should
|
||||
* only use this if you're allowing http response body data to escape the callbacks. E.g. you're
|
||||
* putting the data into a queue for another thread to process and need to make sure the memory
|
||||
* usage is bounded. If this is enabled, you must call HttpStream::UpdateWindow() for every
|
||||
* byte read from the OnIncomingBody callback.
|
||||
*/
|
||||
bool ManualWindowManagement;
|
||||
};
|
||||
|
||||
enum class HttpVersion
|
||||
{
|
||||
Unknown = AWS_HTTP_VERSION_UNKNOWN,
|
||||
Http1_0 = AWS_HTTP_VERSION_1_0,
|
||||
Http1_1 = AWS_HTTP_VERSION_1_1,
|
||||
Http2 = AWS_HTTP_VERSION_2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a connection from a Http Client to a Server.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientConnection : public std::enable_shared_from_this<HttpClientConnection>
|
||||
{
|
||||
public:
|
||||
virtual ~HttpClientConnection() = default;
|
||||
HttpClientConnection(const HttpClientConnection &) = delete;
|
||||
HttpClientConnection(HttpClientConnection &&) = delete;
|
||||
HttpClientConnection &operator=(const HttpClientConnection &) = delete;
|
||||
HttpClientConnection &operator=(HttpClientConnection &&) = delete;
|
||||
|
||||
/**
|
||||
* Make a new client initiated request on this connection.
|
||||
*
|
||||
* If you take a reference to the return value, the memory and resources for the connection
|
||||
* and stream will not be cleaned up until you release it. You can however, release the reference
|
||||
* as soon as you don't need it anymore. The internal reference count ensures the resources will
|
||||
* not be freed until the stream is completed.
|
||||
*
|
||||
* Returns an instance of HttpStream upon success and nullptr on failure.
|
||||
*
|
||||
* You must call HttpClientStream::Activate() to begin outgoing processing of the stream.
|
||||
*/
|
||||
std::shared_ptr<HttpClientStream> NewClientStream(const HttpRequestOptions &requestOptions) noexcept;
|
||||
|
||||
/**
|
||||
* @return true unless the connection is closed or closing.
|
||||
*/
|
||||
bool IsOpen() const noexcept;
|
||||
|
||||
/**
|
||||
* Initiate a shutdown of the connection. Sometimes, connections are persistent and you want
|
||||
* to close them before shutting down your application or whatever is consuming this interface.
|
||||
*
|
||||
* Assuming `OnConnectionShutdown` has not already been invoked, it will be invoked as a result of this
|
||||
* call.
|
||||
*/
|
||||
void Close() noexcept;
|
||||
|
||||
/**
|
||||
* @return protocol version the connection used
|
||||
*/
|
||||
HttpVersion GetVersion() noexcept;
|
||||
|
||||
/**
|
||||
* @return the value of the last aws error encountered by operations on this instance.
|
||||
*/
|
||||
int LastError() const noexcept { return m_lastError; }
|
||||
|
||||
/**
|
||||
* Create a new Https Connection to hostName:port, using `socketOptions` for tcp options and
|
||||
* `tlsConnOptions` for TLS/SSL options. If `tlsConnOptions` is null http (plain-text) will be used.
|
||||
*
|
||||
* returns true on success, and false on failure. If false is returned, `onConnectionSetup` will not
|
||||
* be invoked. On success, `onConnectionSetup` will be called, either with a connection, or an
|
||||
* errorCode.
|
||||
*/
|
||||
static bool CreateConnection(
|
||||
const HttpClientConnectionOptions &connectionOptions,
|
||||
Allocator *allocator) noexcept;
|
||||
|
||||
protected:
|
||||
HttpClientConnection(aws_http_connection *m_connection, Allocator *allocator) noexcept;
|
||||
aws_http_connection *m_connection;
|
||||
|
||||
private:
|
||||
Allocator *m_allocator;
|
||||
int m_lastError;
|
||||
|
||||
static void s_onClientConnectionSetup(
|
||||
struct aws_http_connection *connection,
|
||||
int error_code,
|
||||
void *user_data) noexcept;
|
||||
static void s_onClientConnectionShutdown(
|
||||
struct aws_http_connection *connection,
|
||||
int error_code,
|
||||
void *user_data) noexcept;
|
||||
};
|
||||
|
||||
} // namespace Http
|
||||
} // namespace Crt
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
/**
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0.
|
||||
*/
|
||||
#include <aws/crt/http/HttpConnection.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
|
||||
struct aws_http_connection_manager;
|
||||
|
||||
namespace Aws
|
||||
{
|
||||
namespace Crt
|
||||
{
|
||||
namespace Http
|
||||
{
|
||||
/**
|
||||
* Invoked when a connection from the pool is available. If a connection was successfully obtained
|
||||
* the connection shared_ptr can be seated into your own copy of connection. If it failed, errorCode
|
||||
* will be non-zero.
|
||||
*/
|
||||
using OnClientConnectionAvailable =
|
||||
std::function<void(std::shared_ptr<HttpClientConnection>, int errorCode)>;
|
||||
|
||||
/**
|
||||
* Configuration struct containing all options related to connection manager behavior
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientConnectionManagerOptions
|
||||
{
|
||||
public:
|
||||
HttpClientConnectionManagerOptions() noexcept;
|
||||
HttpClientConnectionManagerOptions(const HttpClientConnectionManagerOptions &rhs) = default;
|
||||
HttpClientConnectionManagerOptions(HttpClientConnectionManagerOptions &&rhs) = default;
|
||||
|
||||
HttpClientConnectionManagerOptions &operator=(const HttpClientConnectionManagerOptions &rhs) = default;
|
||||
HttpClientConnectionManagerOptions &operator=(HttpClientConnectionManagerOptions &&rhs) = default;
|
||||
|
||||
/**
|
||||
* The http connection options to use for each connection created by the manager
|
||||
*/
|
||||
HttpClientConnectionOptions ConnectionOptions;
|
||||
|
||||
/**
|
||||
* The maximum number of connections the manager is allowed to create/manage
|
||||
*/
|
||||
size_t MaxConnections;
|
||||
|
||||
/** If set, initiate shutdown will return a future that will allow a user to block until the
|
||||
* connection manager has completely released all resources. This isn't necessary during the normal
|
||||
* flow of an application, but it is useful for scenarios, such as tests, that need deterministic
|
||||
* shutdown ordering. Be aware, if you use this anywhere other than the main thread, you will most
|
||||
* likely cause a deadlock. If this is set, you MUST call InitiateShutdown() before releasing your last
|
||||
* reference to the connection manager.
|
||||
*/
|
||||
bool EnableBlockingShutdown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages a pool of connections to a specific endpoint using the same socket and tls options.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpClientConnectionManager final
|
||||
: public std::enable_shared_from_this<HttpClientConnectionManager>
|
||||
{
|
||||
public:
|
||||
~HttpClientConnectionManager();
|
||||
|
||||
/**
|
||||
* Acquires a connection from the pool. onClientConnectionAvailable will be invoked upon an available
|
||||
* connection. Returns true if the connection request was successfully queued, returns false if it
|
||||
* failed. On failure, onClientConnectionAvailable will not be invoked. After receiving a connection, it
|
||||
* will automatically be cleaned up when your last reference to the shared_ptr is released.
|
||||
*
|
||||
* @param onClientConnectionAvailable callback to invoke when a connection becomes available or the
|
||||
* acquisition attempt terminates
|
||||
* @return true if the acquisition was successfully kicked off, false otherwise (no callback)
|
||||
*/
|
||||
bool AcquireConnection(const OnClientConnectionAvailable &onClientConnectionAvailable) noexcept;
|
||||
|
||||
/**
|
||||
* Starts shutdown of the connection manager. Returns a future to the connection manager's shutdown
|
||||
* process. If EnableBlockingDestruct was enabled on the connection manager options, calling get() on
|
||||
* the returned future will block until the last connection is released. If the option is not set, get()
|
||||
* will immediately return.
|
||||
* @return future which will complete when shutdown has completed
|
||||
*/
|
||||
std::future<void> InitiateShutdown() noexcept;
|
||||
|
||||
/**
|
||||
* Factory function for connection managers
|
||||
*
|
||||
* @param connectionManagerOptions connection manager configuration data
|
||||
* @param allocator allocator to use
|
||||
* @return a new connection manager instance
|
||||
*/
|
||||
static std::shared_ptr<HttpClientConnectionManager> NewClientConnectionManager(
|
||||
const HttpClientConnectionManagerOptions &connectionManagerOptions,
|
||||
Allocator *allocator = ApiAllocator()) noexcept;
|
||||
|
||||
private:
|
||||
HttpClientConnectionManager(
|
||||
const HttpClientConnectionManagerOptions &options,
|
||||
Allocator *allocator = ApiAllocator()) noexcept;
|
||||
|
||||
Allocator *m_allocator;
|
||||
|
||||
aws_http_connection_manager *m_connectionManager;
|
||||
|
||||
HttpClientConnectionManagerOptions m_options;
|
||||
std::promise<void> m_shutdownPromise;
|
||||
std::atomic<bool> m_releaseInvoked;
|
||||
|
||||
static void s_onConnectionSetup(
|
||||
aws_http_connection *connection,
|
||||
int errorCode,
|
||||
void *userData) noexcept;
|
||||
|
||||
static void s_shutdownCompleted(void *userData) noexcept;
|
||||
|
||||
friend class ManagedConnection;
|
||||
};
|
||||
} // namespace Http
|
||||
} // namespace Crt
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
/**
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0.
|
||||
*/
|
||||
|
||||
#include <aws/crt/Types.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct aws_http_proxy_strategy;
|
||||
|
||||
namespace Aws
|
||||
{
|
||||
namespace Crt
|
||||
{
|
||||
namespace Http
|
||||
{
|
||||
enum class AwsHttpProxyConnectionType;
|
||||
|
||||
/**
|
||||
* Configuration for a proxy strategy that performs basic authentication
|
||||
*/
|
||||
struct AWS_CRT_CPP_API HttpProxyStrategyBasicAuthConfig
|
||||
{
|
||||
HttpProxyStrategyBasicAuthConfig();
|
||||
|
||||
/**
|
||||
* Basic auth can be applied either to forwarding or tunneling proxy connections, but we need
|
||||
* to know the type ahead of time
|
||||
*/
|
||||
AwsHttpProxyConnectionType ConnectionType;
|
||||
|
||||
/**
|
||||
* Username to apply to the basic authentication process
|
||||
*/
|
||||
String Username;
|
||||
|
||||
/**
|
||||
* Password to apply to the basic authentication process
|
||||
*/
|
||||
String Password;
|
||||
};
|
||||
|
||||
using KerberosGetTokenFunction = std::function<bool(String &)>;
|
||||
using NtlmGetTokenFunction = std::function<bool(const String &, String &)>;
|
||||
|
||||
/**
|
||||
* Configuration for a proxy strategy that attempts to use kerberos and ntlm, based on authentication
|
||||
* failure feedback from the proxy's responses to CONNECT attempts. The kerberos/ntlm callbacks are
|
||||
* currently synchronous but invoked potentially from within event loop threads. This is not optimal
|
||||
* but transitioning to fully async hasn't been a need yet.
|
||||
*
|
||||
* The adapative strategy will skip an authentication method whose callbacks are not supplied, so you
|
||||
* can use this for purely kerberos or ntlm as well.
|
||||
*/
|
||||
struct AWS_CRT_CPP_API HttpProxyStrategyAdaptiveConfig
|
||||
{
|
||||
HttpProxyStrategyAdaptiveConfig() : KerberosGetToken(), NtlmGetCredential(), NtlmGetToken() {}
|
||||
|
||||
/**
|
||||
* User-supplied callback for fetching kerberos tokens
|
||||
*/
|
||||
KerberosGetTokenFunction KerberosGetToken;
|
||||
|
||||
/**
|
||||
* User-supplied callback for fetching an ntlm credential
|
||||
*/
|
||||
KerberosGetTokenFunction NtlmGetCredential;
|
||||
|
||||
/**
|
||||
* User-supplied callback for fetching an ntlm token
|
||||
*/
|
||||
NtlmGetTokenFunction NtlmGetToken;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper class for a C-level proxy strategy - an object that allows the user to transform or modify
|
||||
* the authentication logic when connecting to a proxy.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpProxyStrategy
|
||||
{
|
||||
public:
|
||||
HttpProxyStrategy(struct aws_http_proxy_strategy *strategy);
|
||||
virtual ~HttpProxyStrategy();
|
||||
|
||||
/// @private
|
||||
struct aws_http_proxy_strategy *GetUnderlyingHandle() const noexcept { return m_strategy; }
|
||||
|
||||
/**
|
||||
* Creates a proxy strategy that performs basic authentication
|
||||
* @param config basic authentication configuration options
|
||||
* @param allocator allocator to use
|
||||
* @return a new basic authentication proxy strategy
|
||||
*/
|
||||
static std::shared_ptr<HttpProxyStrategy> CreateBasicHttpProxyStrategy(
|
||||
const HttpProxyStrategyBasicAuthConfig &config,
|
||||
Allocator *allocator = ApiAllocator());
|
||||
|
||||
/**
|
||||
* Creates a proxy strategy that, depending on configuration, can attempt kerberos and/or ntlm
|
||||
* authentication when connecting to the proxy
|
||||
* @param config the adaptive strategy configuration options
|
||||
* @param allocator allocator to use
|
||||
* @return a new adaptive proxy strategy
|
||||
*/
|
||||
static std::shared_ptr<HttpProxyStrategy> CreateAdaptiveHttpProxyStrategy(
|
||||
const HttpProxyStrategyAdaptiveConfig &config,
|
||||
Allocator *allocator = ApiAllocator());
|
||||
|
||||
protected:
|
||||
struct aws_http_proxy_strategy *m_strategy;
|
||||
};
|
||||
} // namespace Http
|
||||
} // namespace Crt
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
/**
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0.
|
||||
*/
|
||||
|
||||
#include <aws/crt/Exports.h>
|
||||
#include <aws/crt/Types.h>
|
||||
#include <aws/crt/io/Stream.h>
|
||||
|
||||
struct aws_http_header;
|
||||
struct aws_http_message;
|
||||
|
||||
namespace Aws
|
||||
{
|
||||
namespace Crt
|
||||
{
|
||||
namespace Mqtt
|
||||
{
|
||||
class MqttConnection;
|
||||
class MqttConnectionCore;
|
||||
} // namespace Mqtt
|
||||
namespace Mqtt5
|
||||
{
|
||||
class Mqtt5ClientCore;
|
||||
}
|
||||
namespace Http
|
||||
{
|
||||
using HttpHeader = aws_http_header;
|
||||
|
||||
/**
|
||||
* Base class representing a mutable http request or response.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpMessage
|
||||
{
|
||||
public:
|
||||
virtual ~HttpMessage();
|
||||
|
||||
HttpMessage(const HttpMessage &) = delete;
|
||||
HttpMessage(HttpMessage &&) = delete;
|
||||
HttpMessage &operator=(const HttpMessage &) = delete;
|
||||
HttpMessage &operator=(HttpMessage &&) = delete;
|
||||
|
||||
/**
|
||||
* Gets the input stream representing the message body
|
||||
*/
|
||||
std::shared_ptr<Aws::Crt::Io::InputStream> GetBody() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the input stream representing the message body
|
||||
* @param body the input stream representing the message body
|
||||
* @return success/failure
|
||||
*/
|
||||
bool SetBody(const std::shared_ptr<Aws::Crt::Io::IStream> &body) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the input stream representing the message body
|
||||
* @param body the input stream representing the message body
|
||||
* @return success/failure
|
||||
*/
|
||||
bool SetBody(const std::shared_ptr<Aws::Crt::Io::InputStream> &body) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of headers contained in this request
|
||||
* @return the number of headers contained in this request
|
||||
*/
|
||||
size_t GetHeaderCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets a particular header in the request
|
||||
* @param index index of the header to fetch
|
||||
* @return an option containing the requested header if the index is in bounds
|
||||
*/
|
||||
Optional<HttpHeader> GetHeader(size_t index) const noexcept;
|
||||
|
||||
/**
|
||||
* Adds a header to the request
|
||||
* @param header header to add
|
||||
* @return success/failure
|
||||
*/
|
||||
bool AddHeader(const HttpHeader &header) noexcept;
|
||||
|
||||
/**
|
||||
* Removes a header from the request
|
||||
* @param index index of the header to remove
|
||||
* @return success/failure
|
||||
*/
|
||||
bool EraseHeader(size_t index) noexcept;
|
||||
|
||||
/**
|
||||
* @return true/false if the underlying object is valid
|
||||
*/
|
||||
operator bool() const noexcept { return m_message != nullptr; }
|
||||
|
||||
/// @private
|
||||
struct aws_http_message *GetUnderlyingMessage() const noexcept { return m_message; }
|
||||
|
||||
protected:
|
||||
HttpMessage(Allocator *allocator, struct aws_http_message *message) noexcept;
|
||||
|
||||
Allocator *m_allocator;
|
||||
struct aws_http_message *m_message;
|
||||
std::shared_ptr<Aws::Crt::Io::InputStream> m_bodyStream;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a mutable http request.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpRequest : public HttpMessage
|
||||
{
|
||||
friend class Mqtt::MqttConnectionCore;
|
||||
friend class Mqtt5::Mqtt5ClientCore;
|
||||
|
||||
public:
|
||||
HttpRequest(Allocator *allocator = ApiAllocator());
|
||||
|
||||
/**
|
||||
* @return the value of the Http method associated with this request
|
||||
*/
|
||||
Optional<ByteCursor> GetMethod() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the value of the Http method associated with this request
|
||||
*/
|
||||
bool SetMethod(ByteCursor method) noexcept;
|
||||
|
||||
/**
|
||||
* @return the value of the URI-path associated with this request
|
||||
*/
|
||||
Optional<ByteCursor> GetPath() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the value of the URI-path associated with this request
|
||||
*/
|
||||
bool SetPath(ByteCursor path) noexcept;
|
||||
|
||||
protected:
|
||||
HttpRequest(Allocator *allocator, struct aws_http_message *message);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a mutable http response.
|
||||
*/
|
||||
class AWS_CRT_CPP_API HttpResponse : public HttpMessage
|
||||
{
|
||||
public:
|
||||
HttpResponse(Allocator *allocator = ApiAllocator());
|
||||
|
||||
/**
|
||||
* @return the integral Http response code associated with this response
|
||||
*/
|
||||
Optional<int> GetResponseCode() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the integral Http response code associated with this response
|
||||
*/
|
||||
bool SetResponseCode(int response) noexcept;
|
||||
};
|
||||
} // namespace Http
|
||||
} // namespace Crt
|
||||
} // namespace Aws
|
||||
Reference in New Issue
Block a user