diff --git a/sdk/storage/inc/blobs/append_blob_client.hpp b/sdk/storage/inc/blobs/append_blob_client.hpp index 5d5106a3c..f01fafdd7 100644 --- a/sdk/storage/inc/blobs/append_blob_client.hpp +++ b/sdk/storage/inc/blobs/append_blob_client.hpp @@ -12,40 +12,127 @@ namespace Azure { namespace Storage { namespace Blobs { + /** + * @brief The AppendBlobClient allows you to manipulate Azure Storage append blobs. + * + * An append blob is comprised of blocks and is optimized for append operations. When you modify + * an append blob, blocks are added to the end of the blob only, via the AppendBlock operation. + * Updating or deleting of existing blocks is not supported. Unlike a block blob, an append blob + * does not expose its block IDs. + */ class AppendBlobClient : public BlobClient { public: - // connection string + /** + * @brief Initialize a new instance of AppendBlobClient. + * + * @param connectionString A connection string includes the authentication information required + * for your application to access data in an Azure Storage account at runtime. + * @param containerName The name of the container containing this blob. + * @param blobName The name of this blob. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + * @return A new AppendBlobClient instance. + */ static AppendBlobClient CreateFromConnectionString( const std::string& connectionString, const std::string& containerName, const std::string& blobName, const AppendBlobClientOptions& options = AppendBlobClientOptions()); - // shared key auth + /** + * @brief Initialize a new instance of AppendBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The shared key credential used to sign + * requests. + * @param options Optional client options that define the transport pipeline + * policies for authentication, retries, etc., that are applied to every request. + */ explicit AppendBlobClient( const std::string& blobUri, std::shared_ptr credential, const AppendBlobClientOptions& options = AppendBlobClientOptions()); - // token auth + /** + * @brief Initialize a new instance of AppendBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The token credential used to sign requests. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + */ explicit AppendBlobClient( const std::string& blobUri, std::shared_ptr credential, const AppendBlobClientOptions& options = AppendBlobClientOptions()); - // anonymous/SAS/customized pipeline auth + /** + * @brief Initialize a new instance of AppendBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob, and possibly also a SAS token. + * @param options Optional client + * options that define the transport pipeline policies for authentication, retries, etc., that + * are applied to every request. + */ explicit AppendBlobClient( const std::string& blobUri, const AppendBlobClientOptions& options = AppendBlobClientOptions()); + /** + * @brief Initializes a new instance of the AppendBlobClient class with an identical uri + * source but the specified snapshot timestamp. + * + * @param snapshot The snapshot + * identifier. + * @return A new AppendBlobClient instance. + * @remarks Pass empty string to remove the snapshot returning the base blob. + */ AppendBlobClient WithSnapshot(const std::string& snapshot) const; + /** + * @brief Creates a new 0-length append blob. The content of any existing blob is + * overwritten with the newly initialized append blob. + * + * @param options Optional + * parameters to execute this function. + * @return A BlobContentInfo describing the newly + * created append blob. + */ BlobContentInfo Create(const CreateAppendBlobOptions& options = CreateAppendBlobOptions()); + /** + * @brief Commits a new block of data, represented by the content BodyStream to the end + * of the existing append blob. + * + * @param content A BodyStream containing the + * content of the block to append. + * @param options Optional parameters to execute this + * function. + * @return A BlobAppendInfo describing the state of the updated append blob. + */ BlobAppendInfo AppendBlock( std::unique_ptr content, const AppendBlockOptions& options = AppendBlockOptions()); + /** + * @brief Commits a new block of data, represented by the content BodyStream to the end + * of the existing append blob. + * + * @param sourceUri Specifies the uri of the source + * blob. The value may be a uri of up to 2 KB in length that specifies a blob. The source blob + * must either be public or must be authenticated via a shared access signature. If the source + * blob is public, no authentication is required to perform the operation. + * @param options + * Optional parameters to execute this function. + * @return A BlobAppendInfo describing the + * state of the updated append blob. + */ BlobAppendInfo AppendBlockFromUri( const std::string& sourceUri, const AppendBlockFromUriOptions& options = AppendBlockFromUriOptions()) const; diff --git a/sdk/storage/inc/blobs/blob_client.hpp b/sdk/storage/inc/blobs/blob_client.hpp index 62b714e51..dc4f0dbe5 100644 --- a/sdk/storage/inc/blobs/blob_client.hpp +++ b/sdk/storage/inc/blobs/blob_client.hpp @@ -18,72 +18,237 @@ namespace Azure { namespace Storage { namespace Blobs { class AppendBlobClient; class PageBlobClient; + /** + * @brief The BlobClient allows you to manipulate Azure Storage blobs. + */ class BlobClient { public: - // connection string + /** + * @brief Initialize a new instance of BlobClient. + * + * @param connectionString A connection string includes the authentication information required + * for your application to access data in an Azure Storage account at runtime. + * @param containerName The name of the container containing this blob. + * @param blobName The name of this blob. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + * @return A new BlobClient instance. + */ static BlobClient CreateFromConnectionString( const std::string& connectionString, const std::string& containerName, const std::string& blobName, const BlobClientOptions& options = BlobClientOptions()); - // shared key auth + /** + * @brief Initialize a new instance of BlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The shared key credential used to sign + * requests. + * @param options Optional client options that define the transport pipeline + * policies for authentication, retries, etc., that are applied to every request. + */ explicit BlobClient( const std::string& blobUri, std::shared_ptr credential, const BlobClientOptions& options = BlobClientOptions()); - // token auth + /** + * @brief Initialize a new instance of BlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The token credential used to sign requests. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + */ explicit BlobClient( const std::string& blobUri, std::shared_ptr credential, const BlobClientOptions& options = BlobClientOptions()); - // anonymous/SAS/customized pipeline auth + /** + * @brief Initialize a new instance of BlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob, and possibly also a SAS token. + * @param options Optional client + * options that define the transport pipeline policies for authentication, retries, etc., that + * are applied to every request. + */ explicit BlobClient( const std::string& blobUri, const BlobClientOptions& options = BlobClientOptions()); + /** + * @brief Creates a new BlockBlobClient object with the same uri as this BlobClient. The + * new BlockBlobClient uses the same request policy pipeline as this BlobClient. + * + * + * @return A new BlockBlobClient instance. + */ BlockBlobClient GetBlockBlobClient() const; + /** + * @brief Creates a new AppendBlobClient object with the same uri as this BlobClient. + * The new AppendBlobClient uses the same request policy pipeline as this BlobClient. + * + * @return A new AppendBlobClient instance. + */ AppendBlobClient GetAppendBlobClient() const; + /** + * @brief Creates a new PageBlobClient object with the same uri as this BlobClient. + * The new PageBlobClient uses the same request policy pipeline as this BlobClient. + * + * @return A new PageBlobClient instance. + */ PageBlobClient GetPageBlobClient() const; + /** + * @brief Gets the blob's primary uri endpoint. + * + * @return The blob's + * primary uri endpoint. + */ std::string GetUri() const { return m_blobUrl.ToString(); } + /** + * @brief Initializes a new instance of the BlobClient class with an identical uri + * source but the specified snapshot timestamp. + * + * @param snapshot The snapshot + * identifier. + * @return A new BlobClient instance. + * @remarks Pass empty string to remove the snapshot returning the base blob. + */ BlobClient WithSnapshot(const std::string& snapshot) const; + /** + * @brief Returns all user-defined metadata, standard HTTP properties, and system + * properties for the blob. It does not return the content of the blob. + * + * @param + * options Optional parameters to execute this function. + * @return A BlobProperties + * describing the blob's properties. + */ BlobProperties GetProperties( const GetBlobPropertiesOptions& options = GetBlobPropertiesOptions()) const; + /** + * @brief Sets system properties on the blob. + * + * @param options Optional + * parameters to execute this function. + * @return A BlobInfo describing the updated blob. + */ BlobInfo SetHttpHeaders( const SetBlobHttpHeadersOptions& options = SetBlobHttpHeadersOptions()) const; + /** + * @brief Sets user-defined metadata for the specified blob as one or more name-value + * pairs. + * + * @param metadata Custom metadata to set for this blob. + * @param + * options Optional parameters to execute this function. + * @return A BlobInfo describing + * the updated blob. + */ BlobInfo SetMetadata( std::map metadata, const SetBlobMetadataOptions& options = SetBlobMetadataOptions()) const; + /** + * @brief Sets the tier on a blob. The operation is allowed on a page blob in a premium + * storage account and on a block blob in a blob storage or general purpose v2 account. + * + * @param Tier Indicates the tier to be set on the blob. + * @param options Optional + * parameters to execute this function. + * @return A BasicResponse on successfully setting + * the tier. + */ BasicResponse SetAccessTier( AccessTier Tier, const SetAccessTierOptions& options = SetAccessTierOptions()) const; + /** + * @brief Copies data at from the source to this blob. + * + * @param sourceUri + * Specifies the uri of the source blob. The value may a uri of up to 2 KB in length that + * specifies a blob. A source blob in the same storage account can be authenticated via Shared + * Key. However, if the source is a blob in another account, the source blob must either be + * public or must be authenticated via a shared access signature. If the source blob is public, + * no authentication is required to perform the copy operation. + * @param options Optional parameters to execute this function. + * @return A BlobCopyInfo describing the state of the copy operation. + */ BlobCopyInfo StartCopyFromUri( const std::string& sourceUri, const StartCopyFromUriOptions& options = StartCopyFromUriOptions()) const; + /** + * @brief Aborts a pending StartCopyFromUri operation, and leaves this blob with zero + * length and full metadata. + * + * @param copyId ID of the copy operation to abort. + * @param options Optional parameters to execute this function. + * @return A BasicResponse + * on successfully aborting. + */ BasicResponse AbortCopyFromUri( const std::string& copyId, const AbortCopyFromUriOptions& options = AbortCopyFromUriOptions()) const; - FlattenedDownloadProperties Download( - const DownloadBlobOptions& options = DownloadBlobOptions()) const; + /** + * @brief Downloads a blob from the service, including its metadata and properties. + * * + * @param options Optional parameters to execute this function. + * @return A + * BlobDownloadInfo describing the downloaded blob. + * BlobDownloadInfo.BodyStream contains the blob's data. + */ + BlobDownloadInfo Download(const DownloadBlobOptions& options = DownloadBlobOptions()) const; + + /** + * @brief Creates a read-only snapshot of a blob. + * + * @param options Optional + * parameters to execute this function. + * @return A BlobSnapshotInfo describing the new + * blob snapshot. + */ BlobSnapshotInfo CreateSnapshot( const CreateSnapshotOptions& options = CreateSnapshotOptions()) const; + /** + * @brief Marks the specified blob or snapshot for deletion. The blob is later deleted + * during garbage collection. Note that in order to delete a blob, you must delete all of its + * snapshots. You can delete both at the same time using DeleteBlobOptions.DeleteSnapshots. + * + * @param options Optional parameters to execute this function. + * @return A + * BasicResponse on successfully deleting. + */ BasicResponse Delete(const DeleteBlobOptions& options = DeleteBlobOptions()) const; + /** + * @brief Restores the contents and metadata of a soft deleted blob and any associated + * soft deleted snapshots. + * + * @param options Optional parameters to execute this + * function. + * @return A BasicResponse on successfully deleting. + */ BasicResponse Undelete(const UndeleteBlobOptions& options = UndeleteBlobOptions()) const; protected: diff --git a/sdk/storage/inc/blobs/blob_container_client.hpp b/sdk/storage/inc/blobs/blob_container_client.hpp index 1151d0c83..a25a5b50c 100644 --- a/sdk/storage/inc/blobs/blob_container_client.hpp +++ b/sdk/storage/inc/blobs/blob_container_client.hpp @@ -15,55 +15,176 @@ namespace Azure { namespace Storage { namespace Blobs { + /** + * The BlobContainerClient allows you to manipulate Azure Storage containers and their + * blobs. + */ class BlobContainerClient { public: - // connection string + /** + * @brief Initialize a new instance of BlobContainerClient. + * + * @param connectionString A connection string includes the authentication information required + * for your application to access data in an Azure Storage account at runtime. + * @param containerName The name of the container containing this blob. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + * @return A new BlobContainerClient instance. + */ static BlobContainerClient CreateFromConnectionString( const std::string& connectionString, const std::string& containerName, const BlobContainerClientOptions& options = BlobContainerClientOptions()); - // shared key auth + /** + * @brief Initialize a new instance of BlobContainerClient. + * + * @param containerUri A uri + * referencing the blob container that includes the name of the account and the name of the + * container. + * @param credential The shared key credential used to sign + * requests. + * @param options Optional client options that define the transport pipeline + * policies for authentication, retries, etc., that are applied to every request. + */ explicit BlobContainerClient( const std::string& containerUri, std::shared_ptr credential, const BlobContainerClientOptions& options = BlobContainerClientOptions()); - // token auth + /** + * @brief Initialize a new instance of BlobContainerClient. + * + * @param containerUri A uri + * referencing the blob container that includes the name of the account and the name of the + * container. + * @param credential The token credential used to sign requests. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + */ explicit BlobContainerClient( const std::string& containerUri, std::shared_ptr credential, const BlobContainerClientOptions& options = BlobContainerClientOptions()); - // anonymous/SAS/customized pipeline auth + /** + * @brief Initialize a new instance of BlobContainerClient. + * + * @param containerUri A uri + * referencing the blob that includes the name of the account and the name of the container, and + * possibly also a SAS token. + * @param options Optional client + * options that define the transport pipeline policies for authentication, retries, etc., that + * are applied to every request. + */ explicit BlobContainerClient( const std::string& containerUri, const BlobContainerClientOptions& options = BlobContainerClientOptions()); + /** + * @brief Create a new BlobClient object by appending blobName to the end of uri. The + * new BlobClient uses the same request policy pipeline as this BlobContainerClient. + * + * @param blobName The name of the blob. + * @return A new BlobClient instance. + */ BlobClient GetBlobClient(const std::string& blobName) const; + /** + * @brief Create a new BlockBlobClient object by appending blobName to the end of uri. + * The new BlockBlobClient uses the same request policy pipeline as this BlobContainerClient. + * + * @param blobName The name of the blob. + * @return A new BlockBlobClient instance. + */ BlockBlobClient GetBlockBlobClient(const std::string& blobName) const; + /** + * @brief Create a new AppendBlobClient object by appending blobName to the end of uri. + * The new AppendBlobClient uses the same request policy pipeline as this BlobContainerClient. + * + * @param blobName The name of the blob. + * @return A new AppendBlobClient instance. + */ AppendBlobClient GetAppendBlobClient(const std::string& blobName) const; + /** + * @brief Create a new PageBlobClient object by appending blobName to the end of uri. + * The new PageBlobClient uses the same request policy pipeline as this BlobContainerClient. + * + * @param blobName The name of the blob. + * @return A new PageBlobClient instance. + */ PageBlobClient GetPageBlobClient(const std::string& blobName) const; + /** + * @brief Gets the container's primary uri endpoint. + * + * @return The + * container's primary uri endpoint. + */ std::string GetUri() const { return m_containerUrl.ToString(); } + /** + * @brief Creates a new container under the specified account. If the container with the + * same name already exists, the operation fails. + * + * @param options Optional + * parameters to execute this function. + * @return A BlobContainerInfo describing the newly + * created blob container. + */ BlobContainerInfo Create( const CreateBlobContainerOptions& options = CreateBlobContainerOptions()) const; + /** + * @brief Marks the specified container for deletion. The container and any blobs + * contained within it are later deleted during garbage collection. + * + * @param + * options Optional parameters to execute this function. + * @return A BasicResponse if + * successful. + */ BasicResponse Delete( const DeleteBlobContainerOptions& options = DeleteBlobContainerOptions()) const; + /** + * @brief Returns all user-defined metadata and system properties for the specified + * container. The data returned does not include the container's list of blobs. + * + * @param options Optional parameters to execute this function. + * @return A + * BlobContainerProperties describing the container and its properties. + */ BlobContainerProperties GetProperties( const GetBlobContainerPropertiesOptions& options = GetBlobContainerPropertiesOptions()) const; + /** + * @brief Sets one or more user-defined name-value pairs for the specified container. + * + * @param metadata Custom metadata to set for this container. + * @param options + * Optional parameters to execute this function. + * @return A BlobContainerInfo if + * successful. + */ BlobContainerInfo SetMetadata( std::map metadata, SetBlobContainerMetadataOptions options = SetBlobContainerMetadataOptions()) const; + /** + * @brief Returns a single segment of blobs in this container, starting from the + * specified Marker, Use an empty Marker to start enumeration from the beginning and the + * NextMarker if it's not empty to make subsequent calls to ListBlobs to continue enumerating + * the blobs segment by segment. Blobs are ordered lexicographically by name. A Delimiter can be + * used to traverse a virtual hierarchy of blobs as though it were a file system. + * + * @param options Optional parameters to execute this function. + * @return A + * BlobsFlatSegment describing a segment of the blobs in the container. + */ BlobsFlatSegment ListBlobs(const ListBlobsOptions& options = ListBlobsOptions()) const; private: diff --git a/sdk/storage/inc/blobs/blob_options.hpp b/sdk/storage/inc/blobs/blob_options.hpp index 189c7dec8..4e1293dfa 100644 --- a/sdk/storage/inc/blobs/blob_options.hpp +++ b/sdk/storage/inc/blobs/blob_options.hpp @@ -19,16 +19,15 @@ namespace Azure { namespace Storage { namespace Blobs { struct ListBlobContainersOptions { Azure::Core::Context Context; - std::string Prefix; - std::string Marker; - int MaxResults = 0; + Azure::Core::Nullable Prefix; + Azure::Core::Nullable Marker; + Azure::Core::Nullable MaxResults; std::vector Include; }; struct GetUserDelegationKeyOptions { Azure::Core::Context Context; - std::string StartsOn; }; struct BlobContainerClientOptions @@ -39,15 +38,15 @@ namespace Azure { namespace Storage { namespace Blobs { struct CreateBlobContainerOptions { Azure::Core::Context Context; - PublicAccessType AccessType = PublicAccessType::Private; + Azure::Core::Nullable AccessType; std::map Metadata; }; struct DeleteBlobContainerOptions { Azure::Core::Context Context; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; struct GetBlobContainerPropertiesOptions @@ -58,16 +57,16 @@ namespace Azure { namespace Storage { namespace Blobs { struct SetBlobContainerMetadataOptions { Azure::Core::Context Context; - std::string IfModifiedSince; + Azure::Core::Nullable IfModifiedSince; }; struct ListBlobsOptions { Azure::Core::Context Context; - std::string Prefix; - std::string Delimiter; - std::string Marker; - int MaxResults = 0; + Azure::Core::Nullable Prefix; + Azure::Core::Nullable Delimiter; + Azure::Core::Nullable Marker; + Azure::Core::Nullable MaxResults; std::vector Include; }; @@ -91,10 +90,10 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetBlobPropertiesOptions { Azure::Core::Context Context; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct SetBlobHttpHeadersOptions @@ -106,81 +105,81 @@ namespace Azure { namespace Storage { namespace Blobs { std::string ContentMD5; std::string CacheControl; std::string ContentDisposition; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct SetBlobMetadataOptions { Azure::Core::Context Context; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct SetAccessTierOptions { Azure::Core::Context Context; - Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown; + Azure::Core::Nullable RehydratePriority; }; struct StartCopyFromUriOptions { Azure::Core::Context Context; std::map Metadata; - std::string LeaseId; - std::string SourceLeaseId; - AccessTier Tier = AccessTier::Unknown; - Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; - std::string SourceIfModifiedSince; - std::string SourceIfUnmodifiedSince; - std::string SourceIfMatch; - std::string SourceIfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable SourceLeaseId; + Azure::Core::Nullable Tier = AccessTier::Unknown; + Azure::Core::Nullable RehydratePriority; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfMatch; + Azure::Core::Nullable SourceIfNoneMatch; }; struct AbortCopyFromUriOptions { Azure::Core::Context Context; - std::string LeaseId; + Azure::Core::Nullable LeaseId; }; struct DownloadBlobOptions { Azure::Core::Context Context; - uint64_t Offset = std::numeric_limits::max(); // max means the whole blob - uint64_t Length = 0; // 0 means till the end - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Offset; + Azure::Core::Nullable Length; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct CreateSnapshotOptions { Azure::Core::Context Context; std::map Metadata; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct DeleteBlobOptions { Azure::Core::Context Context; - DeleteSnapshotsOption DeleteSnapshots = DeleteSnapshotsOption::None; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable DeleteSnapshots; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct UndeleteBlobOptions @@ -191,36 +190,36 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadBlobOptions { Azure::Core::Context Context; - std::string ContentMD5; - std::string ContentCRC64; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; BlobHttpHeaders Properties; std::map Metadata; - AccessTier Tier = AccessTier::Unknown; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Tier; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct StageBlockOptions { Azure::Core::Context Context; - std::string ContentMD5; - std::string ContentCRC64; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; }; struct StageBlockFromUriOptions { Azure::Core::Context Context; - uint64_t SourceOffset = std::numeric_limits::max(); - uint64_t SourceLength = 0; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string SourceIfModifiedSince; - std::string SourceIfUnmodifiedSince; - std::string SourceIfMatch; - std::string SourceIfNoneMatch; + Azure::Core::Nullable SourceOffset; + Azure::Core::Nullable SourceLength; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfMatch; + Azure::Core::Nullable SourceIfNoneMatch; }; struct CommitBlockListOptions @@ -228,21 +227,21 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; BlobHttpHeaders Properties; std::map Metadata; - AccessTier Tier = AccessTier::Unknown; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Tier; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct GetBlockListOptions { Azure::Core::Context Context; - BlockListTypeOption ListType = BlockListTypeOption::All; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable ListType; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct CreateAppendBlobOptions @@ -250,119 +249,119 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; BlobHttpHeaders Properties; std::map Metadata; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct AppendBlockOptions { Azure::Core::Context Context; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - uint64_t MaxSize = std::numeric_limits::max(); - uint64_t AppendPosition = std::numeric_limits::max(); - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable MaxSize; + Azure::Core::Nullable AppendPosition; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct AppendBlockFromUriOptions { Azure::Core::Context Context; - uint64_t SourceOffset = std::numeric_limits::max(); - uint64_t SourceLength = 0; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - uint64_t MaxSize = std::numeric_limits::max(); - uint64_t AppendPosition = std::numeric_limits::max(); - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable SourceOffset; + Azure::Core::Nullable SourceLength; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable MaxSize; + Azure::Core::Nullable AppendPosition; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct CreatePageBlobOptions { Azure::Core::Context Context; - uint64_t SequenceNumber = 0; + Azure::Core::Nullable SequenceNumber; BlobHttpHeaders Properties; std::map Metadata; - AccessTier Tier = AccessTier::Unknown; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Tier; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct UploadPagesOptions { Azure::Core::Context Context; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct UploadPagesFromUriOptions { Azure::Core::Context Context; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct ClearPagesOptions { Azure::Core::Context Context; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct ResizePageBlobOptions { Azure::Core::Context Context; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct GetPageRangesOptions { Azure::Core::Context Context; - std::string PreviousSnapshot; - std::string PreviousSnapshotUrl; - uint64_t Offset = 0; - uint64_t Length = 0; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable PreviousSnapshot; + Azure::Core::Nullable PreviousSnapshotUrl; + Azure::Core::Nullable Offset; + Azure::Core::Nullable Length; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; struct IncrementalCopyPageBlobOptions { Azure::Core::Context Context; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; }}} // namespace Azure::Storage::Blobs diff --git a/sdk/storage/inc/blobs/blob_service_client.hpp b/sdk/storage/inc/blobs/blob_service_client.hpp index dc7a1b8c5..7e38185e0 100644 --- a/sdk/storage/inc/blobs/blob_service_client.hpp +++ b/sdk/storage/inc/blobs/blob_service_client.hpp @@ -4,9 +4,9 @@ #pragma once #include "blob_options.hpp" +#include "blobs/blob_container_client.hpp" #include "common/storage_credential.hpp" #include "common/storage_url_builder.hpp" -#include "blobs/blob_container_client.hpp" #include "internal/protocol/blob_rest_client.hpp" #include @@ -14,38 +14,111 @@ namespace Azure { namespace Storage { namespace Blobs { + /** + * The BlobServiceClient allows you to manipulate Azure Storage service resources and blob + * containers. The storage account provides the top-level namespace for the Blob service. + */ class BlobServiceClient { public: - // connection string + /** + * @brief Initialize a new instance of BlobServiceClient. + * + * @param connectionString A connection string includes the authentication information required + * for your application to access data in an Azure Storage account at runtime. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + * @return A new BlobServiceClient instance. + */ static BlobServiceClient CreateFromConnectionString( const std::string& connectionString, const BlobServiceClientOptions& options = BlobServiceClientOptions()); - // shared key auth + /** + * @brief Initialize a new instance of BlobServiceClient. + * + * @param serviceUri A uri + * referencing the blob that includes the name of the account. + * @param credential The shared key credential used to sign + * requests. + * @param options Optional client options that define the transport pipeline + * policies for authentication, retries, etc., that are applied to every request. + */ explicit BlobServiceClient( const std::string& serviceUri, std::shared_ptr credential, const BlobServiceClientOptions& options = BlobServiceClientOptions()); - // token auth + /** + * @brief Initialize a new instance of BlobServiceClient. + * + * @param serviceUri A uri + * referencing the blob that includes the name of the account. + * @param credential The token credential used to sign requests. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + */ explicit BlobServiceClient( const std::string& serviceUri, std::shared_ptr credential, const BlobServiceClientOptions& options = BlobServiceClientOptions()); - // anonymous/SAS/customized pipeline auth + /** + * @brief Initialize a new instance of BlobServiceClient. + * + * @param serviceUri A uri + * referencing the blob that includes the name of the account, and possibly also a SAS token. + * @param options Optional client + * options that define the transport pipeline policies for authentication, retries, etc., that + * are applied to every request. + */ explicit BlobServiceClient( const std::string& serviceUri, const BlobServiceClientOptions& options = BlobServiceClientOptions()); + /** + * @brief Creates a new BlobContainerClient object with the same uri as this BlobServiceClient. + * The new BlobContainerClient uses the same request policy pipeline as this BlobServiceClient. + * + * + * @return A new BlobContainerClient instance. + */ BlobContainerClient GetBlobContainerClient(const std::string& containerName) const; + /** + * @brief Gets the blob service's primary uri endpoint. + * + * @return the blob + * service's primary uri endpoint. + */ std::string GetUri() const { return m_serviceUrl.ToString(); } + /** + * @brief Returns a single segment of blob containers in the storage account, starting + * from the specified Marker. Use an empty Marker to start enumeration from the beginning and + * the NextMarker if it's not empty to make subsequent calls to ListBlobContainersSegment to + * continue enumerating the containers segment by segment. Containers are ordered + * lexicographically by name. + * + * @param options Optional parameters to execute this function. + * @return A + * ListContainersSegment describing segment of the blob containers in the storage account. + */ ListContainersSegment ListBlobContainersSegment( const ListBlobContainersOptions& options = ListBlobContainersOptions()) const; + /** + * @brief Retrieves a key that can be used to delegate Active Directory authorization to + * shared access signatures. + * + * @param startsOn Start time for the key's validity. The time should be specified in UTC. + * @param expiresOn Expiration of the key's validity. + * The time should be specified in UTC. + * @param options Optional parameters to execute + * this function. + * @return A deserialized UserDelegationKey instance. + */ UserDelegationKey GetUserDelegationKey( + const std::string& startsOn, const std::string& expiresOn, const GetUserDelegationKeyOptions& options = GetUserDelegationKeyOptions()) const; diff --git a/sdk/storage/inc/blobs/internal/protocol/blob_rest_client.hpp b/sdk/storage/inc/blobs/internal/protocol/blob_rest_client.hpp index c24f0239b..26eae4352 100644 --- a/sdk/storage/inc/blobs/internal/protocol/blob_rest_client.hpp +++ b/sdk/storage/inc/blobs/internal/protocol/blob_rest_client.hpp @@ -5,10 +5,12 @@ #pragma once #include "common/storage_common.hpp" +#include "common/storage_error.hpp" #include "common/xml_wrapper.hpp" #include "context.hpp" #include "http/http.hpp" #include "http/pipeline.hpp" +#include "nullable.hpp" #include #include @@ -170,7 +172,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; }; // struct BasicResponse struct BlobAppendInfo @@ -178,15 +180,15 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - std::string ContentMD5; - std::string ContentCRC64; - uint64_t AppendOffset = std::numeric_limits::max(); - uint64_t CommittedBlockCount = std::numeric_limits::max(); - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + int64_t AppendOffset = 0; + int64_t CommittedBlockCount = 0; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct BlobAppendInfo enum class BlobArchiveStatus @@ -231,7 +233,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct BlobBlock { std::string Name; - uint64_t Size = 0; + int64_t Size = 0; }; // struct BlobBlock struct BlobContainerInfo @@ -239,7 +241,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; }; // struct BlobContainerInfo @@ -249,14 +251,14 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - std::string ContentMD5; - std::string ContentCRC64; - uint64_t SequenceNumber = 0; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable SequenceNumber; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct BlobContentInfo struct BlobHttpHeaders @@ -274,10 +276,10 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - uint64_t SequenceNumber = 0; + Azure::Core::Nullable SequenceNumber; }; // struct BlobInfo enum class BlobLeaseState @@ -370,12 +372,12 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string Snapshot; std::string ETag; std::string LastModified; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct BlobSnapshotInfo enum class BlobType @@ -429,11 +431,11 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; - std::string ContentMD5; - std::string ContentCRC64; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct BlockInfo enum class BlockListTypeOption @@ -694,10 +696,10 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - uint64_t SequenceNumber = 0; + int64_t SequenceNumber = 0; }; // struct PageBlobInfo struct PageInfo @@ -705,14 +707,14 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - std::string ContentMD5; - std::string ContentCRC64; - uint64_t SequenceNumber = 0; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + int64_t SequenceNumber = 0; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct PageInfo struct PageRangesInfoInternal @@ -720,12 +722,12 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - uint64_t BlobContentLength = 0; - std::vector> PageRanges; - std::vector> ClearRanges; + int64_t BlobContentLength = 0; + std::vector> PageRanges; + std::vector> ClearRanges; }; // struct PageRangesInfoInternal enum class PublicAccessType @@ -811,7 +813,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string SignedObjectId; std::string SignedTenantId; std::string SignedStartsOn; @@ -826,11 +828,11 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; std::string ContentType; - uint64_t ContentLength = 0; + int64_t ContentLength = 0; std::vector CommittedBlocks; std::vector UncommittedBlocks; }; // struct BlobBlockListInfo @@ -844,7 +846,7 @@ namespace Azure { namespace Storage { namespace Blobs { PublicAccessType AccessType = PublicAccessType::Private; bool HasImmutabilityPolicy = false; bool HasLegalHold = false; - std::string LeaseDuration; + Azure::Core::Nullable LeaseDuration; BlobLeaseState LeaseState = BlobLeaseState::Available; BlobLeaseStatus LeaseStatus = BlobLeaseStatus::Unlocked; }; // struct BlobContainerItem @@ -854,14 +856,14 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; std::map Metadata; PublicAccessType AccessType = PublicAccessType::Private; bool HasImmutabilityPolicy = false; bool HasLegalHold = false; - std::string LeaseDuration; + Azure::Core::Nullable LeaseDuration; BlobLeaseState LeaseState = BlobLeaseState::Available; BlobLeaseStatus LeaseStatus = BlobLeaseStatus::Unlocked; }; // struct BlobContainerProperties @@ -871,13 +873,37 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; std::string CopyId; Blobs::CopyStatus CopyStatus = Blobs::CopyStatus::Unknown; }; // struct BlobCopyInfo + struct BlobDownloadInfo + { + std::string RequestId; + std::string Date; + std::string Version; + Azure::Core::Nullable ClientRequestId; + std::unique_ptr BodyStream; + std::string ETag; + std::string LastModified; + Azure::Core::Nullable ContentRange; + BlobHttpHeaders Properties; + std::map Metadata; + Azure::Core::Nullable SequenceNumber; // only for page blob + Azure::Core::Nullable CommittedBlockCount; // only for append blob + Blobs::BlobType BlobType = Blobs::BlobType::Unknown; + Azure::Core::Nullable ContentMD5; // MD5 for the downloaded range + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseDuration; + Azure::Core::Nullable LeaseState; + Azure::Core::Nullable LeaseStatus; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; + }; // struct BlobDownloadInfo + struct BlobItem { std::string Name; @@ -888,15 +914,15 @@ namespace Azure { namespace Storage { namespace Blobs { std::string CreationTime; std::string LastModified; std::string ETag; - uint64_t ContentLength = 0; + int64_t ContentLength = 0; Blobs::BlobType BlobType = Blobs::BlobType::Unknown; AccessTier Tier = AccessTier::Unknown; bool AccessTierInferred = true; BlobLeaseStatus LeaseStatus = BlobLeaseStatus::Unlocked; BlobLeaseState LeaseState = BlobLeaseState::Available; - std::string LeaseDuration; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; + Azure::Core::Nullable LeaseDuration; + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; }; // struct BlobItem struct BlobProperties @@ -904,68 +930,49 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; std::string CreationTime; std::map Metadata; Blobs::BlobType BlobType = Blobs::BlobType::Unknown; - std::string LeaseDuration; - BlobLeaseState LeaseState = BlobLeaseState::Available; - BlobLeaseStatus LeaseStatus = BlobLeaseStatus::Unlocked; - uint64_t ContentLength = 0; + Azure::Core::Nullable LeaseDuration; + Azure::Core::Nullable LeaseState; + Azure::Core::Nullable LeaseStatus; + int64_t ContentLength = 0; std::string ContentType; std::string ContentEncoding; std::string ContentLanguage; std::string ContentMD5; std::string CacheControl; std::string ContentDisposition; - uint64_t SequenceNumber = 0; // only for page blob - int CommittedBlockCount = 0; // only for append blob - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; - AccessTier Tier = AccessTier::Unknown; - bool AccessTierInferred = true; - BlobArchiveStatus ArchiveStatus = BlobArchiveStatus::Unknown; - std::string AccessTierChangeTime; + Azure::Core::Nullable SequenceNumber; // only for page blob + Azure::Core::Nullable CommittedBlockCount; // only for append blob + Azure::Core::Nullable ServerEncrypted; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable Tier; + Azure::Core::Nullable AccessTierInferred; + Azure::Core::Nullable ArchiveStatus; + Azure::Core::Nullable AccessTierChangeTime; + Azure::Core::Nullable CopyId; + Azure::Core::Nullable CopySource; + Azure::Core::Nullable CopyStatus; + Azure::Core::Nullable CopyProgress; + Azure::Core::Nullable CopyCompletionTime; }; // struct BlobProperties - struct FlattenedDownloadProperties - { - std::string RequestId; - std::string Date; - std::string Version; - std::string ClientRequestId; - std::unique_ptr BodyStream; - std::string ETag; - std::string LastModified; - std::string ContentRange; - BlobHttpHeaders Properties; - std::map Metadata; - uint64_t SequenceNumber = 0; // only for page blob - uint64_t CommittedBlockCount = 0; // only for append blob - Blobs::BlobType BlobType = Blobs::BlobType::Unknown; - std::string ContentMD5; // MD5 for the downloaded range - std::string ContentCRC64; - std::string LeaseDuration; - BlobLeaseState LeaseState = BlobLeaseState::Available; - BlobLeaseStatus LeaseStatus = BlobLeaseStatus::Unlocked; - bool ServerEncrypted = true; - std::string EncryptionKeySHA256; - }; // struct FlattenedDownloadProperties - struct BlobsFlatSegment { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ServiceEndpoint; std::string Container; std::string Prefix; std::string Marker; std::string NextMarker; - int MaxResults = 0; + Azure::Core::Nullable MaxResults; std::string Delimiter; std::vector BlobItems; }; // struct BlobsFlatSegment @@ -975,12 +982,12 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ServiceEndpoint; std::string Prefix; std::string Marker; std::string NextMarker; - int MaxResults = 0; + Azure::Core::Nullable MaxResults; std::vector BlobContainerItems; }; // struct ListContainersSegment @@ -990,10 +997,11 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct ListBlobContainersOptions { - std::string Prefix; - std::string Marker; - int MaxResults = 0; - ListBlobContainersIncludeOption IncludeMetadata = ListBlobContainersIncludeOption::None; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable Prefix; + Azure::Core::Nullable Marker; + Azure::Core::Nullable MaxResults; + Azure::Core::Nullable IncludeMetadata; }; // struct ListBlobContainersOptions static Azure::Core::Http::Request ListBlobContainersConstructRequest( @@ -1003,52 +1011,57 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddQueryParameter("comp", "list"); - if (!options.Prefix.empty()) + if (options.Prefix.HasValue()) { - request.AddQueryParameter("prefix", options.Prefix); + request.AddQueryParameter("prefix", options.Prefix.GetValue()); } - if (!options.Marker.empty()) + if (options.Marker.HasValue()) { - request.AddQueryParameter("marker", options.Marker); + request.AddQueryParameter("marker", options.Marker.GetValue()); } - if (options.MaxResults != 0) + if (options.MaxResults.HasValue()) { - request.AddQueryParameter("maxresults", std::to_string(options.MaxResults)); + request.AddQueryParameter("maxresults", std::to_string(options.MaxResults.GetValue())); } - std::string list_blob_containers_include_option - = ListBlobContainersIncludeOptionToString(options.IncludeMetadata); - if (!list_blob_containers_include_option.empty()) + if (options.IncludeMetadata.HasValue()) { + std::string list_blob_containers_include_option + = ListBlobContainersIncludeOptionToString(options.IncludeMetadata.GetValue()); request.AddQueryParameter("include", list_blob_containers_include_option); } return request; } static ListContainersSegment ListBlobContainersParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; ListContainersSegment response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - auto bodyStream = http_response.GetBodyStream(); + auto bodyStream = httpResponse.GetBodyStream(); std::vector bodyContent(static_cast(bodyStream->Length())); bodyStream->Read(&bodyContent[0], bodyContent.size()); XmlReader reader(reinterpret_cast(bodyContent.data()), bodyContent.size()); response = ListContainersSegmentFromXml(reader); - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -1060,12 +1073,12 @@ namespace Azure { namespace Storage { namespace Blobs { ListBlobContainersOptions& options) { auto request = ListBlobContainersConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return ListBlobContainersParseResponse(*response); + return ListBlobContainersParseResponse(pipeline.Send(context, request)); } struct GetUserDelegationKeyOptions { + Azure::Core::Nullable Timeout; std::string StartsOn; std::string ExpiresOn; }; // struct GetUserDelegationKeyOptions @@ -1078,7 +1091,7 @@ namespace Azure { namespace Storage { namespace Blobs { GetUserDelegationKeyOptionsToXml(writer, options); std::string xml_body = writer.GetDocument(); std::vector body_buffer(xml_body.begin(), xml_body.end()); - uint64_t body_buffer_length = body_buffer.size(); + auto body_buffer_length = body_buffer.size(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Post, url, @@ -1087,34 +1100,38 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddQueryParameter("restype", "service"); request.AddQueryParameter("comp", "userdelegationkey"); request.AddHeader("x-ms-version", "2019-07-07"); - unused(options); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } return request; } static UserDelegationKey GetUserDelegationKeyParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; UserDelegationKey response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - auto bodyStream = http_response.GetBodyStream(); + auto bodyStream = httpResponse.GetBodyStream(); std::vector bodyContent(static_cast(bodyStream->Length())); bodyStream->Read(&bodyContent[0], bodyContent.size()); XmlReader reader(reinterpret_cast(bodyContent.data()), bodyContent.size()); response = UserDelegationKeyFromXml(reader); - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -1126,8 +1143,7 @@ namespace Azure { namespace Storage { namespace Blobs { GetUserDelegationKeyOptions& options) { auto request = GetUserDelegationKeyConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return GetUserDelegationKeyParseResponse(*response); + return GetUserDelegationKeyParseResponse(pipeline.Send(context, request)); } private: @@ -1571,7 +1587,8 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct CreateOptions { - PublicAccessType AccessType = PublicAccessType::Private; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable AccessType; std::map Metadata; }; // struct CreateOptions @@ -1583,6 +1600,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("restype", "container"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } std::set metadataKeys; for (const auto& pair : options.Metadata) { @@ -1597,35 +1618,37 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - auto options_accesstype_str = PublicAccessTypeToString(options.AccessType); - if (!options_accesstype_str.empty()) + if (options.AccessType.HasValue()) { - request.AddHeader("x-ms-blob-public-access", options_accesstype_str); + request.AddHeader( + "x-ms-blob-public-access", PublicAccessTypeToString(options.AccessType.GetValue())); } return request; } - static BlobContainerInfo CreateParseResponse(Azure::Core::Http::Response& http_response) + static BlobContainerInfo CreateParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContainerInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); return response; } @@ -1636,14 +1659,14 @@ namespace Azure { namespace Storage { namespace Blobs { CreateOptions& options) { auto request = CreateConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CreateParseResponse(*response); + return CreateParseResponse(pipeline.Send(context, request)); } struct DeleteOptions { - std::string IfModifiedSince; - std::string IfUnmodifiedSince; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct DeleteOptions static Azure::Core::Http::Request DeleteConstructRequest( @@ -1654,35 +1677,41 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("restype", "container"); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.IfModifiedSince.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + } + if (options.IfUnmodifiedSince.HasValue()) + { + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } return request; } - static BasicResponse DeleteParseResponse(Azure::Core::Http::Response& http_response) + static BasicResponse DeleteParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BasicResponse response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 202)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -1694,15 +1723,15 @@ namespace Azure { namespace Storage { namespace Blobs { DeleteOptions& options) { auto request = DeleteConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return DeleteParseResponse(*response); + return DeleteParseResponse(pipeline.Send(context, request)); } struct GetPropertiesOptions { - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; }; // struct GetPropertiesOptions static Azure::Core::Http::Request GetPropertiesConstructRequest( @@ -1713,73 +1742,72 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("restype", "container"); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.EncryptionKey.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); + } + if (options.EncryptionAlgorithm.HasValue()) + { + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } return request; } static BlobContainerProperties GetPropertiesParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContainerProperties response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - for (auto i = http_response.GetHeaders().lower_bound("x-ms-meta-"); - i != http_response.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + for (auto i = httpResponse.GetHeaders().lower_bound("x-ms-meta-"); + i != httpResponse.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; ++i) { response.Metadata.emplace(i->first.substr(10), i->second); } - auto response_accesstype_iterator - = http_response.GetHeaders().find("x-ms-blob-public-access"); - if (response_accesstype_iterator != http_response.GetHeaders().end()) + auto response_access_type_iterator + = httpResponse.GetHeaders().find("x-ms-blob-public-access"); + if (response_access_type_iterator != httpResponse.GetHeaders().end()) { - response.AccessType = PublicAccessTypeFromString(response_accesstype_iterator->second); + response.AccessType = PublicAccessTypeFromString(response_access_type_iterator->second); } response.HasImmutabilityPolicy - = http_response.GetHeaders().at("x-ms-has-immutability-policy") == "true"; - response.HasLegalHold = http_response.GetHeaders().at("x-ms-has-legal-hold") == "true"; - auto response_leasestatus_iterator = http_response.GetHeaders().find("x-ms-lease-status"); - if (response_leasestatus_iterator != http_response.GetHeaders().end()) + = httpResponse.GetHeaders().at("x-ms-has-immutability-policy") == "true"; + response.HasLegalHold = httpResponse.GetHeaders().at("x-ms-has-legal-hold") == "true"; + response.LeaseStatus + = BlobLeaseStatusFromString(httpResponse.GetHeaders().at("x-ms-lease-status")); + response.LeaseState + = BlobLeaseStateFromString(httpResponse.GetHeaders().at("x-ms-lease-state")); + auto response_lease_duration_iterator + = httpResponse.GetHeaders().find("x-ms-lease-duration"); + if (response_lease_duration_iterator != httpResponse.GetHeaders().end()) { - response.LeaseStatus = BlobLeaseStatusFromString(response_leasestatus_iterator->second); - } - auto response_leasestate_iterator = http_response.GetHeaders().find("x-ms-lease-state"); - if (response_leasestate_iterator != http_response.GetHeaders().end()) - { - response.LeaseState = BlobLeaseStateFromString(response_leasestate_iterator->second); - } - auto response_leaseduration_iterator - = http_response.GetHeaders().find("x-ms-lease-duration"); - if (response_leaseduration_iterator != http_response.GetHeaders().end()) - { - response.LeaseDuration = response_leaseduration_iterator->second; + response.LeaseDuration = response_lease_duration_iterator->second; } return response; } @@ -1791,14 +1819,14 @@ namespace Azure { namespace Storage { namespace Blobs { GetPropertiesOptions& options) { auto request = GetPropertiesConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return GetPropertiesParseResponse(*response); + return GetPropertiesParseResponse(pipeline.Send(context, request)); } struct SetMetadataOptions { + Azure::Core::Nullable Timeout; std::map Metadata; - std::string IfModifiedSince; + Azure::Core::Nullable IfModifiedSince; }; // struct SetMetadataOptions static Azure::Core::Http::Request SetMetadataConstructRequest( @@ -1810,6 +1838,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddQueryParameter("restype", "container"); request.AddQueryParameter("comp", "metadata"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } std::set metadataKeys; for (const auto& pair : options.Metadata) { @@ -1824,34 +1856,36 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } return request; } - static BlobContainerInfo SetMetadataParseResponse(Azure::Core::Http::Response& http_response) + static BlobContainerInfo SetMetadataParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContainerInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); return response; } @@ -1862,16 +1896,16 @@ namespace Azure { namespace Storage { namespace Blobs { SetMetadataOptions& options) { auto request = SetMetadataConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return SetMetadataParseResponse(*response); + return SetMetadataParseResponse(pipeline.Send(context, request)); } struct ListBlobsOptions { - std::string Prefix; - std::string Delimiter; - std::string Marker; - int MaxResults = 0; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable Prefix; + Azure::Core::Nullable Delimiter; + Azure::Core::Nullable Marker; + Azure::Core::Nullable MaxResults; std::vector Include; }; // struct ListBlobsOptions @@ -1882,23 +1916,27 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddQueryParameter("restype", "container"); request.AddQueryParameter("comp", "list"); - if (!options.Prefix.empty()) + if (options.Prefix.HasValue()) { - request.AddQueryParameter("prefix", options.Prefix); + request.AddQueryParameter("prefix", options.Prefix.GetValue()); } - if (!options.Delimiter.empty()) + if (options.Delimiter.HasValue()) { - request.AddQueryParameter("delimiter", options.Delimiter); + request.AddQueryParameter("delimiter", options.Delimiter.GetValue()); } - if (!options.Marker.empty()) + if (options.Marker.HasValue()) { - request.AddQueryParameter("marker", options.Marker); + request.AddQueryParameter("marker", options.Marker.GetValue()); } - if (options.MaxResults != 0) + if (options.MaxResults.HasValue()) { - request.AddQueryParameter("maxresults", std::to_string(options.MaxResults)); + request.AddQueryParameter("maxresults", std::to_string(options.MaxResults.GetValue())); } std::string options_include_str; for (auto i : options.Include) @@ -1916,29 +1954,31 @@ namespace Azure { namespace Storage { namespace Blobs { return request; } - static BlobsFlatSegment ListBlobsParseResponse(Azure::Core::Http::Response& http_response) + static BlobsFlatSegment ListBlobsParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobsFlatSegment response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - auto bodyStream = http_response.GetBodyStream(); + auto bodyStream = httpResponse.GetBodyStream(); std::vector bodyContent(static_cast(bodyStream->Length())); bodyStream->Read(&bodyContent[0], bodyContent.size()); XmlReader reader(reinterpret_cast(bodyContent.data()), bodyContent.size()); response = BlobsFlatSegmentFromXml(reader); - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -1950,8 +1990,7 @@ namespace Azure { namespace Storage { namespace Blobs { ListBlobsOptions& options) { auto request = ListBlobsConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return ListBlobsParseResponse(*response); + return ListBlobsParseResponse(pipeline.Send(context, request)); } private: @@ -2309,7 +2348,7 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_ContentLength) { - ret.ContentLength = std::stoull(node.Value); + ret.ContentLength = std::stoll(node.Value); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -2404,14 +2443,15 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct DownloadOptions { - std::pair Range; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable> Range; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct DownloadOptions static Azure::Core::Http::Request DownloadConstructRequest( @@ -2421,197 +2461,203 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); - if (options.Range.first == std::numeric_limits::max()) + if (options.Timeout.HasValue()) { - // do nothing + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - else if (options.Range.second == std::numeric_limits::max()) + if (options.Range.HasValue()) { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-"); + auto startOffset = options.Range.GetValue().first; + auto endOffset = options.Range.GetValue().second; + if (endOffset != std::numeric_limits::max()) + { + request.AddHeader( + "x-ms-range", + "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); + } + else + { + request.AddHeader("x-ms-range", "bytes=" + std::to_string(startOffset) + "-"); + } } - else + if (options.EncryptionKey.HasValue()) { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); - } - if (!options.IfNoneMatch.empty()) - { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static FlattenedDownloadProperties DownloadParseResponse( - Azure::Core::Http::Response& http_response) + static BlobDownloadInfo DownloadParseResponse( + std::unique_ptr pHttpResponse) { - FlattenedDownloadProperties response; + Azure::Core::Http::Response& httpResponse = *pHttpResponse; + BlobDownloadInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200 || http_status_code == 206)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_properties_contenttype_iterator - = http_response.GetHeaders().find("Content-Type"); - if (response_properties_contenttype_iterator != http_response.GetHeaders().end()) + auto response_properties_content_type_iterator + = httpResponse.GetHeaders().find("Content-Type"); + if (response_properties_content_type_iterator != httpResponse.GetHeaders().end()) { - response.Properties.ContentType = response_properties_contenttype_iterator->second; + response.Properties.ContentType = response_properties_content_type_iterator->second; } - auto response_properties_contentencoding_iterator - = http_response.GetHeaders().find("Content-Encoding"); - if (response_properties_contentencoding_iterator != http_response.GetHeaders().end()) + auto response_properties_content_encoding_iterator + = httpResponse.GetHeaders().find("Content-Encoding"); + if (response_properties_content_encoding_iterator != httpResponse.GetHeaders().end()) { response.Properties.ContentEncoding - = response_properties_contentencoding_iterator->second; + = response_properties_content_encoding_iterator->second; } - auto response_properties_contentlanguage_iterator - = http_response.GetHeaders().find("Content-Language"); - if (response_properties_contentlanguage_iterator != http_response.GetHeaders().end()) + auto response_properties_content_language_iterator + = httpResponse.GetHeaders().find("Content-Language"); + if (response_properties_content_language_iterator != httpResponse.GetHeaders().end()) { response.Properties.ContentLanguage - = response_properties_contentlanguage_iterator->second; + = response_properties_content_language_iterator->second; } - auto response_properties_cachecontrol_iterator - = http_response.GetHeaders().find("Cache-Control"); - if (response_properties_cachecontrol_iterator != http_response.GetHeaders().end()) + auto response_properties_cache_control_iterator + = httpResponse.GetHeaders().find("Cache-Control"); + if (response_properties_cache_control_iterator != httpResponse.GetHeaders().end()) { - response.Properties.CacheControl = response_properties_cachecontrol_iterator->second; + response.Properties.CacheControl = response_properties_cache_control_iterator->second; } - auto response_properties_contentmd5_iterator - = http_response.GetHeaders().find("Content-MD5"); - if (response_properties_contentmd5_iterator != http_response.GetHeaders().end()) + auto response_properties_content_md5_iterator + = httpResponse.GetHeaders().find("Content-MD5"); + if (response_properties_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.Properties.ContentMD5 = response_properties_contentmd5_iterator->second; + response.Properties.ContentMD5 = response_properties_content_md5_iterator->second; } - auto response_properties_contentdisposition_iterator - = http_response.GetHeaders().find("Content-Disposition"); - if (response_properties_contentdisposition_iterator != http_response.GetHeaders().end()) + auto response_properties_content_disposition_iterator + = httpResponse.GetHeaders().find("Content-Disposition"); + if (response_properties_content_disposition_iterator != httpResponse.GetHeaders().end()) { response.Properties.ContentDisposition - = response_properties_contentdisposition_iterator->second; + = response_properties_content_disposition_iterator->second; } - for (auto i = http_response.GetHeaders().lower_bound("x-ms-meta-"); - i != http_response.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; + for (auto i = httpResponse.GetHeaders().lower_bound("x-ms-meta-"); + i != httpResponse.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; ++i) { response.Metadata.emplace(i->first.substr(10), i->second); } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } - auto response_leasestatus_iterator = http_response.GetHeaders().find("x-ms-lease-status"); - if (response_leasestatus_iterator != http_response.GetHeaders().end()) + auto response_lease_status_iterator = httpResponse.GetHeaders().find("x-ms-lease-status"); + if (response_lease_status_iterator != httpResponse.GetHeaders().end()) { - response.LeaseStatus = BlobLeaseStatusFromString(response_leasestatus_iterator->second); + response.LeaseStatus = BlobLeaseStatusFromString(response_lease_status_iterator->second); } - auto response_leasestate_iterator = http_response.GetHeaders().find("x-ms-lease-state"); - if (response_leasestate_iterator != http_response.GetHeaders().end()) + auto response_lease_state_iterator = httpResponse.GetHeaders().find("x-ms-lease-state"); + if (response_lease_state_iterator != httpResponse.GetHeaders().end()) { - response.LeaseState = BlobLeaseStateFromString(response_leasestate_iterator->second); + response.LeaseState = BlobLeaseStateFromString(response_lease_state_iterator->second); } - auto response_leaseduration_iterator - = http_response.GetHeaders().find("x-ms-lease-duration"); - if (response_leaseduration_iterator != http_response.GetHeaders().end()) + auto response_lease_duration_iterator + = httpResponse.GetHeaders().find("x-ms-lease-duration"); + if (response_lease_duration_iterator != httpResponse.GetHeaders().end()) { - response.LeaseDuration = response_leaseduration_iterator->second; + response.LeaseDuration = response_lease_duration_iterator->second; } - auto response_contentrange_iterator = http_response.GetHeaders().find("Content-Range"); - if (response_contentrange_iterator != http_response.GetHeaders().end()) + auto response_content_range_iterator = httpResponse.GetHeaders().find("Content-Range"); + if (response_content_range_iterator != httpResponse.GetHeaders().end()) { - response.ContentRange = response_contentrange_iterator->second; + response.ContentRange = response_content_range_iterator->second; } - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + auto response_sequence_number_iterator + = httpResponse.GetHeaders().find("x-ms-blob-sequence-number"); + if (response_sequence_number_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.SequenceNumber = std::stoll(response_sequence_number_iterator->second); } - auto response_committedblockcount_iterator - = http_response.GetHeaders().find("x-ms-blob-committed-block-count"); - if (response_committedblockcount_iterator != http_response.GetHeaders().end()) + auto response_committed_block_count_iterator + = httpResponse.GetHeaders().find("x-ms-blob-committed-block-count"); + if (response_committed_block_count_iterator != httpResponse.GetHeaders().end()) { - response.CommittedBlockCount = std::stoull(response_committedblockcount_iterator->second); + response.CommittedBlockCount + = std::stoll(response_committed_block_count_iterator->second); } - response.BlobType = BlobTypeFromString(http_response.GetHeaders().at("x-ms-blob-type")); - response.BodyStream = http_response.GetBodyStream(); + response.BlobType = BlobTypeFromString(httpResponse.GetHeaders().at("x-ms-blob-type")); + response.BodyStream = httpResponse.GetBodyStream(); return response; } - static FlattenedDownloadProperties Download( + static BlobDownloadInfo Download( Azure::Core::Context context, Azure::Core::Http::HttpPipeline& pipeline, const std::string& url, DownloadOptions& options) { auto request = DownloadConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return DownloadParseResponse(*response); + return DownloadParseResponse(pipeline.Send(context, request)); } struct DeleteOptions { - DeleteSnapshotsOption DeleteSnapshots = DeleteSnapshotsOption::None; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable DeleteSnapshots; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct DeleteOptions static Azure::Core::Http::Request DeleteConstructRequest( @@ -2621,48 +2667,55 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Delete, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); - auto options_deletesnapshots_str = DeleteSnapshotsOptionToString(options.DeleteSnapshots); - if (!options_deletesnapshots_str.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("x-ms-delete-snapshots", options_deletesnapshots_str); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.DeleteSnapshots.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader( + "x-ms-delete-snapshots", + DeleteSnapshotsOptionToString(options.DeleteSnapshots.GetValue())); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BasicResponse DeleteParseResponse(Azure::Core::Http::Response& http_response) + static BasicResponse DeleteParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BasicResponse response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 202)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -2674,12 +2727,12 @@ namespace Azure { namespace Storage { namespace Blobs { DeleteOptions& options) { auto request = DeleteConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return DeleteParseResponse(*response); + return DeleteParseResponse(pipeline.Send(context, request)); } struct UndeleteOptions { + Azure::Core::Nullable Timeout; }; // struct UndeleteOptions static Azure::Core::Http::Request UndeleteConstructRequest( @@ -2689,29 +2742,34 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddQueryParameter("comp", "undelete"); - unused(options); return request; } - static BasicResponse UndeleteParseResponse(Azure::Core::Http::Response& http_response) + static BasicResponse UndeleteParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BasicResponse response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -2723,16 +2781,16 @@ namespace Azure { namespace Storage { namespace Blobs { UndeleteOptions& options) { auto request = UndeleteConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return UndeleteParseResponse(*response); + return UndeleteParseResponse(pipeline.Send(context, request)); } struct GetPropertiesOptions { - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct GetPropertiesOptions static Azure::Core::Http::Request GetPropertiesConstructRequest( @@ -2742,151 +2800,183 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.IfModifiedSince.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobProperties GetPropertiesParseResponse(Azure::Core::Http::Response& http_response) + static BlobProperties GetPropertiesParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobProperties response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - response.CreationTime = http_response.GetHeaders().at("x-ms-creation-time"); - for (auto i = http_response.GetHeaders().lower_bound("x-ms-meta-"); - i != http_response.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.CreationTime = httpResponse.GetHeaders().at("x-ms-creation-time"); + for (auto i = httpResponse.GetHeaders().lower_bound("x-ms-meta-"); + i != httpResponse.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; ++i) { response.Metadata.emplace(i->first.substr(10), i->second); } - response.BlobType = BlobTypeFromString(http_response.GetHeaders().at("x-ms-blob-type")); - auto response_leasestatus_iterator = http_response.GetHeaders().find("x-ms-lease-status"); - if (response_leasestatus_iterator != http_response.GetHeaders().end()) + response.BlobType = BlobTypeFromString(httpResponse.GetHeaders().at("x-ms-blob-type")); + auto response_lease_status_iterator = httpResponse.GetHeaders().find("x-ms-lease-status"); + if (response_lease_status_iterator != httpResponse.GetHeaders().end()) { - response.LeaseStatus = BlobLeaseStatusFromString(response_leasestatus_iterator->second); + response.LeaseStatus = BlobLeaseStatusFromString(response_lease_status_iterator->second); } - auto response_leasestate_iterator = http_response.GetHeaders().find("x-ms-lease-state"); - if (response_leasestate_iterator != http_response.GetHeaders().end()) + auto response_lease_state_iterator = httpResponse.GetHeaders().find("x-ms-lease-state"); + if (response_lease_state_iterator != httpResponse.GetHeaders().end()) { - response.LeaseState = BlobLeaseStateFromString(response_leasestate_iterator->second); + response.LeaseState = BlobLeaseStateFromString(response_lease_state_iterator->second); } - auto response_leaseduration_iterator - = http_response.GetHeaders().find("x-ms-lease-duration"); - if (response_leaseduration_iterator != http_response.GetHeaders().end()) + auto response_lease_duration_iterator + = httpResponse.GetHeaders().find("x-ms-lease-duration"); + if (response_lease_duration_iterator != httpResponse.GetHeaders().end()) { - response.LeaseDuration = response_leaseduration_iterator->second; + response.LeaseDuration = response_lease_duration_iterator->second; } - response.ContentLength = std::stoull(http_response.GetHeaders().at("Content-Length")); - auto response_contenttype_iterator = http_response.GetHeaders().find("Content-Type"); - if (response_contenttype_iterator != http_response.GetHeaders().end()) + response.ContentLength = std::stoll(httpResponse.GetHeaders().at("Content-Length")); + auto response_content_type_iterator = httpResponse.GetHeaders().find("Content-Type"); + if (response_content_type_iterator != httpResponse.GetHeaders().end()) { - response.ContentType = response_contenttype_iterator->second; + response.ContentType = response_content_type_iterator->second; } - auto response_contentencoding_iterator - = http_response.GetHeaders().find("Content-Encoding"); - if (response_contentencoding_iterator != http_response.GetHeaders().end()) + auto response_content_encoding_iterator + = httpResponse.GetHeaders().find("Content-Encoding"); + if (response_content_encoding_iterator != httpResponse.GetHeaders().end()) { - response.ContentEncoding = response_contentencoding_iterator->second; + response.ContentEncoding = response_content_encoding_iterator->second; } - auto response_contentlanguage_iterator - = http_response.GetHeaders().find("Content-Language"); - if (response_contentlanguage_iterator != http_response.GetHeaders().end()) + auto response_content_language_iterator + = httpResponse.GetHeaders().find("Content-Language"); + if (response_content_language_iterator != httpResponse.GetHeaders().end()) { - response.ContentLanguage = response_contentlanguage_iterator->second; + response.ContentLanguage = response_content_language_iterator->second; } - auto response_cachecontrol_iterator = http_response.GetHeaders().find("Cache-Control"); - if (response_cachecontrol_iterator != http_response.GetHeaders().end()) + auto response_cache_control_iterator = httpResponse.GetHeaders().find("Cache-Control"); + if (response_cache_control_iterator != httpResponse.GetHeaders().end()) { - response.CacheControl = response_cachecontrol_iterator->second; + response.CacheControl = response_cache_control_iterator->second; } - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentdisposition_iterator - = http_response.GetHeaders().find("Content-Disposition"); - if (response_contentdisposition_iterator != http_response.GetHeaders().end()) + auto response_content_disposition_iterator + = httpResponse.GetHeaders().find("Content-Disposition"); + if (response_content_disposition_iterator != httpResponse.GetHeaders().end()) { - response.ContentDisposition = response_contentdisposition_iterator->second; + response.ContentDisposition = response_content_disposition_iterator->second; } - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + auto response_sequence_number_iterator + = httpResponse.GetHeaders().find("x-ms-blob-sequence-number"); + if (response_sequence_number_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.SequenceNumber = std::stoll(response_sequence_number_iterator->second); } - auto response_committedblockcount_iterator - = http_response.GetHeaders().find("x-ms-blob-committed-block-count"); - if (response_committedblockcount_iterator != http_response.GetHeaders().end()) + auto response_committed_block_count_iterator + = httpResponse.GetHeaders().find("x-ms-blob-committed-block-count"); + if (response_committed_block_count_iterator != httpResponse.GetHeaders().end()) { - response.CommittedBlockCount = std::stoi(response_committedblockcount_iterator->second); + response.CommittedBlockCount = std::stoi(response_committed_block_count_iterator->second); } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } - auto response_tier_iterator = http_response.GetHeaders().find("x-ms-access-tier"); - if (response_tier_iterator != http_response.GetHeaders().end()) + auto response_tier_iterator = httpResponse.GetHeaders().find("x-ms-access-tier"); + if (response_tier_iterator != httpResponse.GetHeaders().end()) { response.Tier = AccessTierFromString(response_tier_iterator->second); } - auto response_accesstierinferred_iterator - = http_response.GetHeaders().find("x-ms-access-tier-inferred"); - if (response_accesstierinferred_iterator != http_response.GetHeaders().end()) + auto response_access_tier_inferred_iterator + = httpResponse.GetHeaders().find("x-ms-access-tier-inferred"); + if (response_access_tier_inferred_iterator != httpResponse.GetHeaders().end()) { - response.AccessTierInferred = response_accesstierinferred_iterator->second == "true"; + response.AccessTierInferred = response_access_tier_inferred_iterator->second == "true"; } - auto response_archivestatus_iterator - = http_response.GetHeaders().find("x-ms-archive-status"); - if (response_archivestatus_iterator != http_response.GetHeaders().end()) + auto response_archive_status_iterator + = httpResponse.GetHeaders().find("x-ms-archive-status"); + if (response_archive_status_iterator != httpResponse.GetHeaders().end()) { response.ArchiveStatus - = BlobArchiveStatusFromString(response_archivestatus_iterator->second); + = BlobArchiveStatusFromString(response_archive_status_iterator->second); } - auto response_accesstierchangetime_iterator - = http_response.GetHeaders().find("x-ms-access-tier-change-time"); - if (response_accesstierchangetime_iterator != http_response.GetHeaders().end()) + auto response_access_tier_change_time_iterator + = httpResponse.GetHeaders().find("x-ms-access-tier-change-time"); + if (response_access_tier_change_time_iterator != httpResponse.GetHeaders().end()) { - response.AccessTierChangeTime = response_accesstierchangetime_iterator->second; + response.AccessTierChangeTime = response_access_tier_change_time_iterator->second; + } + auto response_copy_id_iterator = httpResponse.GetHeaders().find("x-ms-copy-id"); + if (response_copy_id_iterator != httpResponse.GetHeaders().end()) + { + response.CopyId = response_copy_id_iterator->second; + } + auto response_copy_source_iterator = httpResponse.GetHeaders().find("x-ms-copy-source"); + if (response_copy_source_iterator != httpResponse.GetHeaders().end()) + { + response.CopySource = response_copy_source_iterator->second; + } + auto response_copy_status_iterator = httpResponse.GetHeaders().find("x-ms-copy-status"); + if (response_copy_status_iterator != httpResponse.GetHeaders().end()) + { + response.CopyStatus = CopyStatusFromString(response_copy_status_iterator->second); + } + auto response_copy_progress_iterator = httpResponse.GetHeaders().find("x-ms-copy-progress"); + if (response_copy_progress_iterator != httpResponse.GetHeaders().end()) + { + response.CopyProgress = response_copy_progress_iterator->second; + } + auto response_copy_completion_time_iterator + = httpResponse.GetHeaders().find("x-ms-copy-completion-time"); + if (response_copy_completion_time_iterator != httpResponse.GetHeaders().end()) + { + response.CopyCompletionTime = response_copy_completion_time_iterator->second; } return response; } @@ -2898,25 +2988,25 @@ namespace Azure { namespace Storage { namespace Blobs { GetPropertiesOptions& options) { auto request = GetPropertiesConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return GetPropertiesParseResponse(*response); + return GetPropertiesParseResponse(pipeline.Send(context, request)); } struct SetHttpHeadersOptions { + Azure::Core::Nullable Timeout; std::string ContentType; std::string ContentEncoding; std::string ContentLanguage; std::string ContentMD5; std::string CacheControl; std::string ContentDisposition; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct SetHttpHeadersOptions static Azure::Core::Http::Request SetHttpHeadersConstructRequest( @@ -2927,6 +3017,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } if (!options.ContentType.empty()) { request.AddHeader("x-ms-blob-content-type", options.ContentType); @@ -2951,63 +3045,65 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-content-disposition", options.ContentDisposition); } - if (!options.EncryptionKey.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobInfo SetHttpHeadersParseResponse(Azure::Core::Http::Response& http_response) + static BlobInfo SetHttpHeadersParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_sequence_number_iterator + = httpResponse.GetHeaders().find("x-ms-blob-sequence-number"); + if (response_sequence_number_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.SequenceNumber = std::stoll(response_sequence_number_iterator->second); } return response; } @@ -3019,20 +3115,20 @@ namespace Azure { namespace Storage { namespace Blobs { SetHttpHeadersOptions& options) { auto request = SetHttpHeadersConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return SetHttpHeadersParseResponse(*response); + return SetHttpHeadersParseResponse(pipeline.Send(context, request)); } struct SetMetadataOptions { + Azure::Core::Nullable Timeout; std::map Metadata; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct SetMetadataOptions static Azure::Core::Http::Request SetMetadataConstructRequest( @@ -3043,6 +3139,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "metadata"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } std::set metadataKeys; for (const auto& pair : options.Metadata) { @@ -3057,58 +3157,60 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.EncryptionKey.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobInfo SetMetadataParseResponse(Azure::Core::Http::Response& http_response) + static BlobInfo SetMetadataParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); return response; } @@ -3119,14 +3221,14 @@ namespace Azure { namespace Storage { namespace Blobs { SetMetadataOptions& options) { auto request = SetMetadataConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return SetMetadataParseResponse(*response); + return SetMetadataParseResponse(pipeline.Send(context, request)); } struct SetAccessTierOptions { + Azure::Core::Nullable Timeout; AccessTier Tier = AccessTier::Unknown; - Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown; + Azure::Core::Nullable RehydratePriority; }; // struct SetAccessTierOptions static Azure::Core::Http::Request SetAccessTierConstructRequest( @@ -3137,33 +3239,40 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "tier"); request.AddHeader("x-ms-version", "2019-07-07"); - request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier)); - auto options_rehydratepriority_str = RehydratePriorityToString(options.RehydratePriority); - if (!options_rehydratepriority_str.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("x-ms-rehydrate-priority", options_rehydratepriority_str); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } + request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier)); + if (options.RehydratePriority.HasValue()) + { + request.AddHeader( + "x-ms-rehydrate-priority", + RehydratePriorityToString(options.RehydratePriority.GetValue())); } return request; } - static BasicResponse SetAccessTierParseResponse(Azure::Core::Http::Response& http_response) + static BasicResponse SetAccessTierParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BasicResponse response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200 || http_status_code == 202)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -3175,26 +3284,26 @@ namespace Azure { namespace Storage { namespace Blobs { SetAccessTierOptions& options) { auto request = SetAccessTierConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return SetAccessTierParseResponse(*response); + return SetAccessTierParseResponse(pipeline.Send(context, request)); } struct StartCopyFromUriOptions { + Azure::Core::Nullable Timeout; std::map Metadata; std::string SourceUri; - std::string LeaseId; - std::string SourceLeaseId; - AccessTier Tier = AccessTier::Unknown; - Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; - std::string SourceIfModifiedSince; - std::string SourceIfUnmodifiedSince; - std::string SourceIfMatch; - std::string SourceIfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable SourceLeaseId; + Azure::Core::Nullable Tier; + Azure::Core::Nullable RehydratePriority; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfMatch; + Azure::Core::Nullable SourceIfNoneMatch; }; // struct StartCopyFromUriOptions static Azure::Core::Http::Request StartCopyFromUriConstructRequest( @@ -3204,6 +3313,10 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } std::set metadataKeys; for (const auto& pair : options.Metadata) { @@ -3219,83 +3332,87 @@ namespace Azure { namespace Storage { namespace Blobs { } metadataKeys.clear(); request.AddHeader("x-ms-copy-source", options.SourceUri); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.SourceLeaseId.empty()) + if (options.SourceLeaseId.HasValue()) { - request.AddHeader("x-ms-source-lease-id", options.SourceLeaseId); + request.AddHeader("x-ms-source-lease-id", options.SourceLeaseId.GetValue()); } - auto options_tier_str = AccessTierToString(options.Tier); - if (!options_tier_str.empty()) + if (options.Tier.HasValue()) { - request.AddHeader("x-ms-access-tier", options_tier_str); + request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier.GetValue())); } - auto options_rehydratepriority_str = RehydratePriorityToString(options.RehydratePriority); - if (!options_rehydratepriority_str.empty()) + if (options.RehydratePriority.HasValue()) { - request.AddHeader("x-ms-rehydrate-priority", options_rehydratepriority_str); + request.AddHeader( + "x-ms-rehydrate-priority", + RehydratePriorityToString(options.RehydratePriority.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } - if (!options.SourceIfModifiedSince.empty()) + if (options.SourceIfModifiedSince.HasValue()) { - request.AddHeader("x-ms-source-if-modified-since", options.SourceIfModifiedSince); + request.AddHeader( + "x-ms-source-if-modified-since", options.SourceIfModifiedSince.GetValue()); } - if (!options.SourceIfUnmodifiedSince.empty()) + if (options.SourceIfUnmodifiedSince.HasValue()) { - request.AddHeader("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince); + request.AddHeader( + "x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.GetValue()); } - if (!options.SourceIfMatch.empty()) + if (options.SourceIfMatch.HasValue()) { - request.AddHeader("x-ms-source-if-match", options.SourceIfMatch); + request.AddHeader("x-ms-source-if-match", options.SourceIfMatch.GetValue()); } - if (!options.SourceIfNoneMatch.empty()) + if (options.SourceIfNoneMatch.HasValue()) { - request.AddHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch); + request.AddHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch.GetValue()); } return request; } - static BlobCopyInfo StartCopyFromUriParseResponse(Azure::Core::Http::Response& http_response) + static BlobCopyInfo StartCopyFromUriParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobCopyInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 202)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - response.CopyId = http_response.GetHeaders().at("x-ms-copy-id"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.CopyId = httpResponse.GetHeaders().at("x-ms-copy-id"); response.CopyStatus - = CopyStatusFromString(http_response.GetHeaders().at("x-ms-copy-status")); + = CopyStatusFromString(httpResponse.GetHeaders().at("x-ms-copy-status")); return response; } @@ -3306,14 +3423,14 @@ namespace Azure { namespace Storage { namespace Blobs { StartCopyFromUriOptions& options) { auto request = StartCopyFromUriConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return StartCopyFromUriParseResponse(*response); + return StartCopyFromUriParseResponse(pipeline.Send(context, request)); } struct AbortCopyFromUriOptions { + Azure::Core::Nullable Timeout; std::string CopyId; - std::string LeaseId; + Azure::Core::Nullable LeaseId; }; // struct AbortCopyFromUriOptions static Azure::Core::Http::Request AbortCopyFromUriConstructRequest( @@ -3323,34 +3440,40 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddQueryParameter("comp", "copy"); request.AddQueryParameter("copyid", options.CopyId); request.AddHeader("x-ms-copy-action", "abort"); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } return request; } - static BasicResponse AbortCopyFromUriParseResponse(Azure::Core::Http::Response& http_response) + static BasicResponse AbortCopyFromUriParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BasicResponse response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 204)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } return response; } @@ -3362,21 +3485,21 @@ namespace Azure { namespace Storage { namespace Blobs { AbortCopyFromUriOptions& options) { auto request = AbortCopyFromUriConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return AbortCopyFromUriParseResponse(*response); + return AbortCopyFromUriParseResponse(pipeline.Send(context, request)); } struct CreateSnapshotOptions { + Azure::Core::Nullable Timeout; std::map Metadata; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct CreateSnapshotOptions static Azure::Core::Http::Request CreateSnapshotConstructRequest( @@ -3387,17 +3510,21 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "snapshot"); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.EncryptionKey.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); + } + if (options.EncryptionAlgorithm.HasValue()) + { + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } std::set metadataKeys; for (const auto& pair : options.Metadata) @@ -3413,64 +3540,65 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } static BlobSnapshotInfo CreateSnapshotParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobSnapshotInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } - response.Snapshot = http_response.GetHeaders().at("x-ms-snapshot"); + response.Snapshot = httpResponse.GetHeaders().at("x-ms-snapshot"); return response; } @@ -3481,8 +3609,7 @@ namespace Azure { namespace Storage { namespace Blobs { CreateSnapshotOptions& options) { auto request = CreateSnapshotConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CreateSnapshotParseResponse(*response); + return CreateSnapshotParseResponse(pipeline.Send(context, request)); } private: @@ -3492,50 +3619,55 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct UploadOptions { + Azure::Core::Nullable Timeout; std::unique_ptr BodyStream; - std::string ContentMD5; - std::string ContentCRC64; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; BlobHttpHeaders Properties; std::map Metadata; - std::string LeaseId; - AccessTier Tier = AccessTier::Unknown; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable Tier; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct UploadOptions static Azure::Core::Http::Request UploadConstructRequest( const std::string& url, UploadOptions& options) { - uint64_t body_stream_length = options.BodyStream->Length(); + auto body_stream_length = options.BodyStream->Length(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Put, url, std::move(options.BodyStream)); request.AddHeader("Content-Length", std::to_string(body_stream_length)); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.EncryptionKey.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.ContentMD5.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("Content-MD5", options.ContentMD5); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.ContentCRC64.empty()) + if (options.ContentMD5.HasValue()) { - request.AddHeader("x-ms-content-crc64", options.ContentCRC64); + request.AddHeader("Content-MD5", options.ContentMD5.GetValue()); + } + if (options.ContentCRC64.HasValue()) + { + request.AddHeader("x-ms-content-crc64", options.ContentCRC64.GetValue()); } if (!options.Properties.ContentType.empty()) { @@ -3575,77 +3707,78 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } request.AddHeader("x-ms-blob-type", "BlockBlob"); - auto options_tier_str = AccessTierToString(options.Tier); - if (!options_tier_str.empty()) + if (options.Tier.HasValue()) { - request.AddHeader("x-ms-access-tier", options_tier_str); + request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobContentInfo UploadParseResponse(Azure::Core::Http::Response& http_response) + static BlobContentInfo UploadParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContentInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -3657,100 +3790,106 @@ namespace Azure { namespace Storage { namespace Blobs { UploadOptions& options) { auto request = UploadConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return UploadParseResponse(*response); + return UploadParseResponse(pipeline.Send(context, request)); } struct StageBlockOptions { + Azure::Core::Nullable Timeout; std::unique_ptr BodyStream; std::string BlockId; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; }; // struct StageBlockOptions static Azure::Core::Http::Request StageBlockConstructRequest( const std::string& url, StageBlockOptions& options) { - uint64_t body_stream_length = options.BodyStream->Length(); + auto body_stream_length = options.BodyStream->Length(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Put, url, std::move(options.BodyStream)); request.AddHeader("Content-Length", std::to_string(body_stream_length)); request.AddQueryParameter("comp", "block"); request.AddQueryParameter("blockid", options.BlockId); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.ContentMD5.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("Content-MD5", options.ContentMD5); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.ContentCRC64.empty()) + if (options.ContentMD5.HasValue()) { - request.AddHeader("x-ms-content-crc64", options.ContentCRC64); + request.AddHeader("Content-MD5", options.ContentMD5.GetValue()); } - if (!options.LeaseId.empty()) + if (options.ContentCRC64.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-content-crc64", options.ContentCRC64.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); + } + if (options.EncryptionAlgorithm.HasValue()) + { + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } return request; } - static BlockInfo StageBlockParseResponse(Azure::Core::Http::Response& http_response) + static BlockInfo StageBlockParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlockInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -3762,25 +3901,25 @@ namespace Azure { namespace Storage { namespace Blobs { StageBlockOptions& options) { auto request = StageBlockConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return StageBlockParseResponse(*response); + return StageBlockParseResponse(pipeline.Send(context, request)); } struct StageBlockFromUriOptions { + Azure::Core::Nullable Timeout; std::string BlockId; std::string SourceUri; - std::pair SourceRange; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string SourceIfModifiedSince; - std::string SourceIfUnmodifiedSince; - std::string SourceIfMatch; - std::string SourceIfNoneMatch; + Azure::Core::Nullable> SourceRange; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfMatch; + Azure::Core::Nullable SourceIfNoneMatch; }; // struct StageBlockFromUriOptions static Azure::Core::Http::Request StageBlockFromUriConstructRequest( @@ -3792,109 +3931,113 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddQueryParameter("comp", "block"); request.AddQueryParameter("blockid", options.BlockId); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddHeader("x-ms-copy-source", options.SourceUri); - if (options.SourceRange.first - == std::numeric_limits::max()) + if (options.SourceRange.HasValue()) { - // do nothing + auto startOffset = options.SourceRange.GetValue().first; + auto endOffset = options.SourceRange.GetValue().second; + if (endOffset != std::numeric_limits::max()) + { + request.AddHeader( + "x-ms-source_range", + "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); + } + else + { + request.AddHeader("x-ms-source_range", "bytes=" + std::to_string(startOffset) + "-"); + } } - else if ( - options.SourceRange.second - == std::numeric_limits::max()) + if (options.ContentMD5.HasValue()) + { + request.AddHeader("x-ms-source-content-md5", options.ContentMD5.GetValue()); + } + if (options.ContentCRC64.HasValue()) + { + request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64.GetValue()); + } + if (options.LeaseId.HasValue()) + { + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); + } + if (options.EncryptionKey.HasValue()) + { + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); + } + if (options.EncryptionKeySHA256.HasValue()) + { + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); + } + if (options.EncryptionAlgorithm.HasValue()) + { + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); + } + if (options.SourceIfModifiedSince.HasValue()) { request.AddHeader( - "x-ms-source_range", "bytes=" + std::to_string(options.SourceRange.first) + "-"); + "x-ms-source-if-modified-since", options.SourceIfModifiedSince.GetValue()); } - else + if (options.SourceIfUnmodifiedSince.HasValue()) { request.AddHeader( - "x-ms-source_range", - "bytes=" + std::to_string(options.SourceRange.first) + "-" - + std::to_string(options.SourceRange.second)); + "x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.GetValue()); } - if (!options.ContentMD5.empty()) + if (options.SourceIfMatch.HasValue()) { - request.AddHeader("x-ms-source-content-md5", options.ContentMD5); + request.AddHeader("x-ms-source-if-match", options.SourceIfMatch.GetValue()); } - if (!options.ContentCRC64.empty()) + if (options.SourceIfNoneMatch.HasValue()) { - request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64); - } - if (!options.LeaseId.empty()) - { - request.AddHeader("x-ms-lease-id", options.LeaseId); - } - if (!options.EncryptionKey.empty()) - { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); - } - if (!options.EncryptionKeySHA256.empty()) - { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); - } - if (!options.EncryptionAlgorithm.empty()) - { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); - } - if (!options.SourceIfModifiedSince.empty()) - { - request.AddHeader("x-ms-source-if-modified-since", options.SourceIfModifiedSince); - } - if (!options.SourceIfUnmodifiedSince.empty()) - { - request.AddHeader("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince); - } - if (!options.SourceIfMatch.empty()) - { - request.AddHeader("x-ms-source-if-match", options.SourceIfMatch); - } - if (!options.SourceIfNoneMatch.empty()) - { - request.AddHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch); + request.AddHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch.GetValue()); } return request; } - static BlockInfo StageBlockFromUriParseResponse(Azure::Core::Http::Response& http_response) + static BlockInfo StageBlockFromUriParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlockInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -3906,24 +4049,24 @@ namespace Azure { namespace Storage { namespace Blobs { StageBlockFromUriOptions& options) { auto request = StageBlockFromUriConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return StageBlockFromUriParseResponse(*response); + return StageBlockFromUriParseResponse(pipeline.Send(context, request)); } struct CommitBlockListOptions { + Azure::Core::Nullable Timeout; std::vector> BlockList; BlobHttpHeaders Properties; std::map Metadata; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; - AccessTier Tier = AccessTier::Unknown; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable Tier; }; // struct CommitBlockListOptions static Azure::Core::Http::Request CommitBlockListConstructRequest( @@ -3934,7 +4077,7 @@ namespace Azure { namespace Storage { namespace Blobs { CommitBlockListOptionsToXml(writer, options); std::string xml_body = writer.GetDocument(); std::vector body_buffer(xml_body.begin(), xml_body.end()); - uint64_t body_buffer_length = body_buffer.size(); + auto body_buffer_length = body_buffer.size(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Put, url, @@ -3942,6 +4085,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", std::to_string(body_buffer_length)); request.AddQueryParameter("comp", "blocklist"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } if (!options.Properties.ContentType.empty()) { request.AddHeader("x-ms-blob-content-type", options.Properties.ContentType); @@ -3980,79 +4127,79 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - auto options_tier_str = AccessTierToString(options.Tier); - if (!options_tier_str.empty()) + if (options.Tier.HasValue()) { - request.AddHeader("x-ms-access-tier", options_tier_str); + request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } static BlobContentInfo CommitBlockListParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContentInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -4064,17 +4211,17 @@ namespace Azure { namespace Storage { namespace Blobs { CommitBlockListOptions& options) { auto request = CommitBlockListConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CommitBlockListParseResponse(*response); + return CommitBlockListParseResponse(pipeline.Send(context, request)); } struct GetBlockListOptions { - BlockListTypeOption ListType = BlockListTypeOption::All; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable ListType; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct GetBlockListOptions static Azure::Core::Http::Request GetBlockListConstructRequest( @@ -4084,60 +4231,67 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "blocklist"); - std::string block_list_type_option = BlockListTypeOptionToString(options.ListType); - if (!block_list_type_option.empty()) + if (options.ListType.HasValue()) { + std::string block_list_type_option + = BlockListTypeOptionToString(options.ListType.GetValue()); request.AddQueryParameter("blocklisttype", block_list_type_option); } request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.IfModifiedSince.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobBlockListInfo GetBlockListParseResponse(Azure::Core::Http::Response& http_response) + static BlobBlockListInfo GetBlockListParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobBlockListInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - auto bodyStream = http_response.GetBodyStream(); + auto bodyStream = httpResponse.GetBodyStream(); std::vector bodyContent(static_cast(bodyStream->Length())); bodyStream->Read(&bodyContent[0], bodyContent.size()); XmlReader reader(reinterpret_cast(bodyContent.data()), bodyContent.size()); response = BlobBlockListInfoFromXml(reader); - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - response.ContentType = http_response.GetHeaders().at("Content-Type"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.ContentType = httpResponse.GetHeaders().at("Content-Type"); response.ContentLength - = std::stoull(http_response.GetHeaders().at("x-ms-blob-content-length")); + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); return response; } @@ -4148,8 +4302,7 @@ namespace Azure { namespace Storage { namespace Blobs { GetBlockListOptions& options) { auto request = GetBlockListConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return GetBlockListParseResponse(*response); + return GetBlockListParseResponse(pipeline.Send(context, request)); } private: @@ -4277,7 +4430,7 @@ namespace Azure { namespace Storage { namespace Blobs { } else if (path.size() == 1 && path[0] == XmlTagName::k_Size) { - ret.Size = std::stoull(node.Value); + ret.Size = std::stoll(node.Value); } } } @@ -4304,19 +4457,20 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct CreateOptions { - uint64_t BlobContentLength; - uint64_t SequenceNumber = 0; + Azure::Core::Nullable Timeout; + int64_t BlobContentLength; + Azure::Core::Nullable SequenceNumber; BlobHttpHeaders Properties; std::map Metadata; - std::string LeaseId; - AccessTier Tier = AccessTier::Unknown; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable Tier; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct CreateOptions static Azure::Core::Http::Request CreateConstructRequest( @@ -4326,6 +4480,10 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } if (!options.Properties.ContentType.empty()) { request.AddHeader("x-ms-blob-content-type", options.Properties.ContentType); @@ -4364,91 +4522,96 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } request.AddHeader("x-ms-blob-type", "PageBlob"); request.AddHeader("x-ms-blob-content-length", std::to_string(options.BlobContentLength)); - request.AddHeader("x-ms-blob-sequence-number", std::to_string(options.SequenceNumber)); - auto options_tier_str = AccessTierToString(options.Tier); - if (!options_tier_str.empty()) + if (options.SequenceNumber.HasValue()) { - request.AddHeader("x-ms-access-tier", options_tier_str); + request.AddHeader( + "x-ms-blob-sequence-number", std::to_string(options.SequenceNumber.GetValue())); } - if (!options.EncryptionKey.empty()) + if (options.Tier.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobContentInfo CreateParseResponse(Azure::Core::Http::Response& http_response) + static BlobContentInfo CreateParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContentInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -4460,143 +4623,155 @@ namespace Azure { namespace Storage { namespace Blobs { CreateOptions& options) { auto request = CreateConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CreateParseResponse(*response); + return CreateParseResponse(pipeline.Send(context, request)); } struct UploadPagesOptions { + Azure::Core::Nullable Timeout; std::unique_ptr BodyStream; - std::pair Range; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + std::pair Range; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; + Azure::Core::Nullable IfSequenceNumberLessThan; + Azure::Core::Nullable IfSequenceNumberEqualTo; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct UploadPagesOptions static Azure::Core::Http::Request UploadPagesConstructRequest( const std::string& url, UploadPagesOptions& options) { - uint64_t body_stream_length = options.BodyStream->Length(); + auto body_stream_length = options.BodyStream->Length(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Put, url, std::move(options.BodyStream)); request.AddHeader("Content-Length", std::to_string(body_stream_length)); request.AddQueryParameter("comp", "page"); request.AddHeader("x-ms-version", "2019-07-07"); - if (options.Range.first == std::numeric_limits::max()) + if (options.Timeout.HasValue()) { - // do nothing + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - else if (options.Range.second == std::numeric_limits::max()) + request.AddHeader( + "x-ms-range", + "bytes=" + std::to_string(options.Range.first) + "-" + + std::to_string(options.Range.second)); + if (options.ContentMD5.HasValue()) { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-"); + request.AddHeader("Content-MD5", options.ContentMD5.GetValue()); } - else + if (options.ContentCRC64.HasValue()) { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); - } - if (!options.ContentMD5.empty()) - { - request.AddHeader("Content-MD5", options.ContentMD5); - } - if (!options.ContentCRC64.empty()) - { - request.AddHeader("x-ms-content-crc64", options.ContentCRC64); + request.AddHeader("x-ms-content-crc64", options.ContentCRC64.GetValue()); } request.AddHeader("x-ms-page-write", "update"); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader( + "x-ms-if-sequence-number-le", + std::to_string(options.IfSequenceNumberLessThanOrEqualTo.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.IfSequenceNumberLessThan.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader( + "x-ms-if-sequence-number-lt", + std::to_string(options.IfSequenceNumberLessThan.GetValue())); } - if (!options.EncryptionAlgorithm.empty()) + if (options.IfSequenceNumberEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader( + "x-ms-if-sequence-number-eq", + std::to_string(options.IfSequenceNumberEqualTo.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfMatch.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + } + if (options.IfUnmodifiedSince.HasValue()) + { + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + } + if (options.IfMatch.HasValue()) + { + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static PageInfo UploadPagesParseResponse(Azure::Core::Http::Response& http_response) + static PageInfo UploadPagesParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; PageInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + response.SequenceNumber + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; - } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) - { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -4608,25 +4783,28 @@ namespace Azure { namespace Storage { namespace Blobs { UploadPagesOptions& options) { auto request = UploadPagesConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return UploadPagesParseResponse(*response); + return UploadPagesParseResponse(pipeline.Send(context, request)); } struct UploadPagesFromUriOptions { + Azure::Core::Nullable Timeout; std::string SourceUri; - std::pair SourceRange; - std::pair Range; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + std::pair SourceRange; + std::pair Range; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; + Azure::Core::Nullable IfSequenceNumberLessThan; + Azure::Core::Nullable IfSequenceNumberEqualTo; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct UploadPagesFromUriOptions static Azure::Core::Http::Request UploadPagesFromUriConstructRequest( @@ -4637,133 +4815,127 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "page"); request.AddHeader("x-ms-version", "2019-07-07"); - if (options.Range.first == std::numeric_limits::max()) + if (options.Timeout.HasValue()) { - // do nothing - } - else if (options.Range.second == std::numeric_limits::max()) - { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-"); - } - else - { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } + request.AddHeader( + "x-ms-range", + "bytes=" + std::to_string(options.Range.first) + "-" + + std::to_string(options.Range.second)); request.AddHeader("x-ms-copy-source", options.SourceUri); - if (options.SourceRange.first - == std::numeric_limits::max()) + request.AddHeader( + "x-ms-source-range", + "bytes=" + std::to_string(options.SourceRange.first) + "-" + + std::to_string(options.SourceRange.second)); + if (options.ContentMD5.HasValue()) { - // do nothing + request.AddHeader("x-ms-source-content-md5", options.ContentMD5.GetValue()); } - else if ( - options.SourceRange.second - == std::numeric_limits::max()) + if (options.ContentCRC64.HasValue()) { - request.AddHeader( - "x-ms-source-range", "bytes=" + std::to_string(options.SourceRange.first) + "-"); - } - else - { - request.AddHeader( - "x-ms-source-range", - "bytes=" + std::to_string(options.SourceRange.first) + "-" - + std::to_string(options.SourceRange.second)); - } - if (!options.ContentMD5.empty()) - { - request.AddHeader("x-ms-source-content-md5", options.ContentMD5); - } - if (!options.ContentCRC64.empty()) - { - request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64); + request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64.GetValue()); } request.AddHeader("x-ms-page-write", "update"); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader( + "x-ms-if-sequence-number-le", + std::to_string(options.IfSequenceNumberLessThanOrEqualTo.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.IfSequenceNumberLessThan.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader( + "x-ms-if-sequence-number-lt", + std::to_string(options.IfSequenceNumberLessThan.GetValue())); } - if (!options.EncryptionAlgorithm.empty()) + if (options.IfSequenceNumberEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader( + "x-ms-if-sequence-number-eq", + std::to_string(options.IfSequenceNumberEqualTo.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfMatch.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + } + if (options.IfUnmodifiedSince.HasValue()) + { + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + } + if (options.IfMatch.HasValue()) + { + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static PageInfo UploadPagesFromUriParseResponse(Azure::Core::Http::Response& http_response) + static PageInfo UploadPagesFromUriParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; PageInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + response.SequenceNumber + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; - } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) - { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -4775,21 +4947,24 @@ namespace Azure { namespace Storage { namespace Blobs { UploadPagesFromUriOptions& options) { auto request = UploadPagesFromUriConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return UploadPagesFromUriParseResponse(*response); + return UploadPagesFromUriParseResponse(pipeline.Send(context, request)); } struct ClearPagesOptions { - std::pair Range; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + std::pair Range; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; + Azure::Core::Nullable IfSequenceNumberLessThan; + Azure::Core::Nullable IfSequenceNumberEqualTo; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct ClearPagesOptions static Azure::Core::Http::Request ClearPagesConstructRequest( @@ -4800,95 +4975,104 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "page"); request.AddHeader("x-ms-version", "2019-07-07"); - if (options.Range.first == std::numeric_limits::max()) + if (options.Timeout.HasValue()) { - // do nothing + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - else if (options.Range.second == std::numeric_limits::max()) + request.AddHeader( + "x-ms-range", + "bytes=" + std::to_string(options.Range.first) + "-" + + std::to_string(options.Range.second)); + request.AddHeader("x-ms-page-write", "clear"); + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-"); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - else + if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) { request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + "x-ms-if-sequence-number-le", + std::to_string(options.IfSequenceNumberLessThanOrEqualTo.GetValue())); } - request.AddHeader("x-ms-page-write", "clear"); - if (!options.LeaseId.empty()) + if (options.IfSequenceNumberLessThan.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader( + "x-ms-if-sequence-number-lt", + std::to_string(options.IfSequenceNumberLessThan.GetValue())); } - if (!options.EncryptionKey.empty()) + if (options.IfSequenceNumberEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader( + "x-ms-if-sequence-number-eq", + std::to_string(options.IfSequenceNumberEqualTo.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static PageInfo ClearPagesParseResponse(Azure::Core::Http::Response& http_response) + static PageInfo ClearPagesParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; PageInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.SequenceNumber + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; - } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) - { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -4900,20 +5084,24 @@ namespace Azure { namespace Storage { namespace Blobs { ClearPagesOptions& options) { auto request = ClearPagesConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return ClearPagesParseResponse(*response); + return ClearPagesParseResponse(pipeline.Send(context, request)); } struct ResizeOptions { - uint64_t BlobContentLength; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + int64_t BlobContentLength; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; + Azure::Core::Nullable IfSequenceNumberLessThan; + Azure::Core::Nullable IfSequenceNumberEqualTo; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct ResizeOptions static Azure::Core::Http::Request ResizeConstructRequest( @@ -4924,65 +5112,89 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddHeader("x-ms-blob-content-length", std::to_string(options.BlobContentLength)); - if (!options.EncryptionKey.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader( + "x-ms-if-sequence-number-le", + std::to_string(options.IfSequenceNumberLessThanOrEqualTo.GetValue())); } - if (!options.EncryptionAlgorithm.empty()) + if (options.IfSequenceNumberLessThan.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader( + "x-ms-if-sequence-number-lt", + std::to_string(options.IfSequenceNumberLessThan.GetValue())); } - if (!options.IfModifiedSince.empty()) + if (options.IfSequenceNumberEqualTo.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader( + "x-ms-if-sequence-number-eq", + std::to_string(options.IfSequenceNumberEqualTo.GetValue())); } - if (!options.IfUnmodifiedSince.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.IfMatch.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); + } + if (options.IfModifiedSince.HasValue()) + { + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + } + if (options.IfUnmodifiedSince.HasValue()) + { + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + } + if (options.IfMatch.HasValue()) + { + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static PageBlobInfo ResizeParseResponse(Azure::Core::Http::Response& http_response) + static PageBlobInfo ResizeParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; PageBlobInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; - } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_sequencenumber_iterator - = http_response.GetHeaders().find("x-ms-blob-sequence-number"); - if (response_sequencenumber_iterator != http_response.GetHeaders().end()) - { - response.SequenceNumber = std::stoull(response_sequencenumber_iterator->second); + response.ClientRequestId = response_client_request_id_iterator->second; } + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.SequenceNumber + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); return response; } @@ -4993,20 +5205,20 @@ namespace Azure { namespace Storage { namespace Blobs { ResizeOptions& options) { auto request = ResizeConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return ResizeParseResponse(*response); + return ResizeParseResponse(pipeline.Send(context, request)); } struct GetPageRangesOptions { - std::string PreviousSnapshot; - std::string PreviousSnapshotUrl; - std::pair Range; - std::string LeaseId; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable PreviousSnapshot; + Azure::Core::Nullable PreviousSnapshotUrl; + Azure::Core::Nullable> Range; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct GetPageRangesOptions static Azure::Core::Http::Request GetPageRangesConstructRequest( @@ -5016,82 +5228,87 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "pagelist"); - if (!options.PreviousSnapshot.empty()) + if (options.PreviousSnapshot.HasValue()) { - request.AddQueryParameter("prevsnapshot", options.PreviousSnapshot); + request.AddQueryParameter("prevsnapshot", options.PreviousSnapshot.GetValue()); } request.AddHeader("x-ms-version", "2019-07-07"); - if (options.Range.first == std::numeric_limits::max()) + if (options.Timeout.HasValue()) { - // do nothing + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - else if (options.Range.second == std::numeric_limits::max()) + if (options.Range.HasValue()) { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-"); + auto startOffset = options.Range.GetValue().first; + auto endOffset = options.Range.GetValue().second; + if (endOffset != std::numeric_limits::max()) + { + request.AddHeader( + "x-ms-range", + "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); + } + else + { + request.AddHeader("x-ms-range", "bytes=" + std::to_string(startOffset) + "-"); + } } - else + if (options.LeaseId.HasValue()) { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (!options.LeaseId.empty()) + if (options.PreviousSnapshotUrl.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-previous-snapshot-url", options.PreviousSnapshotUrl.GetValue()); } - if (!options.PreviousSnapshotUrl.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("x-ms-previous-snapshot-url", options.PreviousSnapshotUrl); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); - } - if (!options.IfNoneMatch.empty()) - { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } static PageRangesInfoInternal GetPageRangesParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; PageRangesInfoInternal response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 200)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - auto bodyStream = http_response.GetBodyStream(); + auto bodyStream = httpResponse.GetBodyStream(); std::vector bodyContent(static_cast(bodyStream->Length())); bodyStream->Read(&bodyContent[0], bodyContent.size()); XmlReader reader(reinterpret_cast(bodyContent.data()), bodyContent.size()); response = PageRangesInfoInternalFromXml(reader); - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); response.BlobContentLength - = std::stoull(http_response.GetHeaders().at("x-ms-blob-content-length")); + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); return response; } @@ -5102,17 +5319,17 @@ namespace Azure { namespace Storage { namespace Blobs { GetPageRangesOptions& options) { auto request = GetPageRangesConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return GetPageRangesParseResponse(*response); + return GetPageRangesParseResponse(pipeline.Send(context, request)); } struct CopyIncrementalOptions { + Azure::Core::Nullable Timeout; std::string CopySource; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct CopyIncrementalOptions static Azure::Core::Http::Request CopyIncrementalConstructRequest( @@ -5123,50 +5340,56 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "incrementalcopy"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddHeader("x-ms-copy-source", options.CopySource); - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobCopyInfo CopyIncrementalParseResponse(Azure::Core::Http::Response& http_response) + static BlobCopyInfo CopyIncrementalParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobCopyInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 202)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - response.CopyId = http_response.GetHeaders().at("x-ms-copy-id"); + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + response.CopyId = httpResponse.GetHeaders().at("x-ms-copy-id"); response.CopyStatus - = CopyStatusFromString(http_response.GetHeaders().at("x-ms-copy-status")); + = CopyStatusFromString(httpResponse.GetHeaders().at("x-ms-copy-status")); return response; } @@ -5177,8 +5400,7 @@ namespace Azure { namespace Storage { namespace Blobs { CopyIncrementalOptions& options) { auto request = CopyIncrementalConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CopyIncrementalParseResponse(*response); + return CopyIncrementalParseResponse(pipeline.Send(context, request)); } private: @@ -5250,13 +5472,13 @@ namespace Azure { namespace Storage { namespace Blobs { return ret; } - static std::pair ClearRangesFromXml(XmlReader& reader) + static std::pair ClearRangesFromXml(XmlReader& reader) { int depth = 0; bool is_start = false; bool is_end = false; - uint64_t start; - uint64_t end; + int64_t start; + int64_t end; while (true) { auto node = reader.Read(); @@ -5287,24 +5509,24 @@ namespace Azure { namespace Storage { namespace Blobs { { if (is_start) { - start = std::stoull(node.Value); + start = std::stoll(node.Value); } else if (is_end) { - end = std::stoull(node.Value); + end = std::stoll(node.Value); } } } return std::make_pair(start, end); } - static std::pair PageRangesFromXml(XmlReader& reader) + static std::pair PageRangesFromXml(XmlReader& reader) { int depth = 0; bool is_start = false; bool is_end = false; - uint64_t start; - uint64_t end; + int64_t start; + int64_t end; while (true) { auto node = reader.Read(); @@ -5335,11 +5557,11 @@ namespace Azure { namespace Storage { namespace Blobs { { if (is_start) { - start = std::stoull(node.Value); + start = std::stoll(node.Value); } else if (is_end) { - end = std::stoull(node.Value); + end = std::stoll(node.Value); } } } @@ -5352,16 +5574,17 @@ namespace Azure { namespace Storage { namespace Blobs { public: struct CreateOptions { + Azure::Core::Nullable Timeout; BlobHttpHeaders Properties; std::map Metadata; - std::string LeaseId; - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct CreateOptions static Azure::Core::Http::Request CreateConstructRequest( @@ -5371,6 +5594,10 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } if (!options.Properties.ContentType.empty()) { request.AddHeader("x-ms-blob-content-type", options.Properties.ContentType); @@ -5409,84 +5636,86 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-meta-" + pair.first, pair.second); } metadataKeys.clear(); - if (!options.LeaseId.empty()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } request.AddHeader("x-ms-blob-type", "AppendBlob"); - if (!options.EncryptionKey.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobContentInfo CreateParseResponse(Azure::Core::Http::Response& http_response) + static BlobContentInfo CreateParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobContentInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -5498,135 +5727,141 @@ namespace Azure { namespace Storage { namespace Blobs { CreateOptions& options) { auto request = CreateConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return CreateParseResponse(*response); + return CreateParseResponse(pipeline.Send(context, request)); } struct AppendBlockOptions { + Azure::Core::Nullable Timeout; std::unique_ptr BodyStream; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - uint64_t MaxSize = std::numeric_limits::max(); - uint64_t AppendPosition = std::numeric_limits::max(); - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable MaxSize; + Azure::Core::Nullable AppendPosition; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct AppendBlockOptions static Azure::Core::Http::Request AppendBlockConstructRequest( const std::string& url, AppendBlockOptions& options) { - uint64_t body_stream_length = options.BodyStream->Length(); + auto body_stream_length = options.BodyStream->Length(); auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Put, url, std::move(options.BodyStream)); request.AddHeader("Content-Length", std::to_string(body_stream_length)); request.AddQueryParameter("comp", "appendblock"); request.AddHeader("x-ms-version", "2019-07-07"); - if (!options.ContentMD5.empty()) + if (options.Timeout.HasValue()) { - request.AddHeader("Content-MD5", options.ContentMD5); + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); } - if (!options.ContentCRC64.empty()) + if (options.ContentMD5.HasValue()) { - request.AddHeader("x-ms-content-crc64", options.ContentCRC64); + request.AddHeader("Content-MD5", options.ContentMD5.GetValue()); } - if (!options.LeaseId.empty()) + if (options.ContentCRC64.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-content-crc64", options.ContentCRC64.GetValue()); } - if (options.MaxSize != std::numeric_limits::max()) + if (options.LeaseId.HasValue()) { - request.AddHeader("x-ms-blob-condition-maxsize", std::to_string(options.MaxSize)); + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); } - if (options.AppendPosition != std::numeric_limits::max()) + if (options.MaxSize.HasValue()) { request.AddHeader( - "x-ms-blob-condition-appendpos", std::to_string(options.AppendPosition)); + "x-ms-blob-condition-maxsize", std::to_string(options.MaxSize.GetValue())); } - if (!options.EncryptionKey.empty()) + if (options.AppendPosition.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader( + "x-ms-blob-condition-appendpos", std::to_string(options.AppendPosition.GetValue())); } - if (!options.EncryptionKeySHA256.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.EncryptionAlgorithm.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.IfModifiedSince.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (!options.IfUnmodifiedSince.empty()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (!options.IfMatch.empty()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Match", options.IfMatch); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.IfNoneMatch.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-Match", options.IfMatch.GetValue()); + } + if (options.IfNoneMatch.HasValue()) + { + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } - static BlobAppendInfo AppendBlockParseResponse(Azure::Core::Http::Response& http_response) + static BlobAppendInfo AppendBlockParseResponse( + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobAppendInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - response.AppendOffset - = std::stoull(http_response.GetHeaders().at("x-ms-blob-append-offset")); + response.AppendOffset = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-append-offset")); response.CommittedBlockCount - = std::stoull(http_response.GetHeaders().at("x-ms-blob-committed-block-count")); - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-committed-block-count")); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -5638,26 +5873,26 @@ namespace Azure { namespace Storage { namespace Blobs { AppendBlockOptions& options) { auto request = AppendBlockConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return AppendBlockParseResponse(*response); + return AppendBlockParseResponse(pipeline.Send(context, request)); } struct AppendBlockFromUriOptions { + Azure::Core::Nullable Timeout; std::string SourceUri; - std::pair SourceRange; - std::string ContentMD5; - std::string ContentCRC64; - std::string LeaseId; - uint64_t MaxSize = std::numeric_limits::max(); - uint64_t AppendPosition = std::numeric_limits::max(); - std::string EncryptionKey; - std::string EncryptionKeySHA256; - std::string EncryptionAlgorithm; - std::string IfModifiedSince; - std::string IfUnmodifiedSince; - std::string IfMatch; - std::string IfNoneMatch; + Azure::Core::Nullable> SourceRange; + Azure::Core::Nullable ContentMD5; + Azure::Core::Nullable ContentCRC64; + Azure::Core::Nullable LeaseId; + Azure::Core::Nullable MaxSize; + Azure::Core::Nullable AppendPosition; + Azure::Core::Nullable EncryptionKey; + Azure::Core::Nullable EncryptionKeySHA256; + Azure::Core::Nullable EncryptionAlgorithm; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; }; // struct AppendBlockFromUriOptions static Azure::Core::Http::Request AppendBlockFromUriConstructRequest( @@ -5668,125 +5903,126 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("Content-Length", "0"); request.AddQueryParameter("comp", "appendblock"); request.AddHeader("x-ms-version", "2019-07-07"); + if (options.Timeout.HasValue()) + { + request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue())); + } request.AddHeader("x-ms-copy-source", options.SourceUri); - if (options.SourceRange.first - == std::numeric_limits::max()) + if (options.SourceRange.HasValue()) { - // do nothing + auto startOffset = options.SourceRange.GetValue().first; + auto endOffset = options.SourceRange.GetValue().second; + if (endOffset != std::numeric_limits::max()) + { + request.AddHeader( + "x-ms-source-range", + "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); + } + else + { + request.AddHeader("x-ms-source-range", "bytes=" + std::to_string(startOffset) + "-"); + } } - else if ( - options.SourceRange.second - == std::numeric_limits::max()) + if (options.ContentMD5.HasValue()) + { + request.AddHeader("x-ms-source-content-md5", options.ContentMD5.GetValue()); + } + if (options.ContentCRC64.HasValue()) + { + request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64.GetValue()); + } + if (options.LeaseId.HasValue()) + { + request.AddHeader("x-ms-lease-id", options.LeaseId.GetValue()); + } + if (options.MaxSize.HasValue()) { request.AddHeader( - "x-ms-source-range", "bytes=" + std::to_string(options.SourceRange.first) + "-"); + "x-ms-blob-condition-maxsize", std::to_string(options.MaxSize.GetValue())); } - else + if (options.AppendPosition.HasValue()) { request.AddHeader( - "x-ms-source-range", - "bytes=" + std::to_string(options.SourceRange.first) + "-" - + std::to_string(options.SourceRange.second)); + "x-ms-blob-condition-appendpos", std::to_string(options.AppendPosition.GetValue())); } - if (!options.ContentMD5.empty()) + if (options.EncryptionKey.HasValue()) { - request.AddHeader("x-ms-source-content-md5", options.ContentMD5); + request.AddHeader("x-ms-encryption-key", options.EncryptionKey.GetValue()); } - if (!options.ContentCRC64.empty()) + if (options.EncryptionKeySHA256.HasValue()) { - request.AddHeader("x-ms-source-content-crc64", options.ContentCRC64); + request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256.GetValue()); } - if (!options.LeaseId.empty()) + if (options.EncryptionAlgorithm.HasValue()) { - request.AddHeader("x-ms-lease-id", options.LeaseId); + request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.GetValue()); } - if (options.MaxSize != std::numeric_limits::max()) + if (options.IfModifiedSince.HasValue()) { - request.AddHeader("x-ms-blob-condition-maxsize", std::to_string(options.MaxSize)); + request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); } - if (options.AppendPosition != std::numeric_limits::max()) + if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader( - "x-ms-blob-condition-appendpos", std::to_string(options.AppendPosition)); + request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); } - if (!options.EncryptionKey.empty()) + if (options.IfMatch.HasValue()) { - request.AddHeader("x-ms-encryption-key", options.EncryptionKey); + request.AddHeader("If-Match", options.IfMatch.GetValue()); } - if (!options.EncryptionKeySHA256.empty()) + if (options.IfNoneMatch.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySHA256); - } - if (!options.EncryptionAlgorithm.empty()) - { - request.AddHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm); - } - if (!options.IfModifiedSince.empty()) - { - request.AddHeader("If-Modified-Since", options.IfModifiedSince); - } - if (!options.IfUnmodifiedSince.empty()) - { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince); - } - if (!options.IfMatch.empty()) - { - request.AddHeader("If-Match", options.IfMatch); - } - if (!options.IfNoneMatch.empty()) - { - request.AddHeader("If-None-Match", options.IfNoneMatch); + request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue()); } return request; } static BlobAppendInfo AppendBlockFromUriParseResponse( - Azure::Core::Http::Response& http_response) + std::unique_ptr pHttpResponse) { + Azure::Core::Http::Response& httpResponse = *pHttpResponse; BlobAppendInfo response; auto http_status_code = static_cast::type>( - http_response.GetStatusCode()); + httpResponse.GetStatusCode()); if (!(http_status_code == 201)) { - throw std::runtime_error("HTTP status code " + std::to_string(http_status_code)); + throw StorageError::CreateFromResponse(std::move(pHttpResponse)); } - response.Version = http_response.GetHeaders().at("x-ms-version"); - response.Date = http_response.GetHeaders().at("Date"); - response.RequestId = http_response.GetHeaders().at("x-ms-request-id"); - auto response_clientrequestid_iterator - = http_response.GetHeaders().find("x-ms-client-request-id"); - if (response_clientrequestid_iterator != http_response.GetHeaders().end()) + response.Version = httpResponse.GetHeaders().at("x-ms-version"); + response.Date = httpResponse.GetHeaders().at("Date"); + response.RequestId = httpResponse.GetHeaders().at("x-ms-request-id"); + auto response_client_request_id_iterator + = httpResponse.GetHeaders().find("x-ms-client-request-id"); + if (response_client_request_id_iterator != httpResponse.GetHeaders().end()) { - response.ClientRequestId = response_clientrequestid_iterator->second; + response.ClientRequestId = response_client_request_id_iterator->second; } - response.ETag = http_response.GetHeaders().at("ETag"); - response.LastModified = http_response.GetHeaders().at("Last-Modified"); - auto response_contentmd5_iterator = http_response.GetHeaders().find("Content-MD5"); - if (response_contentmd5_iterator != http_response.GetHeaders().end()) + response.ETag = httpResponse.GetHeaders().at("ETag"); + response.LastModified = httpResponse.GetHeaders().at("Last-Modified"); + auto response_content_md5_iterator = httpResponse.GetHeaders().find("Content-MD5"); + if (response_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.ContentMD5 = response_contentmd5_iterator->second; + response.ContentMD5 = response_content_md5_iterator->second; } - auto response_contentcrc64_iterator = http_response.GetHeaders().find("x-ms-content-crc64"); - if (response_contentcrc64_iterator != http_response.GetHeaders().end()) + auto response_content_crc64_iterator = httpResponse.GetHeaders().find("x-ms-content-crc64"); + if (response_content_crc64_iterator != httpResponse.GetHeaders().end()) { - response.ContentCRC64 = response_contentcrc64_iterator->second; + response.ContentCRC64 = response_content_crc64_iterator->second; } - response.AppendOffset - = std::stoull(http_response.GetHeaders().at("x-ms-blob-append-offset")); + response.AppendOffset = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-append-offset")); response.CommittedBlockCount - = std::stoull(http_response.GetHeaders().at("x-ms-blob-committed-block-count")); - auto response_serverencrypted_iterator - = http_response.GetHeaders().find("x-ms-server-encrypted"); - if (response_serverencrypted_iterator != http_response.GetHeaders().end()) + = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-committed-block-count")); + auto response_server_encrypted_iterator + = httpResponse.GetHeaders().find("x-ms-server-encrypted"); + if (response_server_encrypted_iterator != httpResponse.GetHeaders().end()) { - response.ServerEncrypted = response_serverencrypted_iterator->second == "true"; + response.ServerEncrypted = response_server_encrypted_iterator->second == "true"; } - auto response_encryptionkeysha256_iterator - = http_response.GetHeaders().find("x-ms-encryption-key-sha256"); - if (response_encryptionkeysha256_iterator != http_response.GetHeaders().end()) + auto response_encryption_key_sha256_iterator + = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); + if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySHA256 = response_encryptionkeysha256_iterator->second; + response.EncryptionKeySHA256 = response_encryption_key_sha256_iterator->second; } return response; } @@ -5798,8 +6034,7 @@ namespace Azure { namespace Storage { namespace Blobs { AppendBlockFromUriOptions& options) { auto request = AppendBlockFromUriConstructRequest(url, options); - auto response = pipeline.Send(context, request); - return AppendBlockFromUriParseResponse(*response); + return AppendBlockFromUriParseResponse(pipeline.Send(context, request)); } private: diff --git a/sdk/storage/inc/blobs/page_blob_client.hpp b/sdk/storage/inc/blobs/page_blob_client.hpp index 96d153419..07a47221e 100644 --- a/sdk/storage/inc/blobs/page_blob_client.hpp +++ b/sdk/storage/inc/blobs/page_blob_client.hpp @@ -14,8 +14,8 @@ namespace Azure { namespace Storage { namespace Blobs { struct PageRange { - uint64_t Offset; - uint64_t Length; + int64_t Offset; + int64_t Length; }; struct PageRangesInfo @@ -23,69 +23,202 @@ namespace Azure { namespace Storage { namespace Blobs { std::string RequestId; std::string Date; std::string Version; - std::string ClientRequestId; + Azure::Core::Nullable ClientRequestId; std::string ETag; std::string LastModified; - uint64_t BlobContentLength = 0; + int64_t BlobContentLength = 0; std::vector PageRanges; std::vector ClearRanges; }; + /** + * The PageBlobClient allows you to manipulate Azure Storage page blobs. + * + * Page blobs are a collection of 512-byte pages optimized for random read and write operations. + * To create a page blob, you initialize the page blob and specify the maximum size the page blob + * will grow. To add or update the contents of a page blob, you write a page or pages by + * specifying an offset and a range that align to 512-byte page boundaries. Writes to page blobs + * happen in-place and are immediately committed to the blob. + */ class PageBlobClient : public BlobClient { public: - // connection string + /** + * @brief Initialize a new instance of PageBlobClient. + * + * @param connectionString A connection string includes the authentication information required + * for your application to access data in an Azure Storage account at runtime. + * @param containerName The name of the container containing this blob. + * @param blobName The name of this blob. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + * @return A new PageBlobClient instance. + */ static PageBlobClient CreateFromConnectionString( const std::string& connectionString, const std::string& containerName, const std::string& blobName, const PageBlobClientOptions& options = PageBlobClientOptions()); - // shared key auth + /** + * @brief Initialize a new instance of PageBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The shared key credential used to sign + * requests. + * @param options Optional client options that define the transport pipeline + * policies for authentication, retries, etc., that are applied to every request. + */ explicit PageBlobClient( const std::string& blobUri, std::shared_ptr credential, const PageBlobClientOptions& options = PageBlobClientOptions()); - // token auth + /** + * @brief Initialize a new instance of PageBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob. + * @param credential The token credential used to sign requests. + * @param options Optional client options that define the transport pipeline policies for + * authentication, retries, etc., that are applied to every request. + */ explicit PageBlobClient( const std::string& blobUri, std::shared_ptr credential, const PageBlobClientOptions& options = PageBlobClientOptions()); - // anonymous/SAS/customized pipeline auth + /** + * @brief Initialize a new instance of PageBlobClient. + * + * @param blobUri A uri + * referencing the blob that includes the name of the account, the name of the container, and + * the name of the blob, and possibly also a SAS token. + * @param options Optional client + * options that define the transport pipeline policies for authentication, retries, etc., that + * are applied to every request. + */ explicit PageBlobClient( const std::string& blobUri, const PageBlobClientOptions& options = PageBlobClientOptions()); + /** + * @brief Initializes a new instance of the PageBlobClient class with an identical uri + * source but the specified snapshot timestamp. + * + * @param snapshot The snapshot + * identifier. + * @return A new PageBlobClient instance. + * @remarks Pass empty string to remove the snapshot returning the base blob. + */ PageBlobClient WithSnapshot(const std::string& snapshot) const; + /** + * @brief Creates a new page blob of the specified size. The content of any existing + * blob is overwritten with the newly initialized page blob. + * + * @param + * blobContentLength Specifies the maximum size for the page blob. The size must be aligned to a + * 512-byte boundary. + * @param options Optional parameters to execute this function. + * @return A BlobContentInfo describing the newly created page blob. + */ BlobContentInfo Create( - uint64_t blobContentLength, + int64_t blobContentLength, const CreatePageBlobOptions& options = CreatePageBlobOptions()); + /** + * @brief Writes content to a range of pages in a page blob, starting at offset. + * + * @param content A BodyStream containing the content of the pages to upload. + * @param offset Specifies the starting offset for the content to be written as a page. Given + * that pages must be aligned with 512-byte boundaries, the start offset must be a modulus of + * 512. + * @param options Optional parameters to execute this function. + * @return A + * PageInfo describing the state of the updated pages. + */ PageInfo UploadPages( std::unique_ptr content, - uint64_t offset, + int64_t offset, const UploadPagesOptions& options = UploadPagesOptions()); + /** + * @brief Writes a range of pages to a page blob where the contents are read from a + * uri. + * + * @param sourceUri Specifies the uri of the source blob. The value may be a + * uri of up to 2 KB in length that specifies a blob. The source blob must either be public or + * must be authenticated via a shared access signature. If the source blob is public, no + * authentication is required to perform the operation. + * @param sourceOffset Only upload a + * part of the blob in the sourceUri from the specified offset. + * @param sourceLength Only + * upload specified length of the blob in the sourceUri. + * @param destinationOffset + * Specifies the starting offset for the content to be written. Given that pages must be aligned + * with 512-byte boundaries, the start offset must be a modulus of 512. + * @param options + * Optional parameters to execute this function. + * @return A PageInfo describing the state + * of the updated pages. + */ PageInfo UploadPagesFromUri( std::string sourceUri, - uint64_t sourceOffset, - uint64_t sourceLength, - uint64_t destinationoffset, + int64_t sourceOffset, + int64_t sourceLength, + int64_t destinationoffset, const UploadPagesFromUriOptions& options = UploadPagesFromUriOptions()); + /** + * @brief Clears one or more pages from the page blob, as specificed by offset and length. + * + * @param offset Specifies the starting offset for the content to be cleared. Given that pages + * must be aligned with 512-byte boundaries, the start offset must be a modulus of 512. + * @param length Specifies the length of the content to be cleared. + * @param options Optional parameters to execute this function. + * @return A PageInfo describing the state of the updated pages. + */ PageInfo ClearPages( - uint64_t offset, - uint64_t length, + int64_t offset, + int64_t length, const ClearPagesOptions& options = ClearPagesOptions()); + /** + * @brief Resizes the page blob to the specified size (which must be a multiple of 512). If the + * specified value is less than the current size of the blob, then all pages above the specified + * value are cleared. + * + * @param blobContentLength Specifies the maximum size for the page blob. The size must be + * aligned to a 512-byte boundary. + * @param options Optional parameters to execute this function. + * @return A PageBlobInfo describing the resized page blob. + */ PageBlobInfo Resize( - uint64_t blobContentLength, + int64_t blobContentLength, const ResizePageBlobOptions& options = ResizePageBlobOptions()); + /** + * @brief Returns the list of valid page ranges for a page blob or snapshot of a page blob. + * + * @param options Optional parameters to execute this function. + * @return A PageRangesInfo describing the valid page ranges for this blob. + */ PageRangesInfo GetPageRanges(const GetPageRangesOptions& options = GetPageRangesOptions()); + /** + * @brief Starts copying a snapshot of the sourceUri page blob to this page blob. The snapshot + * is copied such that only the differential changes between the previously copied snapshot + * are transferred to the destination. The copied snapshots are complete copies of the original + * snapshot and can be read or copied from as usual. + * + * @param sourceUri Specifies the to the source page blob as a uri up to 2 KB in length. The + * source blob must either be public or must be authenticated via a shared access signature. + * @param options Optional parameters to execute this function. + * @return A BlobCopyInfo describing the state of the copy operation. + */ BlobCopyInfo StartCopyIncremental( const std::string& sourceUri, const IncrementalCopyPageBlobOptions& options = IncrementalCopyPageBlobOptions()); diff --git a/sdk/storage/sample/blob_getting_started.cpp b/sdk/storage/sample/blob_getting_started.cpp index 54b2bff7d..d7acb6d1d 100644 --- a/sdk/storage/sample/blob_getting_started.cpp +++ b/sdk/storage/sample/blob_getting_started.cpp @@ -38,15 +38,17 @@ void BlobsGettingStarted() auto blobDownloadContent = blobClient.Download(); blobContent.resize(static_cast(blobDownloadContent.BodyStream->Length())); - // read body stream until it returns 0 (all content read) - auto readTotal = uint64_t(); - do + std::size_t offset = 0; + while (true) { - auto offset = uint64_t(); - readTotal = blobDownloadContent.BodyStream->Read( - reinterpret_cast(&blobContent[(size_t)offset]), blobContent.length()); - offset += readTotal; - } while (readTotal != 0); + auto bytesRead = blobDownloadContent.BodyStream->Read( + reinterpret_cast(&blobContent[offset]), blobContent.length() - offset); + offset += static_cast(bytesRead); + if (bytesRead == 0 || offset == blobContent.length()) + { + break; + } + } std::cout << blobContent << std::endl; diff --git a/sdk/storage/src/blobs/append_blob_client.cpp b/sdk/storage/src/blobs/append_blob_client.cpp index 1f9193906..34f119264 100644 --- a/sdk/storage/src/blobs/append_blob_client.cpp +++ b/sdk/storage/src/blobs/append_blob_client.cpp @@ -95,8 +95,19 @@ namespace Azure { namespace Storage { namespace Blobs { { BlobRestClient::AppendBlob::AppendBlockFromUriOptions protocolLayerOptions; protocolLayerOptions.SourceUri = sourceUri; - protocolLayerOptions.SourceRange - = std::make_pair(options.SourceOffset, options.SourceOffset + options.SourceLength - 1); + if (options.SourceOffset.HasValue() && options.SourceLength.HasValue()) + { + protocolLayerOptions.SourceRange = std::make_pair( + options.SourceOffset.GetValue(), + options.SourceOffset.GetValue() + options.SourceLength.GetValue() - 1); + } + else if (options.SourceOffset.HasValue()) + { + protocolLayerOptions.SourceRange = std::make_pair( + options.SourceOffset.GetValue(), + std::numeric_limits< + std::remove_reference_t>::max()); + } protocolLayerOptions.ContentMD5 = options.ContentMD5; protocolLayerOptions.ContentCRC64 = options.ContentCRC64; protocolLayerOptions.LeaseId = options.LeaseId; diff --git a/sdk/storage/src/blobs/blob_client.cpp b/sdk/storage/src/blobs/blob_client.cpp index ab72ba752..b5c717406 100644 --- a/sdk/storage/src/blobs/blob_client.cpp +++ b/sdk/storage/src/blobs/blob_client.cpp @@ -105,26 +105,19 @@ namespace Azure { namespace Storage { namespace Blobs { return newClient; } - FlattenedDownloadProperties BlobClient::Download(const DownloadBlobOptions& options) const + BlobDownloadInfo BlobClient::Download(const DownloadBlobOptions& options) const { BlobRestClient::Blob::DownloadOptions protocolLayerOptions; - if (options.Offset != std::numeric_limits::max()) + if (options.Offset.HasValue() && options.Length.HasValue()) { - if (options.Length == 0) - { - protocolLayerOptions.Range - = std::make_pair(options.Offset, std::numeric_limits::max()); - } - else - { - protocolLayerOptions.Range - = std::make_pair(options.Offset, options.Offset + options.Length - 1); - } + protocolLayerOptions.Range = std::make_pair( + options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); } - else + else if (options.Offset.HasValue()) { - protocolLayerOptions.Range - = std::make_pair(std::numeric_limits::max(), uint64_t(0)); + protocolLayerOptions.Range = std::make_pair( + options.Offset.GetValue(), + std::numeric_limits>::max()); } protocolLayerOptions.IfModifiedSince = options.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince; diff --git a/sdk/storage/src/blobs/blob_service_client.cpp b/sdk/storage/src/blobs/blob_service_client.cpp index 97743da06..254f64f8e 100644 --- a/sdk/storage/src/blobs/blob_service_client.cpp +++ b/sdk/storage/src/blobs/blob_service_client.cpp @@ -112,11 +112,12 @@ namespace Azure { namespace Storage { namespace Blobs { } UserDelegationKey BlobServiceClient::GetUserDelegationKey( + const std::string& startsOn, const std::string& expiresOn, const GetUserDelegationKeyOptions& options) const { BlobRestClient::Service::GetUserDelegationKeyOptions protocolLayerOptions; - protocolLayerOptions.StartsOn = options.StartsOn; + protocolLayerOptions.StartsOn = startsOn; protocolLayerOptions.ExpiresOn = expiresOn; return BlobRestClient::Service::GetUserDelegationKey( options.Context, *m_pipeline, m_serviceUrl.ToString(), protocolLayerOptions); diff --git a/sdk/storage/src/blobs/block_blob_client.cpp b/sdk/storage/src/blobs/block_blob_client.cpp index c5d150051..e6622b09c 100644 --- a/sdk/storage/src/blobs/block_blob_client.cpp +++ b/sdk/storage/src/blobs/block_blob_client.cpp @@ -98,23 +98,18 @@ namespace Azure { namespace Storage { namespace Blobs { BlobRestClient::BlockBlob::StageBlockFromUriOptions protocolLayerOptions; protocolLayerOptions.BlockId = blockId; protocolLayerOptions.SourceUri = sourceUri; - if (options.SourceOffset != std::numeric_limits::max()) + if (options.SourceOffset.HasValue() && options.SourceLength.HasValue()) { - if (options.SourceLength == 0) - { - protocolLayerOptions.SourceRange = std::make_pair( - options.SourceOffset, std::numeric_limits::max()); - } - else - { - protocolLayerOptions.SourceRange - = std::make_pair(options.SourceOffset, options.SourceOffset + options.SourceLength - 1); - } + protocolLayerOptions.SourceRange = std::make_pair( + options.SourceOffset.GetValue(), + options.SourceOffset.GetValue() + options.SourceLength.GetValue() - 1); } - else + else if (options.SourceOffset.HasValue()) { - protocolLayerOptions.SourceRange - = std::make_pair(std::numeric_limits::max(), uint64_t(0)); + protocolLayerOptions.SourceRange = std::make_pair( + options.SourceOffset.GetValue(), + std::numeric_limits< + std::remove_reference_t>::max()); } protocolLayerOptions.ContentMD5 = options.ContentMD5; protocolLayerOptions.ContentCRC64 = options.ContentCRC64; diff --git a/sdk/storage/src/blobs/page_blob_client.cpp b/sdk/storage/src/blobs/page_blob_client.cpp index fa005dd78..b7afcbab5 100644 --- a/sdk/storage/src/blobs/page_blob_client.cpp +++ b/sdk/storage/src/blobs/page_blob_client.cpp @@ -56,7 +56,7 @@ namespace Azure { namespace Storage { namespace Blobs { } BlobContentInfo PageBlobClient::Create( - uint64_t blobContentLength, + int64_t blobContentLength, const CreatePageBlobOptions& options) { BlobRestClient::PageBlob::CreateOptions protocolLayerOptions; @@ -75,7 +75,7 @@ namespace Azure { namespace Storage { namespace Blobs { PageInfo PageBlobClient::UploadPages( std::unique_ptr content, - uint64_t offset, + int64_t offset, const UploadPagesOptions& options) { BlobRestClient::PageBlob::UploadPagesOptions protocolLayerOptions; @@ -95,9 +95,9 @@ namespace Azure { namespace Storage { namespace Blobs { PageInfo PageBlobClient::UploadPagesFromUri( std::string sourceUri, - uint64_t sourceOffset, - uint64_t sourceLength, - uint64_t destinationoffset, + int64_t sourceOffset, + int64_t sourceLength, + int64_t destinationoffset, const UploadPagesFromUriOptions& options) { BlobRestClient::PageBlob::UploadPagesFromUriOptions protocolLayerOptions; @@ -118,8 +118,8 @@ namespace Azure { namespace Storage { namespace Blobs { } PageInfo PageBlobClient::ClearPages( - uint64_t offset, - uint64_t length, + int64_t offset, + int64_t length, const ClearPagesOptions& options) { BlobRestClient::PageBlob::ClearPagesOptions protocolLayerOptions; @@ -134,7 +134,7 @@ namespace Azure { namespace Storage { namespace Blobs { } PageBlobInfo PageBlobClient::Resize( - uint64_t blobContentLength, + int64_t blobContentLength, const ResizePageBlobOptions& options) { BlobRestClient::PageBlob::ResizeOptions protocolLayerOptions; @@ -152,8 +152,11 @@ namespace Azure { namespace Storage { namespace Blobs { BlobRestClient::PageBlob::GetPageRangesOptions protocolLayerOptions; protocolLayerOptions.PreviousSnapshot = options.PreviousSnapshot; protocolLayerOptions.PreviousSnapshotUrl = options.PreviousSnapshotUrl; - protocolLayerOptions.Range - = std::make_pair(options.Offset, options.Offset + options.Length - 1); + if (options.Offset.HasValue() && options.Length.HasValue()) + { + protocolLayerOptions.Range = std::make_pair( + options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); + } protocolLayerOptions.IfModifiedSince = options.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince; protocolLayerOptions.IfMatch = options.IfMatch; diff --git a/sdk/storage/src/common/storage_error.cpp b/sdk/storage/src/common/storage_error.cpp index c3e24b874..bb4d40e4b 100644 --- a/sdk/storage/src/common/storage_error.cpp +++ b/sdk/storage/src/common/storage_error.cpp @@ -9,7 +9,7 @@ namespace Azure { namespace Storage { StorageError StorageError::CreateFromResponse( - /* const */ std::unique_ptr response) + std::unique_ptr response) { auto bodyStream = response->GetBodyStream(); auto bodyBuffer = std::make_unique>(); diff --git a/sdk/storage/test/CMakeLists.txt b/sdk/storage/test/CMakeLists.txt index 07a1df13b..62c66452a 100644 --- a/sdk/storage/test/CMakeLists.txt +++ b/sdk/storage/test/CMakeLists.txt @@ -16,7 +16,7 @@ add_executable ( append_blob_client_test.cpp page_blob_client_test.hpp page_blob_client_test.cpp - main.cpp + main.cpp ) target_link_libraries(azure-storage-test PRIVATE azure-storage) diff --git a/sdk/storage/test/append_blob_client_test.cpp b/sdk/storage/test/append_blob_client_test.cpp index 48c6e6826..8621ad3df 100644 --- a/sdk/storage/test/append_blob_client_test.cpp +++ b/sdk/storage/test/append_blob_client_test.cpp @@ -43,14 +43,15 @@ namespace Azure { namespace Storage { namespace Test { appendBlobClient.Create(m_blobUploadOptions); auto properties = appendBlobClient.GetProperties(); - EXPECT_EQ(properties.CommittedBlockCount, 0); + EXPECT_TRUE(properties.CommittedBlockCount.HasValue()); + EXPECT_EQ(properties.CommittedBlockCount.GetValue(), 0); EXPECT_EQ(properties.ContentLength, 0); appendBlobClient.AppendBlock( Azure::Storage::CreateMemoryStream(m_blobContent.data(), m_blobContent.size())); properties = appendBlobClient.GetProperties(); - EXPECT_EQ(properties.CommittedBlockCount, 1); - EXPECT_EQ(properties.ContentLength, m_blobContent.size()); + EXPECT_EQ(properties.CommittedBlockCount.GetValue(), 1); + EXPECT_EQ(properties.ContentLength, static_cast(m_blobContent.size())); Azure::Storage::Blobs::AppendBlockOptions options; options.AppendPosition = 1_MB; diff --git a/sdk/storage/test/blob_container_client_test.cpp b/sdk/storage/test/blob_container_client_test.cpp index f7e06a92b..81a98c948 100644 --- a/sdk/storage/test/blob_container_client_test.cpp +++ b/sdk/storage/test/blob_container_client_test.cpp @@ -109,7 +109,7 @@ namespace Azure { namespace Storage { namespace Test { ; EXPECT_FALSE(res.Version.empty()); EXPECT_FALSE(res.ServiceEndpoint.empty()); - EXPECT_EQ(res.MaxResults, options.MaxResults); + EXPECT_EQ(res.MaxResults.GetValue(), options.MaxResults.GetValue()); EXPECT_EQ(res.Container, m_containerName); options.Marker = res.NextMarker; @@ -123,7 +123,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_NE(blob.Tier, Azure::Storage::Blobs::AccessTier::Unknown); listBlobs.insert(blob.Name); } - } while (!options.Marker.empty()); + } while (!options.Marker.GetValue().empty()); EXPECT_TRUE( std::includes(listBlobs.begin(), listBlobs.end(), p1p2Blobs.begin(), p1p2Blobs.end())); @@ -137,7 +137,7 @@ namespace Azure { namespace Storage { namespace Test { { listBlobs.insert(blob.Name); } - } while (!options.Marker.empty()); + } while (!options.Marker.GetValue().empty()); EXPECT_TRUE(std::includes(listBlobs.begin(), listBlobs.end(), p1Blobs.begin(), p1Blobs.end())); } @@ -162,8 +162,8 @@ namespace Azure { namespace Storage { namespace Test { while (true) { auto res = m_blobContainerClient->ListBlobs(options); - EXPECT_EQ(res.Delimiter, options.Delimiter); - EXPECT_EQ(res.Prefix, options.Prefix); + EXPECT_EQ(res.Delimiter, options.Delimiter.GetValue()); + EXPECT_EQ(res.Prefix, options.Prefix.GetValue()); for (const auto& blob : res.BlobItems) { listBlobs.insert(blob.Name); @@ -175,7 +175,10 @@ namespace Azure { namespace Storage { namespace Test { else if (!res.BlobItems.empty()) { options.Prefix = res.BlobItems[0].Name + delimiter; - options.Marker.clear(); + if (options.Marker.HasValue()) + { + options.Marker.Reset(); + } } else { diff --git a/sdk/storage/test/blob_service_client_test.cpp b/sdk/storage/test/blob_service_client_test.cpp index 40548a323..defd8a2c4 100644 --- a/sdk/storage/test/blob_service_client_test.cpp +++ b/sdk/storage/test/blob_service_client_test.cpp @@ -53,14 +53,14 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.Date.empty()); EXPECT_FALSE(res.Version.empty()); EXPECT_FALSE(res.ServiceEndpoint.empty()); - EXPECT_EQ(res.MaxResults, options.MaxResults); + EXPECT_EQ(res.MaxResults.GetValue(), options.MaxResults.GetValue()); options.Marker = res.NextMarker; for (const auto& container : res.BlobContainerItems) { listContainers.insert(container.Name); } - } while (!options.Marker.empty()); + } while (!options.Marker.GetValue().empty()); EXPECT_TRUE(std::includes( listContainers.begin(), listContainers.end(), @@ -76,7 +76,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.Date.empty()); EXPECT_FALSE(res.Version.empty()); EXPECT_FALSE(res.ServiceEndpoint.empty()); - EXPECT_EQ(res.MaxResults, options.MaxResults); + EXPECT_EQ(res.MaxResults.GetValue(), options.MaxResults.GetValue()); options.Marker = res.NextMarker; for (const auto& container : res.BlobContainerItems) @@ -86,7 +86,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(container.LastModified.empty()); listContainers.insert(container.Name); } - } while (!options.Marker.empty()); + } while (!options.Marker.GetValue().empty()); EXPECT_TRUE(std::includes( listContainers.begin(), listContainers.end(), p1Containers.begin(), p1Containers.end())); diff --git a/sdk/storage/test/block_blob_client_test.cpp b/sdk/storage/test/block_blob_client_test.cpp index 56e9c1d18..b3a572ccf 100644 --- a/sdk/storage/test/block_blob_client_test.cpp +++ b/sdk/storage/test/block_blob_client_test.cpp @@ -34,7 +34,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, m_blobName); m_blockBlobClient = std::make_shared(std::move(blockBlobClient)); - m_blobContent.resize((size_t)8_MB); + m_blobContent.resize(static_cast(8_MB)); RandomBuffer(reinterpret_cast(&m_blobContent[0]), m_blobContent.size()); m_blobUploadOptions.Metadata = {{"key1", "V1"}, {"KEY2", "Value2"}}; m_blobUploadOptions.Properties.ContentType = "application/x-binary"; @@ -62,6 +62,9 @@ namespace Azure { namespace Storage { namespace Test { blockBlobClient.Delete(); EXPECT_THROW(blockBlobClient.Delete(), std::runtime_error); + blockBlobClient.Undelete(); + blockBlobClient.Delete(); + EXPECT_THROW(blockBlobClient.Delete(), std::runtime_error); } TEST_F(BlockBlobClientTest, UploadDownload) @@ -83,16 +86,17 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ( ReadBodyStream(res.BodyStream), std::vector( - m_blobContent.begin() + (size_t)options.Offset, - m_blobContent.begin() + (size_t)(options.Offset + options.Length))); - EXPECT_FALSE(res.ContentRange.empty()); + m_blobContent.begin() + static_cast(options.Offset.GetValue()), + m_blobContent.begin() + + static_cast(options.Offset.GetValue() + options.Length.GetValue()))); + EXPECT_FALSE(res.ContentRange.GetValue().empty()); } TEST_F(BlockBlobClientTest, CopyFromUri) { auto blobClient = m_blobContainerClient->GetBlobClient(RandomString()); auto res = blobClient.StartCopyFromUri(m_blockBlobClient->GetUri()); - ; + EXPECT_FALSE(res.RequestId.empty()); EXPECT_FALSE(res.Date.empty()); EXPECT_FALSE(res.Version.empty()); @@ -102,6 +106,17 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE( res.CopyStatus == Azure::Storage::Blobs::CopyStatus::Pending || res.CopyStatus == Azure::Storage::Blobs::CopyStatus::Success); + auto properties = blobClient.GetProperties(); + EXPECT_EQ(properties.CopyId.GetValue(), res.CopyId); + EXPECT_FALSE(properties.CopySource.GetValue().empty()); + EXPECT_TRUE( + properties.CopyStatus.GetValue() == Azure::Storage::Blobs::CopyStatus::Pending + || properties.CopyStatus.GetValue() == Azure::Storage::Blobs::CopyStatus::Success); + EXPECT_FALSE(properties.CopyProgress.GetValue().empty()); + if (properties.CopyStatus.GetValue() == Azure::Storage::Blobs::CopyStatus::Success) + { + EXPECT_FALSE(properties.CopyCompletionTime.GetValue().empty()); + } } TEST_F(BlockBlobClientTest, SnapShot) @@ -156,15 +171,15 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.LastModified.empty()); EXPECT_FALSE(res.CreationTime.empty()); EXPECT_EQ(res.Metadata, m_blobUploadOptions.Metadata); - EXPECT_EQ(res.ContentLength, m_blobContent.size()); + EXPECT_EQ(res.ContentLength, static_cast(m_blobContent.size())); EXPECT_EQ(res.ContentType, options.ContentType); EXPECT_EQ(res.ContentEncoding, options.ContentEncoding); EXPECT_EQ(res.ContentLanguage, options.ContentLanguage); EXPECT_EQ(res.ContentMD5, options.ContentMD5); EXPECT_EQ(res.CacheControl, options.CacheControl); EXPECT_EQ(res.ContentDisposition, options.ContentDisposition); - EXPECT_EQ(res.Tier, Azure::Storage::Blobs::AccessTier::Cool); - EXPECT_FALSE(res.AccessTierChangeTime.empty()); + EXPECT_EQ(res.Tier.GetValue(), Azure::Storage::Blobs::AccessTier::Cool); + EXPECT_FALSE(res.AccessTierChangeTime.GetValue().empty()); } TEST_F(BlockBlobClientTest, StageBlock) @@ -189,10 +204,10 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.Version.empty()); EXPECT_FALSE(res.ETag.empty()); EXPECT_FALSE(res.LastModified.empty()); - EXPECT_EQ(res.ContentLength, block1Content.size()); + EXPECT_EQ(res.ContentLength, static_cast(block1Content.size())); ASSERT_FALSE(res.CommittedBlocks.empty()); EXPECT_EQ(res.CommittedBlocks[0].Name, blockId1); - EXPECT_EQ(res.CommittedBlocks[0].Size, block1Content.size()); + EXPECT_EQ(res.CommittedBlocks[0].Size, static_cast(block1Content.size())); EXPECT_TRUE(res.UncommittedBlocks.empty()); // TODO: StageBlockFromUri must be authorized with SAS, but we don't have SAS for now. diff --git a/sdk/storage/test/page_blob_client_test.cpp b/sdk/storage/test/page_blob_client_test.cpp index bd2ac45b1..3d5a4cdcc 100644 --- a/sdk/storage/test/page_blob_client_test.cpp +++ b/sdk/storage/test/page_blob_client_test.cpp @@ -19,7 +19,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, m_blobName); m_pageBlobClient = std::make_shared(std::move(pageBlobClient)); - m_blobContent.resize((size_t)1_KB); + m_blobContent.resize(static_cast(1_KB)); RandomBuffer(reinterpret_cast(&m_blobContent[0]), m_blobContent.size()); m_blobUploadOptions.Metadata = {{"key1", "V1"}, {"KEY2", "Value2"}}; m_blobUploadOptions.Properties.ContentType = "application/x-binary"; @@ -53,16 +53,16 @@ namespace Azure { namespace Storage { namespace Test { pageBlobClient.Create(0, m_blobUploadOptions); EXPECT_EQ(pageBlobClient.GetProperties().ContentLength, 0); - pageBlobClient.Resize((size_t)2_KB); - EXPECT_EQ(pageBlobClient.GetProperties().ContentLength, 2_KB); - pageBlobClient.Resize((size_t)1_KB); - EXPECT_EQ(pageBlobClient.GetProperties().ContentLength, 1_KB); + pageBlobClient.Resize(static_cast(2_KB)); + EXPECT_EQ(static_cast(pageBlobClient.GetProperties().ContentLength), 2_KB); + pageBlobClient.Resize(static_cast(1_KB)); + EXPECT_EQ(static_cast(pageBlobClient.GetProperties().ContentLength), 1_KB); } TEST_F(PageBlobClientTest, UploadClear) { std::vector blobContent; - blobContent.resize((size_t)4_KB); + blobContent.resize(static_cast(4_KB)); RandomBuffer(reinterpret_cast(&blobContent[0]), blobContent.size()); auto pageBlobClient = Azure::Storage::Blobs::PageBlobClient::CreateFromConnectionString( @@ -71,12 +71,14 @@ namespace Azure { namespace Storage { namespace Test { pageBlobClient.UploadPages( Azure::Storage::CreateMemoryStream(blobContent.data(), blobContent.size()), 2_KB); // |_|_|x|x| |x|x|_|_| - blobContent.insert(blobContent.begin(), (size_t)2_KB, '\x00'); - blobContent.resize((size_t)8_KB, '\x00'); + blobContent.insert(blobContent.begin(), static_cast(2_KB), '\x00'); + blobContent.resize(static_cast(8_KB), '\x00'); pageBlobClient.ClearPages(2_KB, 1_KB); // |_|_|_|x| |x|x|_|_| std::fill( - blobContent.begin() + (size_t)2_KB, blobContent.begin() + (size_t)(2_KB + 1_KB), '\x00'); + blobContent.begin() + static_cast(2_KB), + blobContent.begin() + static_cast(2_KB + 1_KB), + '\x00'); auto downloadContent = pageBlobClient.Download(); EXPECT_EQ(ReadBodyStream(downloadContent.BodyStream), blobContent); @@ -84,8 +86,8 @@ namespace Azure { namespace Storage { namespace Test { auto pageRanges = pageBlobClient.GetPageRanges(); EXPECT_TRUE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); - EXPECT_EQ(pageRanges.PageRanges[0].Offset, 3_KB); - EXPECT_EQ(pageRanges.PageRanges[0].Length, 3_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Offset), 3_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 3_KB); Azure::Storage::Blobs::GetPageRangesOptions options; options.Offset = 4_KB; @@ -93,12 +95,12 @@ namespace Azure { namespace Storage { namespace Test { pageRanges = pageBlobClient.GetPageRanges(options); EXPECT_TRUE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); - EXPECT_EQ(pageRanges.PageRanges[0].Offset, 4_KB); - EXPECT_EQ(pageRanges.PageRanges[0].Length, 1_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Offset), 4_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 1_KB); auto snapshot = pageBlobClient.CreateSnapshot().Snapshot; // |_|_|_|x| |x|x|_|_| This is what's in snapshot - blobContent.resize((size_t)1_KB); + blobContent.resize(static_cast(1_KB)); pageBlobClient.UploadPages( Azure::Storage::CreateMemoryStream(blobContent.data(), blobContent.size()), 0); pageBlobClient.ClearPages(3_KB, 1_KB); @@ -110,9 +112,9 @@ namespace Azure { namespace Storage { namespace Test { ASSERT_FALSE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); EXPECT_EQ(pageRanges.PageRanges[0].Offset, 0); - EXPECT_EQ(pageRanges.PageRanges[0].Length, 1_KB); - EXPECT_EQ(pageRanges.ClearRanges[0].Offset, 3_KB); - EXPECT_EQ(pageRanges.ClearRanges[0].Length, 1_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 1_KB); + EXPECT_EQ(static_cast(pageRanges.ClearRanges[0].Offset), 3_KB); + EXPECT_EQ(static_cast(pageRanges.ClearRanges[0].Length), 1_KB); } TEST_F(PageBlobClientTest, UploadFromUri) diff --git a/sdk/storage/test/test_base.cpp b/sdk/storage/test/test_base.cpp index 460edf12f..809e6b430 100644 --- a/sdk/storage/test/test_base.cpp +++ b/sdk/storage/test/test_base.cpp @@ -134,25 +134,39 @@ namespace Azure { namespace Storage { namespace Test { std::vector ReadBodyStream(std::unique_ptr& stream) { - auto s = stream->Length(); - std::vector body((size_t)s, '\x00'); - // Read 15k at at time. warning C6262: exceeds /analyze:stacksize '16384'. + std::vector body; + if (stream->Length() == static_castLength())>(-1)) { - constexpr uint64_t fixedSize = 1024 * 15; - uint8_t tempBuffer[fixedSize]; - auto readBytes = uint64_t(); - auto offset = uint64_t(); - do + std::size_t bufferSize = static_cast(16_KB); + auto readBuffer = std::make_unique(bufferSize); + while (true) { - readBytes = stream->Read(tempBuffer, fixedSize); - for (uint64_t index = 0; index != readBytes; index++) + auto bytesRead = stream->Read(readBuffer.get(), bufferSize); + if (bytesRead == 0) { - body[(size_t)(offset + index)] = tempBuffer[index]; + break; } - offset += readBytes; - } while (readBytes != 0); + body.insert(body.end(), readBuffer.get(), readBuffer.get() + bytesRead); + } + } + else + { + body.resize(static_cast(stream->Length())); + std::size_t offset = 0; + while (true) + { + auto bytesRead = stream->Read(&body[offset], body.size() - offset); + offset += static_cast(bytesRead); + if (bytesRead == 0 || offset == body.size()) + { + break; + } + } + if (offset != body.size()) + { + throw std::runtime_error("failed to read all content from body stream"); + } } - return body; }