// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #if (IS_PROGRAM || WITH_EDITOR) #include "Containers/Map.h" #include "Containers/StringView.h" #include "Containers/UnrealString.h" #include "Memory/MemoryView.h" #include "Memory/SharedBuffer.h" #include "Misc/DateTime.h" #include "Misc/StringBuilder.h" #define UE_API S3CLIENT_API namespace UE { /** Credentials for creating signed/authenticated requests to S3. */ class FS3ClientCredentials { public: /** Default constructor creating invalid credentails. */ FS3ClientCredentials() = default; /** * Constructor for basic credentials. * * @param AccessKey The access key. * @param SecretKey The secret key. */ FS3ClientCredentials(const FString& InAccessKey, const FString& InSecretKey) : AccessKey(InAccessKey) , SecretKey(InSecretKey) { } /** * Constructor for short termed credentials. * * @param AccessKey The access key. * @param SecretKey The secret key. * @param SessionToken Token defining the lifetime of the credentials. */ FS3ClientCredentials(const FString& InAccessKey, const FString& InSecretKey, const FString& InSessionToken) : AccessKey(InAccessKey) , SecretKey(InSecretKey) , SessionToken(InSessionToken) { } FS3ClientCredentials(const FS3ClientCredentials& Other) = default; FS3ClientCredentials(FS3ClientCredentials&&) = default; FS3ClientCredentials& operator=(const FS3ClientCredentials&) = default; FS3ClientCredentials& operator=(FS3ClientCredentials&&) = default; /** Returns whether the access and secret is is valid. */ bool IsValid() const; /** Returns the access key. */ const FString& GetAccessKey() const { return AccessKey; } /** Returns the secret key. */ const FString& GetSecretKey() const { return SecretKey; } /** Returns the session token. */ const FString& GetSessionToken() const { return SessionToken; } private: FString AccessKey; FString SecretKey; FString SessionToken; }; /** * Container for named credentials. */ class UE_API FS3CredentialsProfileStore { public: /** Returns the first credentials loaded into the profile store. */ FS3ClientCredentials GetDefault() const; /** Get credentials for the specified profile name. */ bool TryGetCredentials(const FString& ProfileName, FS3ClientCredentials& OutCredentials) const; /** Reads named credentials from an .ini file. */ static FS3CredentialsProfileStore FromFile(const FString& FileName, FString* OutError = nullptr); private: TMap Credentials; }; /** Describes an object stored in S3. */ struct FS3Object { /** The object identifider. */ FString Key; /** Date and time when this object was last modified in text format. */ FString LastModifiedText; /** Date and time when this object was last modified. */ FDateTime LastModified; /** The size of the object. */ uint64 Size = 0; bool operator==(const FS3Object& RHS) const { return Key == RHS.Key; } bool operator!=(const FS3Object& RHS) const { return !operator==(RHS); } friend inline uint32 GetTypeHash(const FS3Object& Object) { return GetTypeHash(Object.Key); } }; /** Basic response parameters. */ struct FS3Response { public: FS3Response(); FS3Response(const FS3Response& Other); FS3Response(FS3Response&& Other); FS3Response(uint32 InHttpStatusCode, uint32 InApiStatusCode); FS3Response(uint32 InHttpStatusCode, uint32 InApiStatusCode, FSharedBuffer&& InBody); FS3Response(uint32 InHttpStatusCode, FS3Response&& Other); public: UE_API ~FS3Response() = default; UE_API FS3Response& operator=(const FS3Response& Other); UE_API FS3Response& operator=(FS3Response&& Other); /** Returns whether the request is considered successful or not. */ UE_API bool IsOk() const; /** Returns the body as text. */ UE_API FString ToString() const; /** Returns the body as a raw buffer */ UE_API FSharedBuffer GetBody() const; /** * Returns an error message comprised of the api/http status code and any error * that might have been returned as part of the response body. * If there response had no errors it the message will be "Success" */ UE_API void GetErrorResponse(FStringBuilderBase& OutErrorMsg) const; /** * Returns a short error message comprised of the api/http status code * If there response had no errors it the message will be "Success" */ UE_API FString GetErrorStatus() const; private: /** Status code returned by the HTTP request. */ uint32 HttpStatusCode = 0; /** Status code returned by the API */ uint32 ApiStatusCode = 0; /** HTTP response body. */ FSharedBuffer Body; }; /** Request parameters for retrieving objects. */ struct FS3GetObjectRequest { /** The bucket name. */ FString BucketName; /** The object key. */ FString Key; }; /** Response parameters when retrieving objects. */ using FS3GetObjectResponse = FS3Response; /** Request parameters for retrieving object meta data. */ struct FS3HeadObjectRequest { /** The bucket name. */ FString BucketName; /** The object key. */ FString Key; }; /** Response parameters when retrieving object meta data. */ using FS3HeadObjectResponse = FS3Response; /** Request parameters for uploading objects. */ struct FS3PutObjectRequest { /** The bucket name. */ FString BucketName; /** The object key. */ FString Key; /** The object data. */ FMemoryView ObjectData; }; /** Response parameters when uploading objects. */ using FS3PutObjectResponse = FS3Response; /** Request parameters for listing objects. */ struct FS3ListObjectsRequest { /** The bucket name. */ FString BucketName; /** The object prefix, i.e. the path. */ FString Prefix; /** The path delimiter, i.e. '/'. */ TCHAR Delimiter; /* Max key(s). */ int32 MaxKeys = INDEX_NONE; /** Marker from where to list objects. */ FString Marker; }; /** Response parameters when listing objects. */ struct FS3ListObjectResponse : public FS3Response { FS3ListObjectResponse() = default; FS3ListObjectResponse(FS3Response&& Other) : FS3Response(MoveTemp(Other)) {} FS3ListObjectResponse(FS3Response&& Other, FString&& InBucketName, TArray&& InObjects, FString InNextMarker = FString(), bool bInIsTruncated = false) : FS3Response(MoveTemp(Other)) , BucketName(MoveTemp(InBucketName)) , Objects(MoveTemp(InObjects)) , NextMarker(MoveTemp(InNextMarker)) , bIsTruncated(bInIsTruncated) {} /** The bucket name. */ FString BucketName; /** The list of object(s). */ TArray Objects; /** Marker to use for paginated requests. */ FString NextMarker; /** Whether the response is truncated. */ bool bIsTruncated = false; }; /** Request parameters for deleting objects. */ using FS3DeleteObjectRequest = FS3GetObjectRequest; /** Response parameters when deleting objects. */ using FS3DeleteObjectResponse = FS3Response; /** S3 client configuration with region and service URL. */ struct FS3ClientConfig { FString Region; FString ServiceUrl; }; /** * A simple HTTP(s) client for down, uploading and listing data objects from Amazon S3. */ class UE_API FS3Client { class FConnectionPool; class FS3Request; public: /** Creates a new instance from the specified configuration and credentials. */ explicit FS3Client(const FS3ClientConfig& ClientConfig, const FS3ClientCredentials& BasicCredentials); FS3Client(const FS3Client&) = delete; FS3Client(FS3Client&&) = delete; ~FS3Client(); FS3Client& operator=(const FS3Client&) = delete; FS3Client& operator=(FS3Client&&) = delete; /** Returns the credentials. */ const FS3ClientCredentials& GetCredentials() const { return Credentials; } /** Returns the client configuration. */ const FS3ClientConfig& GetConfig() const { return Config; } /** Download an object associated with the specified request parameters. */ FS3GetObjectResponse GetObject(const FS3GetObjectRequest& Request); /** Download object meta data. */ FS3HeadObjectResponse HeadObject(const FS3HeadObjectRequest& Request); /** List all objects described by the specified request parameters. */ FS3ListObjectResponse ListObjects(const FS3ListObjectsRequest& Request); /** Upload an object described by the specified request parameters. */ FS3PutObjectResponse PutObject(const FS3PutObjectRequest& Request); /** Retries uploading an object until succeeded or max attempts has been reached. */ FS3PutObjectResponse TryPutObject(const FS3PutObjectRequest& Request, int32 MaxAttempts = 3, float Delay = 0.5f); /** Delete an object associated with the specified request parameters. */ FS3DeleteObjectResponse DeleteObject(const FS3DeleteObjectRequest& Request); private: void Setup(FS3Request& Request); void Teardown(FS3Request& Request); FS3ClientConfig Config; FS3ClientCredentials Credentials; TUniquePtr ConnectionPool; }; } // namesapce UE #endif // (IS_PROGRAM || WITH_EDITOR) #undef UE_API