From b8e5c95d219de3d5a4267ce80b9f2d30498b280f Mon Sep 17 00:00:00 2001 From: JinmingHu Date: Mon, 28 Dec 2020 16:00:18 +0800 Subject: [PATCH] Integrate Core::DateTime into storage (#1246) * blob package can build * test can build * changelog * datatime for datalake sas * fix test error * user delegation key doesn't support time fractional part * add comments * Added DateTime for DataLake and many other refinements. * Resolved review comments. * Added changelog Co-authored-by: Tank Tang --- sdk/storage/azure-storage-blobs/CHANGELOG.md | 1 + .../azure/storage/blobs/blob_responses.hpp | 4 +- .../azure/storage/blobs/blob_sas_builder.hpp | 9 +- .../storage/blobs/blob_service_client.hpp | 12 +- .../blobs/protocol/blob_rest_client.hpp | 818 +++++--- .../src/blob_sas_builder.cpp | 59 +- .../src/blob_service_client.cpp | 4 +- .../test/append_blob_client_test.cpp | 16 +- .../test/blob_batch_client_test.cpp | 6 +- .../test/blob_container_client_test.cpp | 50 +- .../test/blob_sas_test.cpp | 33 +- .../test/blob_service_client_test.cpp | 8 +- .../test/block_blob_client_test.cpp | 54 +- .../test/page_blob_client_test.cpp | 18 +- .../test/storage_retry_policy_test.cpp | 72 +- sdk/storage/azure-storage-common/CHANGELOG.md | 8 +- .../storage/common/access_conditions.hpp | 8 +- .../storage/common/account_sas_builder.hpp | 5 +- .../src/account_sas_builder.cpp | 17 +- .../azure-storage-common/test/test_base.cpp | 68 +- .../azure-storage-common/test/test_base.hpp | 10 +- .../azure-storage-files-datalake/CHANGELOG.md | 6 + .../files/datalake/datalake_responses.hpp | 32 +- .../files/datalake/datalake_sas_builder.hpp | 9 +- .../datalake/datalake_service_client.hpp | 12 +- .../protocol/datalake_rest_client.hpp | 1663 ++++++----------- .../src/datalake_file_client.cpp | 7 +- .../src/datalake_file_system_client.cpp | 1 + .../src/datalake_path_client.cpp | 10 +- .../src/datalake_sas_builder.cpp | 64 +- .../test/datalake_directory_client_test.cpp | 3 + .../test/datalake_file_client_test.cpp | 14 +- .../test/datalake_path_client_test.cpp | 20 +- .../test/datalake_sas_test.cpp | 23 +- .../test/datalake_service_client_test.cpp | 6 +- .../shares/protocol/share_rest_client.hpp | 50 +- .../files/shares/share_sas_builder.hpp | 9 +- .../src/share_sas_builder.cpp | 25 +- .../test/share_sas_test.cpp | 19 +- 39 files changed, 1492 insertions(+), 1761 deletions(-) diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index 8995a3984..407beb49c 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -58,6 +58,7 @@ - `ListBlobContainersSegment` is renamed to `ListBlobContainersSinglePage`. - `FindBlobsByTags` is renamed to `FindBlobsByTagsSinglePage`. - `MaxResults` in list APIs are renamed to `PageSizeHint`. +- All date time related strings are now changed to `Azure::Core::DateTime` type. ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp index 7c3e22351..4417c1086 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp @@ -16,7 +16,7 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Models { struct DownloadBlobToResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int64_t ContentLength = 0; BlobHttpHeaders HttpHeaders; Storage::Metadata Metadata; @@ -36,7 +36,7 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Models { struct GetPageBlobPageRangesResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int64_t BlobContentLength = 0; std::vector PageRanges; std::vector ClearRanges; diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_sas_builder.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_sas_builder.hpp index c30183586..2f9efa10a 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_sas_builder.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_sas_builder.hpp @@ -182,15 +182,16 @@ namespace Azure { namespace Storage { namespace Sas { /** * @brief Optionally specify the time at which the shared access signature becomes - * valid. + * valid. This timestamp will be truncated to second. */ - Azure::Core::Nullable StartsOn; + Azure::Core::Nullable StartsOn; /** * @brief The time at which the shared access signature becomes invalid. This field must - * be omitted if it has been specified in an associated stored access policy. + * be omitted if it has been specified in an associated stored access policy. This timestamp + * will be truncated to second. */ - std::string ExpiresOn; + Azure::Core::DateTime ExpiresOn; /** * @brief Specifies an IP address or a range of IP addresses from which to accept diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_service_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_service_client.hpp index 5470b29c1..d6e66870c 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_service_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_service_client.hpp @@ -104,16 +104,16 @@ namespace Azure { namespace Storage { namespace Blobs { * @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, in ISO date format. The time should be - * specified in UTC. - * @param expiresOn Expiration of the key's validity, in ISO date format. The time should be - * specified in UTC. + * @param startsOn Start time for the key's validity. The time should be specified in UTC, and + * will be truncated to second. + * @param expiresOn Expiration of the key's validity. The time should be specified in UTC, and + * will be truncated to second. * @param options Optional parameters to execute this function. * @return A deserialized GetUserDelegationKeyResult instance. */ Azure::Core::Response GetUserDelegationKey( - const std::string& startsOn, - const std::string& expiresOn, + const Azure::Core::DateTime& startsOn, + const Azure::Core::DateTime& expiresOn, const GetUserDelegationKeyOptions& options = GetUserDelegationKeyOptions()) const; /** diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp index d37817a00..294bc702f 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -70,14 +71,14 @@ namespace Azure { namespace Storage { namespace Blobs { struct AcquireBlobContainerLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct AcquireBlobContainerLeaseResult struct AcquireBlobLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct AcquireBlobLeaseResult @@ -140,8 +141,8 @@ namespace Azure { namespace Storage { namespace Blobs { struct BlobSignedIdentifier { std::string Id; - std::string StartsOn; - std::string ExpiresOn; + Azure::Core::DateTime StartsOn; + Azure::Core::DateTime ExpiresOn; std::string Permissions; }; // struct BlobSignedIdentifier @@ -178,35 +179,35 @@ namespace Azure { namespace Storage { namespace Blobs { struct BreakBlobContainerLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int32_t LeaseTime = 0; }; // struct BreakBlobContainerLeaseResult struct BreakBlobLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int32_t LeaseTime = 0; }; // struct BreakBlobLeaseResult struct ChangeBlobContainerLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct ChangeBlobContainerLeaseResult struct ChangeBlobLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct ChangeBlobLeaseResult struct ClearPageBlobPagesResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int64_t SequenceNumber = 0; }; // struct ClearPageBlobPagesResult @@ -220,7 +221,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct CreateAppendBlobResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable VersionId; bool IsServerEncrypted = false; Azure::Core::Nullable> EncryptionKeySha256; @@ -230,14 +231,14 @@ namespace Azure { namespace Storage { namespace Blobs { struct CreateBlobContainerResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; }; // struct CreateBlobContainerResult struct CreateBlobSnapshotResult { std::string Snapshot; std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable VersionId; bool IsServerEncrypted = false; Azure::Core::Nullable> EncryptionKeySha256; @@ -247,7 +248,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct CreatePageBlobResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable VersionId; bool IsServerEncrypted = false; Azure::Core::Nullable> EncryptionKeySha256; @@ -291,7 +292,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetPageBlobPageRangesResultInternal { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int64_t BlobContentLength = 0; std::vector> PageRanges; std::vector> ClearRanges; @@ -301,8 +302,8 @@ namespace Azure { namespace Storage { namespace Blobs { { std::string SignedObjectId; std::string SignedTenantId; - std::string SignedStartsOn; - std::string SignedExpiresOn; + Azure::Core::DateTime SignedStartsOn; + Azure::Core::DateTime SignedExpiresOn; std::string SignedService; std::string SignedVersion; std::string Value; @@ -408,34 +409,34 @@ namespace Azure { namespace Storage { namespace Blobs { struct ReleaseBlobContainerLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; }; // struct ReleaseBlobContainerLeaseResult struct ReleaseBlobLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable SequenceNumber; }; // struct ReleaseBlobLeaseResult struct RenewBlobContainerLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct RenewBlobContainerLeaseResult struct RenewBlobLeaseResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string LeaseId; }; // struct RenewBlobLeaseResult struct ResizePageBlobResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; int64_t SequenceNumber = 0; }; // struct ResizePageBlobResult @@ -451,7 +452,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct SealAppendBlobResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; bool IsSealed = true; }; // struct SealAppendBlobResult @@ -462,13 +463,13 @@ namespace Azure { namespace Storage { namespace Blobs { struct SetBlobContainerAccessPolicyResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; }; // struct SetBlobContainerAccessPolicyResult struct SetBlobContainerMetadataResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; }; // struct SetBlobContainerMetadataResult struct SetBlobExpiryResult @@ -478,14 +479,14 @@ namespace Azure { namespace Storage { namespace Blobs { struct SetBlobHttpHeadersResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable SequenceNumber; }; // struct SetBlobHttpHeadersResult struct SetBlobMetadataResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable SequenceNumber; }; // struct SetBlobMetadataResult @@ -536,7 +537,7 @@ namespace Azure { namespace Storage { namespace Blobs { { std::string Name; std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Storage::Metadata Metadata; PublicAccessType AccessType = PublicAccessType::Private; bool HasImmutabilityPolicy = false; @@ -548,14 +549,14 @@ namespace Azure { namespace Storage { namespace Blobs { bool PreventEncryptionScopeOverride = false; bool IsDeleted = false; Azure::Core::Nullable VersionId; - Azure::Core::Nullable DeletedTime; + Azure::Core::Nullable DeletedOn; Azure::Core::Nullable RemainingRetentionDays; }; // struct BlobContainerItem struct BlobGeoReplication { BlobGeoReplicationStatus Status = BlobGeoReplicationStatus::Unknown; - Azure::Core::Nullable LastSyncTime; + Azure::Core::Nullable LastSyncedOn; }; // struct BlobGeoReplication struct BlobMetrics @@ -585,14 +586,14 @@ namespace Azure { namespace Storage { namespace Blobs { { PublicAccessType AccessType = PublicAccessType::Private; std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::vector SignedIdentifiers; }; // struct GetBlobContainerAccessPolicyResult struct GetBlobContainerPropertiesResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Storage::Metadata Metadata; PublicAccessType AccessType = PublicAccessType::Private; bool HasImmutabilityPolicy = false; @@ -607,7 +608,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetBlockListResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string ContentType; int64_t ContentLength = 0; std::vector CommittedBlocks; @@ -623,7 +624,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct StartCopyBlobFromUriResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string CopyId; Models::CopyStatus CopyStatus = Models::CopyStatus::Unknown; Azure::Core::Nullable VersionId; @@ -632,7 +633,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct StartCopyPageBlobIncrementalResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; std::string CopyId; Models::CopyStatus CopyStatus = Models::CopyStatus::Unknown; Azure::Core::Nullable VersionId; @@ -641,7 +642,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct AppendBlockFromUriResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable TransactionalContentHash; int64_t AppendOffset = 0; int64_t CommittedBlockCount = 0; @@ -653,7 +654,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct AppendBlockResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable TransactionalContentHash; int64_t AppendOffset = 0; int64_t CommittedBlockCount = 0; @@ -686,7 +687,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct CommitBlockListResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable VersionId; bool IsServerEncrypted = false; Azure::Core::Nullable> EncryptionKeySha256; @@ -744,7 +745,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadBlockBlobResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable VersionId; bool IsServerEncrypted = false; Azure::Core::Nullable> EncryptionKeySha256; @@ -755,7 +756,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadPageBlobPagesFromUriResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable TransactionalContentHash; int64_t SequenceNumber = 0; bool IsServerEncrypted = false; @@ -766,7 +767,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadPageBlobPagesResult { std::string ETag; - std::string LastModified; + Azure::Core::DateTime LastModified; Azure::Core::Nullable TransactionalContentHash; int64_t SequenceNumber = 0; bool IsServerEncrypted = false; @@ -783,10 +784,10 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable IsCurrentVersion; BlobHttpHeaders HttpHeaders; Storage::Metadata Metadata; - std::string CreationTime; - Azure::Core::Nullable ExpiryTime; - Azure::Core::Nullable LastAccessTime; - std::string LastModified; + Azure::Core::DateTime CreatedOn; + Azure::Core::Nullable ExpiriesOn; + Azure::Core::Nullable LastAccessedOn; + Azure::Core::DateTime LastModified; std::string ETag; int64_t ContentLength = 0; Models::BlobType BlobType = Models::BlobType::Unknown; @@ -808,10 +809,10 @@ namespace Azure { namespace Storage { namespace Blobs { { std::unique_ptr BodyStream; std::string ETag; - std::string LastModified; - std::string CreationTime; - Azure::Core::Nullable ExpiryTime; - Azure::Core::Nullable LastAccessTime; + Azure::Core::DateTime LastModified; + Azure::Core::DateTime CreatedOn; + Azure::Core::Nullable ExpiriesOn; + Azure::Core::Nullable LastAccessedOn; Azure::Core::Nullable ContentRange; BlobHttpHeaders HttpHeaders; Storage::Metadata Metadata; @@ -836,10 +837,10 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetBlobPropertiesResult { std::string ETag; - std::string LastModified; - std::string CreationTime; - Azure::Core::Nullable ExpiryTime; - Azure::Core::Nullable LastAccessTime; + Azure::Core::DateTime LastModified; + Azure::Core::DateTime CreatedOn; + Azure::Core::Nullable ExpiriesOn; + Azure::Core::Nullable LastAccessedOn; Storage::Metadata Metadata; Models::BlobType BlobType = Models::BlobType::Unknown; Azure::Core::Nullable LeaseDuration; @@ -856,12 +857,12 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Tier; Azure::Core::Nullable IsAccessTierInferred; Azure::Core::Nullable ArchiveStatus; - Azure::Core::Nullable AccessTierChangeTime; + Azure::Core::Nullable AccessTierChangedOn; Azure::Core::Nullable CopyId; Azure::Core::Nullable CopySource; Azure::Core::Nullable CopyStatus; Azure::Core::Nullable CopyProgress; - Azure::Core::Nullable CopyCompletionTime; + Azure::Core::Nullable CopyCompletedOn; Azure::Core::Nullable ObjectReplicationDestinationPolicyId; // only valid for replication destination blob std::vector @@ -1763,8 +1764,8 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetUserDelegationKeyOptions { Azure::Core::Nullable Timeout; - std::string StartsOn; - std::string ExpiresOn; + Azure::Core::DateTime StartsOn; + Azure::Core::DateTime ExpiresOn; }; // struct GetUserDelegationKeyOptions static Azure::Core::Response GetUserDelegationKey( @@ -2411,13 +2412,15 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_UserDelegationKey && path[1] == XmlTagName::k_SignedStart) { - ret.SignedStartsOn = node.Value; + ret.SignedStartsOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc3339); } else if ( path.size() == 2 && path[0] == XmlTagName::k_UserDelegationKey && path[1] == XmlTagName::k_SignedExpiry) { - ret.SignedExpiresOn = node.Value; + ret.SignedExpiresOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc3339); } else if ( path.size() == 2 && path[0] == XmlTagName::k_UserDelegationKey @@ -2769,7 +2772,8 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_LastModified) { - ret.LastModified = node.Value; + ret.LastModified = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -2831,7 +2835,8 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_DeletedTime) { - ret.DeletedTime = node.Value; + ret.DeletedOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -2980,7 +2985,8 @@ namespace Azure { namespace Storage { namespace Blobs { } else if (path.size() == 1 && path[0] == XmlTagName::k_LastSyncTime) { - ret.LastSyncTime = node.Value; + ret.LastSyncedOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } } } @@ -3307,12 +3313,19 @@ namespace Azure { namespace Storage { namespace Blobs { Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "KeyInfo"}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Start"}); writer.Write(Storage::Details::XmlNode{ - Storage::Details::XmlNodeType::Text, nullptr, options.StartsOn.data()}); + Storage::Details::XmlNodeType::Text, + nullptr, + options.StartsOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + .data()}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag}); writer.Write( Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Expiry"}); writer.Write(Storage::Details::XmlNode{ - Storage::Details::XmlNodeType::Text, nullptr, options.ExpiresOn.data()}); + Storage::Details::XmlNodeType::Text, + nullptr, + options.ExpiresOn + .GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + .data()}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag}); } @@ -3585,7 +3598,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -3594,8 +3609,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct DeleteBlobContainerOptions static Azure::Core::Response Delete( @@ -3619,11 +3634,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -3715,7 +3736,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); for (auto i = httpResponse.GetHeaders().lower_bound("x-ms-meta-"); i != httpResponse.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; ++i) @@ -3755,7 +3778,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Storage::Metadata Metadata; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfModifiedSince; }; // struct SetBlobContainerMetadataOptions static Azure::Core::Response SetMetadata( @@ -3785,7 +3808,10 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -3798,7 +3824,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -3984,7 +4012,9 @@ namespace Azure { namespace Storage { namespace Blobs { response = GetBlobContainerAccessPolicyResultFromXml(reader); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.AccessType = PublicAccessTypeFromString(httpResponse.GetHeaders().at("x-ms-blob-public-access")); return Azure::Core::Response( @@ -3996,8 +4026,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Azure::Core::Nullable AccessType; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; std::vector SignedIdentifiers; }; // struct SetBlobContainerAccessPolicyOptions @@ -4039,11 +4069,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4056,7 +4092,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -4066,8 +4104,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; int32_t LeaseDuration = -1; Azure::Core::Nullable ProposedLeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct AcquireBlobContainerLeaseOptions static Azure::Core::Response AcquireLease( @@ -4095,11 +4133,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4112,7 +4156,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -4122,8 +4168,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct RenewBlobContainerLeaseOptions static Azure::Core::Response RenewLease( @@ -4147,11 +4193,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4164,7 +4216,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -4175,8 +4229,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; std::string LeaseId; std::string ProposedLeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct ChangeBlobContainerLeaseOptions static Azure::Core::Response ChangeLease( @@ -4201,11 +4255,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4218,7 +4278,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -4228,8 +4290,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct ReleaseBlobContainerLeaseOptions static Azure::Core::Response ReleaseLease( @@ -4253,11 +4315,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4270,7 +4338,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -4279,8 +4349,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; Azure::Core::Nullable BreakPeriod; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; // struct BreakBlobContainerLeaseOptions static Azure::Core::Response BreakLease( @@ -4308,11 +4378,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -4325,7 +4401,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseTime = std::stoi(httpResponse.GetHeaders().at("x-ms-lease-time")); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -4884,25 +4962,29 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_CreationTime) { - ret.CreationTime = node.Value; + ret.CreatedOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_ExpiryTime) { - ret.ExpiryTime = node.Value; + ret.ExpiriesOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_LastAccessTime) { - ret.LastAccessTime = node.Value; + ret.LastAccessedOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_LastModified) { - ret.LastModified = node.Value; + ret.LastModified = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc1123); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -5098,13 +5180,15 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_AccessPolicy && path[1] == XmlTagName::k_Start) { - ret.StartsOn = node.Value; + ret.StartsOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc3339); } else if ( path.size() == 2 && path[0] == XmlTagName::k_AccessPolicy && path[1] == XmlTagName::k_Expiry) { - ret.ExpiresOn = node.Value; + ret.ExpiresOn = Azure::Core::DateTime::Parse( + node.Value, Azure::Core::DateTime::DateFormat::Rfc3339); } else if ( path.size() == 2 && path[0] == XmlTagName::k_AccessPolicy @@ -5230,12 +5314,20 @@ namespace Azure { namespace Storage { namespace Blobs { Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "AccessPolicy"}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Start"}); writer.Write(Storage::Details::XmlNode{ - Storage::Details::XmlNodeType::Text, nullptr, options.StartsOn.data()}); + Storage::Details::XmlNodeType::Text, + nullptr, + options.StartsOn + .GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::AllDigits) + .data()}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag}); writer.Write( Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Expiry"}); writer.Write(Storage::Details::XmlNode{ - Storage::Details::XmlNodeType::Text, nullptr, options.ExpiresOn.data()}); + Storage::Details::XmlNodeType::Text, + nullptr, + options.ExpiresOn + .GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::AllDigits) + .data()}); writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag}); writer.Write( Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Permission"}); @@ -5258,8 +5350,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -5311,11 +5403,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -5345,7 +5443,9 @@ namespace Azure { namespace Storage { namespace Blobs { } response.BodyStream = httpResponse.GetBodyStream(); response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -5440,17 +5540,22 @@ namespace Azure { namespace Storage { namespace Blobs { { response.LeaseDuration = x_ms_lease_duration__iterator->second; } - response.CreationTime = httpResponse.GetHeaders().at("x-ms-creation-time"); + response.CreatedOn = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("x-ms-creation-time"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_expiry_time__iterator = httpResponse.GetHeaders().find("x-ms-expiry-time"); if (x_ms_expiry_time__iterator != httpResponse.GetHeaders().end()) { - response.ExpiryTime = x_ms_expiry_time__iterator->second; + response.ExpiriesOn = Azure::Core::DateTime::Parse( + x_ms_expiry_time__iterator->second, Azure::Core::DateTime::DateFormat::Rfc1123); } auto x_ms_last_access_time__iterator = httpResponse.GetHeaders().find("x-ms-last-access-time"); if (x_ms_last_access_time__iterator != httpResponse.GetHeaders().end()) { - response.LastAccessTime = x_ms_last_access_time__iterator->second; + response.LastAccessedOn = Azure::Core::DateTime::Parse( + x_ms_last_access_time__iterator->second, + Azure::Core::DateTime::DateFormat::Rfc1123); } auto content_range__iterator = httpResponse.GetHeaders().find("content-range"); if (content_range__iterator != httpResponse.GetHeaders().end()) @@ -5524,8 +5629,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Azure::Core::Nullable DeleteSnapshots; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -5555,11 +5660,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -5690,8 +5801,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -5732,11 +5843,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -5761,18 +5878,25 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); - response.CreationTime = httpResponse.GetHeaders().at("x-ms-creation-time"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); + response.CreatedOn = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("x-ms-creation-time"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_expiry_time__iterator = httpResponse.GetHeaders().find("x-ms-expiry-time"); if (x_ms_expiry_time__iterator != httpResponse.GetHeaders().end()) { - response.ExpiryTime = x_ms_expiry_time__iterator->second; + response.ExpiriesOn = Azure::Core::DateTime::Parse( + x_ms_expiry_time__iterator->second, Azure::Core::DateTime::DateFormat::Rfc1123); } auto x_ms_last_access_time__iterator = httpResponse.GetHeaders().find("x-ms-last-access-time"); if (x_ms_last_access_time__iterator != httpResponse.GetHeaders().end()) { - response.LastAccessTime = x_ms_last_access_time__iterator->second; + response.LastAccessedOn = Azure::Core::DateTime::Parse( + x_ms_last_access_time__iterator->second, + Azure::Core::DateTime::DateFormat::Rfc1123); } for (auto i = httpResponse.GetHeaders().lower_bound("x-ms-meta-"); i != httpResponse.GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-"; @@ -5891,7 +6015,9 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-access-tier-change-time"); if (x_ms_access_tier_change_time__iterator != httpResponse.GetHeaders().end()) { - response.AccessTierChangeTime = x_ms_access_tier_change_time__iterator->second; + response.AccessTierChangedOn = Azure::Core::DateTime::Parse( + x_ms_access_tier_change_time__iterator->second, + Azure::Core::DateTime::DateFormat::Rfc1123); } auto x_ms_copy_id__iterator = httpResponse.GetHeaders().find("x-ms-copy-id"); if (x_ms_copy_id__iterator != httpResponse.GetHeaders().end()) @@ -5917,7 +6043,9 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-copy-completion-time"); if (x_ms_copy_completion_time__iterator != httpResponse.GetHeaders().end()) { - response.CopyCompletionTime = x_ms_copy_completion_time__iterator->second; + response.CopyCompletedOn = Azure::Core::DateTime::Parse( + x_ms_copy_completion_time__iterator->second, + Azure::Core::DateTime::DateFormat::Rfc1123); } auto x_ms_or_policy_id__iterator = httpResponse.GetHeaders().find("x-ms-or-policy-id"); if (x_ms_or_policy_id__iterator != httpResponse.GetHeaders().end()) @@ -5967,8 +6095,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; BlobHttpHeaders HttpHeaders; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6022,11 +6150,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6051,7 +6185,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_blob_sequence_number__iterator = httpResponse.GetHeaders().find("x-ms-blob-sequence-number"); if (x_ms_blob_sequence_number__iterator != httpResponse.GetHeaders().end()) @@ -6071,8 +6207,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6123,11 +6259,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6152,7 +6294,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -6231,13 +6375,13 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable SourceLeaseId; Azure::Core::Nullable Tier; Azure::Core::Nullable RehydratePriority; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; - Azure::Core::Nullable SourceIfModifiedSince; - Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; Azure::Core::Nullable SourceIfMatch; Azure::Core::Nullable SourceIfNoneMatch; Azure::Core::Nullable SourceIfTags; @@ -6289,11 +6433,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6310,12 +6460,16 @@ namespace Azure { namespace Storage { namespace Blobs { if (options.SourceIfModifiedSince.HasValue()) { request.AddHeader( - "x-ms-source-if-modified-since", options.SourceIfModifiedSince.GetValue()); + "x-ms-source-if-modified-since", + options.SourceIfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.SourceIfUnmodifiedSince.HasValue()) { request.AddHeader( - "x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.GetValue()); + "x-ms-source-if-unmodified-since", + options.SourceIfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.SourceIfMatch.HasValue()) { @@ -6340,7 +6494,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.CopyId = httpResponse.GetHeaders().at("x-ms-copy-id"); response.CopyStatus = CopyStatusFromString(httpResponse.GetHeaders().at("x-ms-copy-status")); @@ -6406,8 +6562,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6458,11 +6614,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6487,7 +6649,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.IsServerEncrypted = httpResponse.GetHeaders().at("x-ms-request-server-encrypted") == "true"; auto x_ms_encryption_key_sha256__iterator @@ -6615,8 +6779,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; int32_t LeaseDuration = -1; Azure::Core::Nullable ProposedLeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6646,11 +6810,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6675,7 +6845,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -6685,8 +6857,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6712,11 +6884,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6741,7 +6919,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -6752,8 +6932,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; std::string LeaseId; std::string ProposedLeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6780,11 +6960,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6809,7 +6995,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id"); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -6819,8 +7007,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6846,11 +7034,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6875,7 +7069,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_blob_sequence_number__iterator = httpResponse.GetHeaders().find("x-ms-blob-sequence-number"); if (x_ms_blob_sequence_number__iterator != httpResponse.GetHeaders().end()) @@ -6890,8 +7086,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; Azure::Core::Nullable BreakPeriod; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -6921,11 +7117,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -6950,7 +7152,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.LeaseTime = std::stoi(httpResponse.GetHeaders().at("x-ms-lease-time")); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); @@ -7104,8 +7308,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -7202,11 +7406,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -7231,7 +7441,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -7404,8 +7616,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable SourceIfModifiedSince; - Azure::Core::Nullable SourceIfUnmodifiedSince; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; Azure::Core::Nullable SourceIfMatch; Azure::Core::Nullable SourceIfNoneMatch; }; // struct StageBlockFromUriOptions @@ -7485,12 +7697,16 @@ namespace Azure { namespace Storage { namespace Blobs { if (options.SourceIfModifiedSince.HasValue()) { request.AddHeader( - "x-ms-source-if-modified-since", options.SourceIfModifiedSince.GetValue()); + "x-ms-source-if-modified-since", + options.SourceIfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.SourceIfUnmodifiedSince.HasValue()) { request.AddHeader( - "x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.GetValue()); + "x-ms-source-if-unmodified-since", + options.SourceIfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.SourceIfMatch.HasValue()) { @@ -7559,8 +7775,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -7652,11 +7868,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -7681,7 +7903,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_version_id__iterator = httpResponse.GetHeaders().find("x-ms-version-id"); if (x_ms_version_id__iterator != httpResponse.GetHeaders().end()) { @@ -7761,7 +7985,9 @@ namespace Azure { namespace Storage { namespace Blobs { response = GetBlockListResultFromXml(reader); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.ContentType = httpResponse.GetHeaders().at("content-type"); response.ContentLength = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); @@ -7934,8 +8160,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8022,11 +8248,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8051,7 +8283,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_version_id__iterator = httpResponse.GetHeaders().find("x-ms-version-id"); if (x_ms_version_id__iterator != httpResponse.GetHeaders().end()) { @@ -8089,8 +8323,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8176,11 +8410,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8205,7 +8445,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -8261,8 +8503,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8352,11 +8594,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8381,7 +8629,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -8434,8 +8684,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8505,11 +8755,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8534,7 +8790,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.SequenceNumber = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); return Azure::Core::Response( @@ -8553,8 +8811,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8620,11 +8878,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8649,7 +8913,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.SequenceNumber = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); return Azure::Core::Response( @@ -8663,8 +8929,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable PreviousSnapshotUrl; Azure::Core::Nullable> Range; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8716,11 +8982,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8751,7 +9023,9 @@ namespace Azure { namespace Storage { namespace Blobs { response = GetPageBlobPageRangesResultInternalFromXml(reader); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.BlobContentLength = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); return Azure::Core::Response( @@ -8762,8 +9036,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string CopySource; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -8788,11 +9062,17 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-copy-source", options.CopySource); if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -8817,7 +9097,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); response.CopyId = httpResponse.GetHeaders().at("x-ms-copy-id"); response.CopyStatus = CopyStatusFromString(httpResponse.GetHeaders().at("x-ms-copy-status")); @@ -9018,8 +9300,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -9096,11 +9378,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -9125,7 +9413,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); auto x_ms_version_id__iterator = httpResponse.GetHeaders().find("x-ms-version-id"); if (x_ms_version_id__iterator != httpResponse.GetHeaders().end()) { @@ -9161,8 +9451,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -9235,11 +9525,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -9264,7 +9560,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -9320,8 +9618,8 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -9409,11 +9707,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -9438,7 +9742,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); { const auto& headers = httpResponse.GetHeaders(); auto content_md5_iterator = headers.find("Content-MD5"); @@ -9485,8 +9791,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; Azure::Core::Nullable LeaseId; - Azure::Core::Nullable IfModifiedSince; - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; Azure::Core::Nullable IfMatch; Azure::Core::Nullable IfNoneMatch; Azure::Core::Nullable IfTags; @@ -9515,11 +9821,17 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.IfModifiedSince.HasValue()) { - request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue()); + request.AddHeader( + "If-Modified-Since", + options.IfModifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfUnmodifiedSince.HasValue()) { - request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue()); + request.AddHeader( + "If-Unmodified-Since", + options.IfUnmodifiedSince.GetValue().GetString( + Azure::Core::DateTime::DateFormat::Rfc1123)); } if (options.IfMatch.HasValue()) { @@ -9549,7 +9861,9 @@ namespace Azure { namespace Storage { namespace Blobs { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } response.ETag = httpResponse.GetHeaders().at("etag"); - response.LastModified = httpResponse.GetHeaders().at("last-modified"); + response.LastModified = Azure::Core::DateTime::Parse( + httpResponse.GetHeaders().at("last-modified"), + Azure::Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } diff --git a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp index f12618ba9..7c4dcb0df 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp @@ -128,12 +128,18 @@ namespace Azure { namespace Storage { namespace Sas { snapshotVersion = BlobVersionId; } - std::string stringToSign = Permissions + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") - + "\n" + ExpiresOn + "\n" + canonicalName + "\n" + Identifier + "\n" - + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" - + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + snapshotVersion + "\n" - + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage - + "\n" + ContentType; + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr = Identifier.empty() + ? ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + + std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + canonicalName + "\n" + Identifier + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + + snapshotVersion + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + + "\n" + ContentLanguage + "\n" + ContentType; std::string signature = Base64Encode(Storage::Details::HmacSha256( std::vector(stringToSign.begin(), stringToSign.end()), @@ -143,14 +149,13 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sv", Storage::Details::UrlEncodeQueryParameter(Storage::Details::DefaultSasVersion)); builder.AppendQueryParameter("spr", Storage::Details::UrlEncodeQueryParameter(protocol)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", Storage::Details::UrlEncodeQueryParameter(startsOnStr)); } - if (!ExpiresOn.empty()) + if (!expiresOnStr.empty()) { - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(expiresOnStr)); } if (IPRange.HasValue()) { @@ -217,12 +222,21 @@ namespace Azure { namespace Storage { namespace Sas { snapshotVersion = BlobVersionId; } - std::string stringToSign = Permissions + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") - + "\n" + ExpiresOn + "\n" + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" - + userDelegationKey.SignedTenantId + "\n" + userDelegationKey.SignedStartsOn + "\n" - + userDelegationKey.SignedExpiresOn + "\n" + userDelegationKey.SignedService + "\n" - + userDelegationKey.SignedVersion + "\n\n\n\n" - + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr + = ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate); + std::string signedStartsOnStr = userDelegationKey.SignedStartsOn.GetRfc3339String( + Azure::Core::DateTime::TimeFractionFormat::Truncate); + std::string signedExpiresOnStr = userDelegationKey.SignedExpiresOn.GetRfc3339String( + Azure::Core::DateTime::TimeFractionFormat::Truncate); + + std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" + + userDelegationKey.SignedTenantId + "\n" + signedStartsOnStr + "\n" + signedExpiresOnStr + + "\n" + userDelegationKey.SignedService + "\n" + userDelegationKey.SignedVersion + + "\n\n\n\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + snapshotVersion + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; @@ -235,12 +249,11 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sv", Storage::Details::UrlEncodeQueryParameter(Storage::Details::DefaultSasVersion)); builder.AppendQueryParameter("sr", Storage::Details::UrlEncodeQueryParameter(resource)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", Storage::Details::UrlEncodeQueryParameter(startsOnStr)); } - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(expiresOnStr)); builder.AppendQueryParameter("sp", Storage::Details::UrlEncodeQueryParameter(Permissions)); if (IPRange.HasValue()) { @@ -253,9 +266,9 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sktid", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedTenantId)); builder.AppendQueryParameter( - "skt", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedStartsOn)); + "skt", Storage::Details::UrlEncodeQueryParameter(signedStartsOnStr)); builder.AppendQueryParameter( - "ske", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedExpiresOn)); + "ske", Storage::Details::UrlEncodeQueryParameter(signedExpiresOnStr)); builder.AppendQueryParameter( "sks", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedService)); builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-blobs/src/blob_service_client.cpp b/sdk/storage/azure-storage-blobs/src/blob_service_client.cpp index ea29a343b..8d187043a 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_service_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_service_client.cpp @@ -134,8 +134,8 @@ namespace Azure { namespace Storage { namespace Blobs { } Azure::Core::Response BlobServiceClient::GetUserDelegationKey( - const std::string& startsOn, - const std::string& expiresOn, + const Azure::Core::DateTime& startsOn, + const Azure::Core::DateTime& expiresOn, const GetUserDelegationKeyOptions& options) const { Details::BlobRestClient::Service::GetUserDelegationKeyOptions protocolLayerOptions; diff --git a/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp index c35bb48b3..937475a76 100644 --- a/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp @@ -44,7 +44,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, RandomString()); auto blobContentInfo = appendBlobClient.Create(m_blobUploadOptions); EXPECT_FALSE(blobContentInfo->ETag.empty()); - EXPECT_FALSE(blobContentInfo->LastModified.empty()); + EXPECT_TRUE(IsValidTime(blobContentInfo->LastModified)); EXPECT_TRUE(blobContentInfo->VersionId.HasValue()); EXPECT_FALSE(blobContentInfo->VersionId.GetValue().empty()); EXPECT_FALSE(blobContentInfo->EncryptionScope.HasValue()); @@ -111,9 +111,9 @@ namespace Azure { namespace Storage { namespace Test { UnmodifiedSince, }; - auto lastModifiedTime = FromRfc1123(appendBlobClient.GetProperties()->LastModified); - auto timeBeforeStr = ToRfc1123(lastModifiedTime - std::chrono::seconds(1)); - auto timeAfterStr = ToRfc1123(lastModifiedTime + std::chrono::seconds(1)); + auto lastModifiedTime = appendBlobClient.GetProperties()->LastModified; + auto timeBeforeStr = lastModifiedTime - std::chrono::seconds(1); + auto timeAfterStr = lastModifiedTime + std::chrono::seconds(1); for (auto condition : {Condition::ModifiedSince, Condition::UnmodifiedSince}) { for (auto sinceTime : {TimePoint::TimeBefore, TimePoint::TimeAfter}) @@ -204,9 +204,9 @@ namespace Azure { namespace Storage { namespace Test { = sourceBlobClient.AcquireLease(CreateUniqueLeaseId(), InfiniteLeaseDuration); std::string leaseId = leaseResponse->LeaseId; std::string eTag = leaseResponse->ETag; - auto lastModifiedTime = FromRfc1123(leaseResponse->LastModified); - auto timeBeforeStr = ToRfc1123(lastModifiedTime - std::chrono::seconds(1)); - auto timeAfterStr = ToRfc1123(lastModifiedTime + std::chrono::seconds(1)); + auto lastModifiedTime = leaseResponse->LastModified; + auto timeBeforeStr = lastModifiedTime - std::chrono::seconds(1); + auto timeAfterStr = lastModifiedTime + std::chrono::seconds(1); auto destBlobClient = Azure::Storage::Blobs::AppendBlobClient::CreateFromConnectionString( StandardStorageConnectionString(), m_containerName, RandomString()); @@ -285,7 +285,7 @@ namespace Azure { namespace Storage { namespace Test { sealOptions.AccessConditions.IfAppendPositionEqual = m_blobContent.size(); auto sealResult = blobClient.Seal(sealOptions); EXPECT_FALSE(sealResult->ETag.empty()); - EXPECT_FALSE(sealResult->LastModified.empty()); + EXPECT_TRUE(IsValidTime(sealResult->LastModified)); EXPECT_TRUE(sealResult->IsSealed); downloadResult = blobClient.Download(); diff --git a/sdk/storage/azure-storage-blobs/test/blob_batch_client_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_batch_client_test.cpp index c7759f1db..47687fe5f 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_batch_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_batch_client_test.cpp @@ -25,10 +25,8 @@ namespace Azure { namespace Storage { namespace Test { { Sas::AccountSasBuilder accountSasBuilder; accountSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - accountSasBuilder.StartsOn - = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - accountSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + accountSasBuilder.StartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(5); + accountSasBuilder.ExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(60); accountSasBuilder.Services = Sas::AccountSasServices::Blobs; accountSasBuilder.ResourceTypes = Sas::AccountSasResource::Object | Sas::AccountSasResource::BlobContainer; diff --git a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp index 96ec09ffa..5c1e71791 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp @@ -42,7 +42,7 @@ namespace Azure { namespace Storage { namespace Test { { Sas::BlobSasBuilder sasBuilder; sasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - sasBuilder.ExpiresOn = ToIso8601(std::chrono::system_clock::now() + std::chrono::hours(72)); + sasBuilder.ExpiresOn = Azure::Core::DateTime::Now() + std::chrono::hours(72); sasBuilder.BlobContainerName = m_containerName; sasBuilder.Resource = Sas::BlobSasResource::BlobContainer; sasBuilder.SetPermissions(Sas::BlobContainerSasPermissions::All); @@ -64,7 +64,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_THROW(container_client.Create(), StorageException); auto res2 = container_client.Delete(); @@ -105,7 +105,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); auto res2 = m_blobContainerClient->GetProperties(); EXPECT_FALSE(res2.GetRawResponse().GetHeaders().at(Details::HttpHeaderRequestId).empty()); @@ -113,7 +113,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res2.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); auto properties = *res2; EXPECT_FALSE(properties.ETag.empty()); - EXPECT_FALSE(properties.LastModified.empty()); + EXPECT_TRUE(IsValidTime(properties.LastModified)); EXPECT_EQ(properties.Metadata, metadata); metadata.clear(); @@ -174,8 +174,8 @@ namespace Azure { namespace Storage { namespace Test { for (const auto& blob : res->Items) { EXPECT_FALSE(blob.Name.empty()); - EXPECT_FALSE(blob.CreationTime.empty()); - EXPECT_FALSE(blob.LastModified.empty()); + EXPECT_TRUE(IsValidTime(blob.CreatedOn)); + EXPECT_TRUE(IsValidTime(blob.LastModified)); EXPECT_FALSE(blob.ETag.empty()); EXPECT_NE(blob.BlobType, Azure::Storage::Blobs::Models::BlobType::Unknown); if (blob.BlobType == Blobs::Models::BlobType::BlockBlob) @@ -376,19 +376,19 @@ namespace Azure { namespace Storage { namespace Test { options.AccessType = Blobs::Models::PublicAccessType::Blob; Blobs::Models::BlobSignedIdentifier identifier; identifier.Id = RandomString(64); - identifier.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(1), 7); - identifier.ExpiresOn = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(1), 7); + identifier.StartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(1); + identifier.ExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(1); identifier.Permissions = "r"; options.SignedIdentifiers.emplace_back(identifier); identifier.Id = RandomString(64); - identifier.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(2), 7); - identifier.ExpiresOn = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(2), 7); + identifier.StartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(2); + identifier.ExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(2); identifier.Permissions = "racwdxlt"; options.SignedIdentifiers.emplace_back(identifier); auto ret = container_client.SetAccessPolicy(options); EXPECT_FALSE(ret->ETag.empty()); - EXPECT_FALSE(ret->LastModified.empty()); + EXPECT_TRUE(IsValidTime(ret->LastModified)); auto ret2 = container_client.GetAccessPolicy(); EXPECT_EQ(ret2->ETag, ret->ETag); @@ -405,11 +405,11 @@ namespace Azure { namespace Storage { namespace Test { int32_t leaseDuration = 20; auto aLease = *m_blobContainerClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(aLease.LastModified)); EXPECT_EQ(aLease.LeaseId, leaseId1); aLease = *m_blobContainerClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(aLease.LastModified)); EXPECT_EQ(aLease.LeaseId, leaseId1); auto properties = *m_blobContainerClient->GetProperties(); @@ -419,32 +419,32 @@ namespace Azure { namespace Storage { namespace Test { auto rLease = *m_blobContainerClient->RenewLease(leaseId1); EXPECT_FALSE(rLease.ETag.empty()); - EXPECT_FALSE(rLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(rLease.LastModified)); EXPECT_EQ(rLease.LeaseId, leaseId1); std::string leaseId2 = CreateUniqueLeaseId(); EXPECT_NE(leaseId1, leaseId2); auto cLease = *m_blobContainerClient->ChangeLease(leaseId1, leaseId2); EXPECT_FALSE(cLease.ETag.empty()); - EXPECT_FALSE(cLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(cLease.LastModified)); EXPECT_EQ(cLease.LeaseId, leaseId2); auto containerInfo = *m_blobContainerClient->ReleaseLease(leaseId2); EXPECT_FALSE(containerInfo.ETag.empty()); - EXPECT_FALSE(containerInfo.LastModified.empty()); + EXPECT_TRUE(IsValidTime(containerInfo.LastModified)); aLease = *m_blobContainerClient->AcquireLease(CreateUniqueLeaseId(), InfiniteLeaseDuration); properties = *m_blobContainerClient->GetProperties(); EXPECT_FALSE(properties.LeaseDuration.GetValue().empty()); auto brokenLease = *m_blobContainerClient->BreakLease(); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(brokenLease.LastModified)); EXPECT_EQ(brokenLease.LeaseTime, 0); aLease = *m_blobContainerClient->AcquireLease(CreateUniqueLeaseId(), leaseDuration); brokenLease = *m_blobContainerClient->BreakLease(); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(brokenLease.LastModified)); EXPECT_NE(brokenLease.LeaseTime, 0); Blobs::BreakBlobContainerLeaseOptions options; @@ -645,21 +645,21 @@ namespace Azure { namespace Storage { namespace Test { { for (auto sinceTime : {TimePoint::TimeBefore, TimePoint::TimeAfter}) { - auto lastModifiedTime = FromRfc1123(containerClient.GetProperties()->LastModified); - auto timeBeforeStr = ToRfc1123(lastModifiedTime - std::chrono::seconds(1)); - auto timeAfterStr = ToRfc1123(lastModifiedTime + std::chrono::seconds(1)); + auto lastModifiedTime = containerClient.GetProperties()->LastModified; + auto timeBefore = lastModifiedTime - std::chrono::seconds(1); + auto timeAfter = lastModifiedTime + std::chrono::seconds(1); Blobs::SetBlobContainerAccessPolicyOptions options; options.AccessType = Blobs::Models::PublicAccessType::Private; if (condition == Condition::ModifiedSince) { options.AccessConditions.IfModifiedSince - = sinceTime == TimePoint::TimeBefore ? timeBeforeStr : timeAfterStr; + = sinceTime == TimePoint::TimeBefore ? timeBefore : timeAfter; } else if (condition == Condition::UnmodifiedSince) { options.AccessConditions.IfUnmodifiedSince - = sinceTime == TimePoint::TimeBefore ? timeBeforeStr : timeAfterStr; + = sinceTime == TimePoint::TimeBefore ? timeBefore : timeAfter; } bool shouldThrow = (condition == Condition::ModifiedSince && sinceTime == TimePoint::TimeAfter) @@ -723,8 +723,8 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE(deletedContainerItem.IsDeleted); EXPECT_TRUE(deletedContainerItem.VersionId.HasValue()); EXPECT_FALSE(deletedContainerItem.VersionId.GetValue().empty()); - EXPECT_TRUE(deletedContainerItem.DeletedTime.HasValue()); - EXPECT_FALSE(deletedContainerItem.DeletedTime.GetValue().empty()); + EXPECT_TRUE(deletedContainerItem.DeletedOn.HasValue()); + EXPECT_TRUE(IsValidTime(deletedContainerItem.DeletedOn.GetValue())); EXPECT_TRUE(deletedContainerItem.RemainingRetentionDays.HasValue()); EXPECT_GE(deletedContainerItem.RemainingRetentionDays.GetValue(), 0); diff --git a/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp index bf9aed919..bd80ef93b 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp @@ -10,21 +10,22 @@ namespace Azure { namespace Storage { namespace Test { TEST_F(BlobContainerClientTest, BlobSasTest) { + auto sasStartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(5); + auto sasExpiredOn = Azure::Core::DateTime::Now() - std::chrono::minutes(1); + auto sasExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(60); + Sas::AccountSasBuilder accountSasBuilder; accountSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - accountSasBuilder.StartsOn - = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - accountSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + accountSasBuilder.StartsOn = sasStartsOn; + accountSasBuilder.ExpiresOn = sasExpiresOn; accountSasBuilder.Services = Sas::AccountSasServices::Blobs; accountSasBuilder.ResourceTypes = Sas::AccountSasResource::All; std::string blobName = RandomString(); Sas::BlobSasBuilder blobSasBuilder; blobSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - blobSasBuilder.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - blobSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + blobSasBuilder.StartsOn = sasStartsOn; + blobSasBuilder.ExpiresOn = sasExpiresOn; blobSasBuilder.BlobContainerName = m_containerName; blobSasBuilder.BlobName = blobName; blobSasBuilder.Resource = Sas::BlobSasResource::Blob; @@ -49,9 +50,7 @@ namespace Azure { namespace Storage { namespace Test { serviceUrl, std::make_shared( AadTenantId(), AadClientId(), AadClientSecret())); - auto userDelegationKey = *blobServiceClient1.GetUserDelegationKey( - ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)), - ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60))); + auto userDelegationKey = *blobServiceClient1.GetUserDelegationKey(sasStartsOn, sasExpiresOn); auto verify_blob_read = [&](const std::string& sas) { EXPECT_NO_THROW(blobClient0.Create()); @@ -218,8 +217,8 @@ namespace Azure { namespace Storage { namespace Test { // Expires { Sas::AccountSasBuilder builder2 = accountSasBuilder; - builder2.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - builder2.ExpiresOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(1)); + builder2.StartsOn = sasStartsOn; + builder2.ExpiresOn = sasExpiredOn; auto sasToken = builder2.GenerateSasToken(*keyCredential); EXPECT_THROW(verify_blob_create(sasToken), StorageException); } @@ -330,8 +329,8 @@ namespace Azure { namespace Storage { namespace Test { // Expires { Sas::BlobSasBuilder builder2 = blobSasBuilder; - builder2.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - builder2.ExpiresOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(1)); + builder2.StartsOn = sasStartsOn; + builder2.ExpiresOn = sasExpiredOn; auto sasToken = builder2.GenerateSasToken(*keyCredential); EXPECT_THROW(verify_blob_create(sasToken), StorageException); @@ -372,15 +371,15 @@ namespace Azure { namespace Storage { namespace Test { options.AccessType = Blobs::Models::PublicAccessType::Blob; Blobs::Models::BlobSignedIdentifier identifier; identifier.Id = RandomString(64); - identifier.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - identifier.ExpiresOn = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + identifier.StartsOn = sasStartsOn; + identifier.ExpiresOn = sasExpiresOn; identifier.Permissions = "r"; options.SignedIdentifiers.emplace_back(identifier); m_blobContainerClient->SetAccessPolicy(options); Sas::BlobSasBuilder builder2 = blobSasBuilder; builder2.StartsOn.Reset(); - builder2.ExpiresOn.clear(); + builder2.ExpiresOn = Azure::Core::DateTime(); builder2.SetPermissions(static_cast(0)); builder2.Identifier = identifier.Id; diff --git a/sdk/storage/azure-storage-blobs/test/blob_service_client_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_service_client_test.cpp index 95045992f..e0a16fafd 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_service_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_service_client_test.cpp @@ -144,10 +144,10 @@ namespace Azure { namespace Storage { namespace Test { { EXPECT_FALSE(container.Name.empty()); EXPECT_FALSE(container.ETag.empty()); - EXPECT_FALSE(container.LastModified.empty()); + EXPECT_TRUE(IsValidTime(container.LastModified)); EXPECT_FALSE(container.IsDeleted); EXPECT_FALSE(container.VersionId.HasValue()); - EXPECT_FALSE(container.DeletedTime.HasValue()); + EXPECT_FALSE(container.DeletedOn.HasValue()); EXPECT_FALSE(container.RemainingRetentionDays.HasValue()); EXPECT_EQ(container.DefaultEncryptionScope, AccountEncryptionKey); EXPECT_FALSE(container.PreventEncryptionScopeOverride); @@ -339,9 +339,9 @@ namespace Azure { namespace Storage { namespace Test { auto serviceStatistics = *secondaryServiceClient.GetStatistics(); EXPECT_NE( serviceStatistics.GeoReplication.Status, Blobs::Models::BlobGeoReplicationStatus::Unknown); - if (serviceStatistics.GeoReplication.LastSyncTime.HasValue()) + if (serviceStatistics.GeoReplication.LastSyncedOn.HasValue()) { - EXPECT_FALSE(serviceStatistics.GeoReplication.LastSyncTime.GetValue().empty()); + EXPECT_TRUE(IsValidTime(serviceStatistics.GeoReplication.LastSyncedOn.GetValue())); } } diff --git a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp index 07d9a060a..630bfe7ff 100644 --- a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp @@ -66,7 +66,7 @@ namespace Azure { namespace Storage { namespace Test { = Azure::Core::Http::MemoryBodyStream(m_blobContent.data(), m_blobContent.size()); auto blobContentInfo = blockBlobClient.Upload(&blobContent, m_blobUploadOptions); EXPECT_FALSE(blobContentInfo->ETag.empty()); - EXPECT_FALSE(blobContentInfo->LastModified.empty()); + EXPECT_TRUE(IsValidTime(blobContentInfo->LastModified)); EXPECT_TRUE(blobContentInfo->VersionId.HasValue()); EXPECT_FALSE(blobContentInfo->VersionId.GetValue().empty()); EXPECT_FALSE(blobContentInfo->EncryptionScope.HasValue()); @@ -84,8 +84,8 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); - EXPECT_FALSE(res->CreationTime.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); + EXPECT_TRUE(IsValidTime(res->CreatedOn)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); @@ -106,16 +106,16 @@ namespace Azure { namespace Storage { namespace Test { { { auto res = m_blockBlobClient->Download(); - ASSERT_TRUE(res->LastAccessTime.HasValue()); - EXPECT_FALSE(res->LastAccessTime.GetValue().empty()); + ASSERT_TRUE(res->LastAccessedOn.HasValue()); + EXPECT_TRUE(IsValidTime(res->LastAccessedOn.GetValue())); } { auto res = m_blockBlobClient->GetProperties(); - ASSERT_TRUE(res->LastAccessTime.HasValue()); - EXPECT_FALSE(res->LastAccessTime.GetValue().empty()); + ASSERT_TRUE(res->LastAccessedOn.HasValue()); + EXPECT_TRUE(IsValidTime(res->LastAccessedOn.GetValue())); } { - std::string lastAccessTime; + Azure::Core::DateTime lastAccessedOn; Azure::Storage::Blobs::ListBlobsSinglePageOptions options; options.Prefix = m_blobName; @@ -127,13 +127,13 @@ namespace Azure { namespace Storage { namespace Test { { if (blob.Name == m_blobName) { - lastAccessTime = blob.LastAccessTime.GetValue(); + lastAccessedOn = blob.LastAccessedOn.GetValue(); break; } } } while (!options.ContinuationToken.GetValue().empty()); - EXPECT_FALSE(lastAccessTime.empty()); + EXPECT_TRUE(IsValidTime(lastAccessedOn)); } } @@ -154,7 +154,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); @@ -175,7 +175,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_FALSE(res->CopyId.empty()); EXPECT_TRUE(res->VersionId.HasValue()); EXPECT_FALSE(res->VersionId.GetValue().empty()); @@ -191,7 +191,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(properties.CopyProgress.GetValue().empty()); if (properties.CopyStatus.GetValue() == Azure::Storage::Blobs::Models::CopyStatus::Success) { - EXPECT_FALSE(properties.CopyCompletionTime.GetValue().empty()); + EXPECT_TRUE(IsValidTime(properties.CopyCompletedOn.GetValue())); } } @@ -202,7 +202,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_FALSE(res->Snapshot.empty()); EXPECT_TRUE(res->VersionId.HasValue()); EXPECT_FALSE(res->VersionId.GetValue().empty()); @@ -256,14 +256,14 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); - EXPECT_FALSE(res->CreationTime.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); + EXPECT_TRUE(IsValidTime(res->CreatedOn)); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->ContentLength, static_cast(m_blobContent.size())); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->HttpHeaders.ContentHash.Algorithm, Storage::HashAlgorithm::Md5); EXPECT_EQ(res->Tier.GetValue(), Azure::Storage::Blobs::Models::AccessTier::Cool); - EXPECT_FALSE(res->AccessTierChangeTime.GetValue().empty()); + EXPECT_TRUE(IsValidTime(res->AccessTierChangedOn.GetValue())); } TEST_F(BlockBlobClientTest, StageBlock) @@ -283,7 +283,7 @@ namespace Azure { namespace Storage { namespace Test { options.Metadata = m_blobUploadOptions.Metadata; auto blobContentInfo = blockBlobClient.CommitBlockList({blockId1}, options); EXPECT_FALSE(blobContentInfo->ETag.empty()); - EXPECT_FALSE(blobContentInfo->LastModified.empty()); + EXPECT_TRUE(IsValidTime(blobContentInfo->LastModified)); EXPECT_TRUE(blobContentInfo->VersionId.HasValue()); EXPECT_FALSE(blobContentInfo->VersionId.GetValue().empty()); auto res = blockBlobClient.GetBlockList(); @@ -291,7 +291,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderDate).empty()); EXPECT_FALSE(res.GetRawResponse().GetHeaders().at(Details::HttpHeaderXMsVersion).empty()); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->ContentLength, static_cast(block1Content.size())); ASSERT_FALSE(res->CommittedBlocks.empty()); EXPECT_EQ(res->CommittedBlocks[0].Name, blockId1); @@ -568,14 +568,14 @@ namespace Azure { namespace Storage { namespace Test { auto res = blockBlobClient.DownloadTo(emptyContent.data(), 0); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); res = blockBlobClient.DownloadTo(tempFilename); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); @@ -585,14 +585,14 @@ namespace Azure { namespace Storage { namespace Test { res = blockBlobClient.DownloadTo(emptyContent.data(), static_cast(8_MB)); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); res = blockBlobClient.DownloadTo(tempFilename); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); @@ -610,14 +610,14 @@ namespace Azure { namespace Storage { namespace Test { emptyContent.data(), static_cast(8_MB), options); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); res = blockBlobClient.DownloadTo(tempFilename, options); EXPECT_EQ(res->ContentLength, 0); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(res->HttpHeaders, m_blobUploadOptions.HttpHeaders); EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); @@ -670,7 +670,7 @@ namespace Azure { namespace Storage { namespace Test { auto res = blockBlobClient.UploadFrom( blobContent.data(), static_cast(blobSize), options); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); auto properties = *blockBlobClient.GetProperties(); properties.HttpHeaders.ContentHash.Value.clear(); EXPECT_EQ(properties.ContentLength, blobSize); @@ -705,7 +705,7 @@ namespace Azure { namespace Storage { namespace Test { } auto res = blockBlobClient.UploadFrom(tempFilename, options); EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); auto properties = *blockBlobClient.GetProperties(); properties.HttpHeaders.ContentHash.Value.clear(); EXPECT_EQ(properties.ContentLength, blobSize); diff --git a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp index 8e23c233b..41878985e 100644 --- a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp @@ -50,7 +50,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, RandomString()); auto blobContentInfo = pageBlobClient.Create(0, m_blobUploadOptions); EXPECT_FALSE(blobContentInfo->ETag.empty()); - EXPECT_FALSE(blobContentInfo->LastModified.empty()); + EXPECT_TRUE(IsValidTime(blobContentInfo->LastModified)); EXPECT_TRUE(blobContentInfo->VersionId.HasValue()); EXPECT_FALSE(blobContentInfo->VersionId.GetValue().empty()); EXPECT_FALSE(blobContentInfo->EncryptionScope.HasValue()); @@ -147,7 +147,7 @@ namespace Azure { namespace Storage { namespace Test { sourceUri.AppendQueryParameters(GetSas()); auto copyInfo = pageBlobClient.StartCopyIncremental(sourceUri.GetAbsoluteUrl()); EXPECT_FALSE(copyInfo->ETag.empty()); - EXPECT_FALSE(copyInfo->LastModified.empty()); + EXPECT_TRUE(IsValidTime(copyInfo->LastModified)); EXPECT_FALSE(copyInfo->CopyId.empty()); EXPECT_NE(copyInfo->CopyStatus, Blobs::Models::CopyStatus::Unknown); EXPECT_TRUE(copyInfo->VersionId.HasValue()); @@ -160,11 +160,11 @@ namespace Azure { namespace Storage { namespace Test { int32_t leaseDuration = 20; auto aLease = *m_pageBlobClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(aLease.LastModified)); EXPECT_EQ(aLease.LeaseId, leaseId1); aLease = *m_pageBlobClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(aLease.LastModified)); EXPECT_EQ(aLease.LeaseId, leaseId1); auto properties = *m_pageBlobClient->GetProperties(); @@ -174,32 +174,32 @@ namespace Azure { namespace Storage { namespace Test { auto rLease = *m_pageBlobClient->RenewLease(leaseId1); EXPECT_FALSE(rLease.ETag.empty()); - EXPECT_FALSE(rLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(rLease.LastModified)); EXPECT_EQ(rLease.LeaseId, leaseId1); std::string leaseId2 = CreateUniqueLeaseId(); EXPECT_NE(leaseId1, leaseId2); auto cLease = *m_pageBlobClient->ChangeLease(leaseId1, leaseId2); EXPECT_FALSE(cLease.ETag.empty()); - EXPECT_FALSE(cLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(cLease.LastModified)); EXPECT_EQ(cLease.LeaseId, leaseId2); auto blobInfo = *m_pageBlobClient->ReleaseLease(leaseId2); EXPECT_FALSE(blobInfo.ETag.empty()); - EXPECT_FALSE(blobInfo.LastModified.empty()); + EXPECT_TRUE(IsValidTime(blobInfo.LastModified)); aLease = *m_pageBlobClient->AcquireLease(CreateUniqueLeaseId(), InfiniteLeaseDuration); properties = *m_pageBlobClient->GetProperties(); EXPECT_FALSE(properties.LeaseDuration.GetValue().empty()); auto brokenLease = *m_pageBlobClient->BreakLease(); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(brokenLease.LastModified)); EXPECT_EQ(brokenLease.LeaseTime, 0); aLease = *m_pageBlobClient->AcquireLease(CreateUniqueLeaseId(), leaseDuration); brokenLease = *m_pageBlobClient->BreakLease(); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_TRUE(IsValidTime(brokenLease.LastModified)); EXPECT_NE(brokenLease.LeaseTime, 0); Blobs::BreakBlobLeaseOptions options; diff --git a/sdk/storage/azure-storage-blobs/test/storage_retry_policy_test.cpp b/sdk/storage/azure-storage-blobs/test/storage_retry_policy_test.cpp index a2fde60bc..803c2ce7a 100644 --- a/sdk/storage/azure-storage-blobs/test/storage_retry_policy_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/storage_retry_policy_test.cpp @@ -87,7 +87,9 @@ namespace Azure { namespace Storage { namespace Test { response->AddHeader("x-ms-request-id", Core::Uuid::CreateUuid().GetUuidString()); response->AddHeader("x-ms-version", Blobs::Details::ApiVersion); response->AddHeader("x-ms-error-code", "BlobNotFound"); - response->AddHeader("date", ToRfc1123(std::chrono::system_clock::now())); + response->AddHeader( + "date", + Azure::Core::DateTime::Now().GetString(Azure::Core::DateTime::DateFormat::Rfc1123)); return response; }; auto ConstructPreconditionFailedResponse = []() { @@ -109,36 +111,40 @@ namespace Azure { namespace Storage { namespace Test { response->AddHeader("x-ms-request-id", Core::Uuid::CreateUuid().GetUuidString()); response->AddHeader("x-ms-version", Blobs::Details::ApiVersion); response->AddHeader("x-ms-error-code", "ConditionNotMet"); - response->AddHeader("date", ToRfc1123(std::chrono::system_clock::now())); + response->AddHeader( + "date", + Azure::Core::DateTime::Now().GetString(Azure::Core::DateTime::DateFormat::Rfc1123)); return response; }; - auto ConstructPrimaryResponse - = [requestOffset, requestLength, this, ConstructNotFoundResponse]() { - if (!m_primaryContent) - { - return ConstructNotFoundResponse(); - } - auto response = std::make_unique( - Core::Http::RawResponse(1, 1, Core::Http::HttpStatusCode::Ok, "OK")); - int64_t bodyLength = std::min( - static_cast(m_primaryContent->length()) - requestOffset, requestLength); - auto bodyStream = std::make_unique( - reinterpret_cast(m_primaryContent->data() + requestOffset), - bodyLength); - response->SetBodyStream(std::move(bodyStream)); - response->AddHeader("content-length", std::to_string(bodyLength)); - response->AddHeader("etag", m_primaryETag); - response->AddHeader("last-modified", "Thu 27 Aug 2001 07:00:00 GMT"); - response->AddHeader("x-ms-request-id", Core::Uuid::CreateUuid().GetUuidString()); - response->AddHeader("x-ms-version", Blobs::Details::ApiVersion); - response->AddHeader("x-ms-creation-time", "Thu 27 Aug 2002 07:00:00 GMT"); - response->AddHeader("x-ms-lease-status", "unlocked"); - response->AddHeader("x-ms-lease-state", "available"); - response->AddHeader("x-ms-blob-type", "BlockBlob"); - response->AddHeader("x-ms-server-encrypted", "true"); - response->AddHeader("date", ToRfc1123(std::chrono::system_clock::now())); - return response; - }; + auto ConstructPrimaryResponse = + [requestOffset, requestLength, this, ConstructNotFoundResponse]() { + if (!m_primaryContent) + { + return ConstructNotFoundResponse(); + } + auto response = std::make_unique( + Core::Http::RawResponse(1, 1, Core::Http::HttpStatusCode::Ok, "OK")); + int64_t bodyLength = std::min( + static_cast(m_primaryContent->length()) - requestOffset, requestLength); + auto bodyStream = std::make_unique( + reinterpret_cast(m_primaryContent->data() + requestOffset), + bodyLength); + response->SetBodyStream(std::move(bodyStream)); + response->AddHeader("content-length", std::to_string(bodyLength)); + response->AddHeader("etag", m_primaryETag); + response->AddHeader("last-modified", "Thu, 23 Aug 2001 07:00:00 GMT"); + response->AddHeader("x-ms-request-id", Core::Uuid::CreateUuid().GetUuidString()); + response->AddHeader("x-ms-version", Blobs::Details::ApiVersion); + response->AddHeader("x-ms-creation-time", "Thu, 22 Aug 2002 07:00:00 GMT"); + response->AddHeader("x-ms-lease-status", "unlocked"); + response->AddHeader("x-ms-lease-state", "available"); + response->AddHeader("x-ms-blob-type", "BlockBlob"); + response->AddHeader("x-ms-server-encrypted", "true"); + response->AddHeader( + "date", + Azure::Core::DateTime::Now().GetString(Azure::Core::DateTime::DateFormat::Rfc1123)); + return response; + }; auto ConstructSecondaryResponse = [requestOffset, requestLength, this, ConstructNotFoundResponse]() { if (!m_secondaryContent) @@ -155,15 +161,17 @@ namespace Azure { namespace Storage { namespace Test { response->SetBodyStream(std::move(bodyStream)); response->AddHeader("content-length", std::to_string(bodyLength)); response->AddHeader("etag", m_secondaryETag); - response->AddHeader("last-modified", "Thu 27 Aug 2001 07:00:00 GMT"); + response->AddHeader("last-modified", "Thu, 23 Aug 2001 07:00:00 GMT"); response->AddHeader("x-ms-request-id", Core::Uuid::CreateUuid().GetUuidString()); response->AddHeader("x-ms-version", Blobs::Details::ApiVersion); - response->AddHeader("x-ms-creation-time", "Thu 27 Aug 2002 07:00:00 GMT"); + response->AddHeader("x-ms-creation-time", "Thu, 22 Aug 2002 07:00:00 GMT"); response->AddHeader("x-ms-lease-status", "unlocked"); response->AddHeader("x-ms-lease-state", "available"); response->AddHeader("x-ms-blob-type", "BlockBlob"); response->AddHeader("x-ms-server-encrypted", "true"); - response->AddHeader("date", ToRfc1123(std::chrono::system_clock::now())); + response->AddHeader( + "date", + Azure::Core::DateTime::Now().GetString(Azure::Core::DateTime::DateFormat::Rfc1123)); return response; }; diff --git a/sdk/storage/azure-storage-common/CHANGELOG.md b/sdk/storage/azure-storage-common/CHANGELOG.md index dffd71d3c..fd575a424 100644 --- a/sdk/storage/azure-storage-common/CHANGELOG.md +++ b/sdk/storage/azure-storage-common/CHANGELOG.md @@ -2,12 +2,18 @@ ## 12.0.0-beta.6 (Unreleased) +### New Features + +- Add new type `ContentHash`. + +### Breaking Changes + - Rename `SharedKeyCredential` to `StorageSharedKeyCredential`. - Rename `StorageSharedKeyCredential::UpdateAccountKey` to `StorageSharedKeyCredential::Update`. - Move `StorageRetryPolicy`, `StoragePerRetryPolicy` and `SharedKeyPolicy` to `Details` namespace. - Remove `StorageRetryOptions`, use `Azure::Core::Http::RetryOptions` instead. - Move Account SAS into `Azure::Storage::Sas` namespace. -- Add new type `ContentHash`. +- All date time related strings are now changed to `Azure::Core::DateTime` type. ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-common/inc/azure/storage/common/access_conditions.hpp b/sdk/storage/azure-storage-common/inc/azure/storage/common/access_conditions.hpp index 68447a43d..a6962b382 100644 --- a/sdk/storage/azure-storage-common/inc/azure/storage/common/access_conditions.hpp +++ b/sdk/storage/azure-storage-common/inc/azure/storage/common/access_conditions.hpp @@ -18,15 +18,15 @@ namespace Azure { namespace Storage { { /** * @brief Specify this header to perform the operation only if the resource has been - * modified since the specified time. + * modified since the specified time. This timestamp will be truncated to second. */ - Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfModifiedSince; /** * @brief Specify this header to perform the operation only if the resource has not been - * modified since the specified date/time. + * modified since the specified date/time. This timestamp will be truncated to second. */ - Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; /** diff --git a/sdk/storage/azure-storage-common/inc/azure/storage/common/account_sas_builder.hpp b/sdk/storage/azure-storage-common/inc/azure/storage/common/account_sas_builder.hpp index 036d8e7e2..3512d11c9 100644 --- a/sdk/storage/azure-storage-common/inc/azure/storage/common/account_sas_builder.hpp +++ b/sdk/storage/azure-storage-common/inc/azure/storage/common/account_sas_builder.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "azure/storage/common/constants.hpp" @@ -216,13 +217,13 @@ namespace Azure { namespace Storage { namespace Sas { * @brief Optionally specify the time at which the shared access signature becomes * valid. */ - Azure::Core::Nullable StartsOn; + Azure::Core::Nullable StartsOn; /** * @brief The time at which the shared access signature becomes invalid. This field must * be omitted if it has been specified in an associated stored access policy. */ - std::string ExpiresOn; + Azure::Core::DateTime ExpiresOn; /** * @brief Specifies an IP address or a range of IP addresses from which to accept diff --git a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp index b49265562..3292c7258 100644 --- a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp +++ b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp @@ -91,9 +91,15 @@ namespace Azure { namespace Storage { namespace Sas { resourceTypes += "o"; } + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr + = ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate); + std::string stringToSign = credential.AccountName + "\n" + Permissions + "\n" + services + "\n" - + resourceTypes + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") + "\n" + ExpiresOn - + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + + resourceTypes + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n"; std::string signature = Base64Encode(Storage::Details::HmacSha256( @@ -106,12 +112,11 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter("ss", Storage::Details::UrlEncodeQueryParameter(services)); builder.AppendQueryParameter("srt", Storage::Details::UrlEncodeQueryParameter(resourceTypes)); builder.AppendQueryParameter("sp", Storage::Details::UrlEncodeQueryParameter(Permissions)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", startsOnStr); } - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", expiresOnStr); if (IPRange.HasValue()) { builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-common/test/test_base.cpp b/sdk/storage/azure-storage-common/test/test_base.cpp index a96f12042..29df27ba9 100644 --- a/sdk/storage/azure-storage-common/test/test_base.cpp +++ b/sdk/storage/azure-storage-common/test/test_base.cpp @@ -235,66 +235,6 @@ namespace Azure { namespace Storage { namespace Test { return result; } - std::string ToIso8601( - const std::chrono::system_clock::time_point& timePoint, - int numDecimalDigits) - { - std::time_t epoch_seconds = std::chrono::system_clock::to_time_t(timePoint); - struct tm ct; -#if defined(AZ_PLATFORM_WINDOWS) - gmtime_s(&ct, &epoch_seconds); -#elif defined(AZ_PLATFORM_POSIX) - gmtime_r(&epoch_seconds, &ct); -#endif - std::string time_str; - time_str.resize(64); - std::strftime(&time_str[0], time_str.length(), "%Y-%m-%dT%H:%M:%S", &ct); - time_str = time_str.data(); - if (numDecimalDigits != 0) - { - time_str += "."; - auto time_point_second = std::chrono::time_point_cast(timePoint); - auto decimal_part = timePoint - time_point_second; - uint64_t num_nanoseconds - = std::chrono::duration_cast(decimal_part).count(); - std::string decimal_part_str = std::to_string(num_nanoseconds); - decimal_part_str = std::string(9 - decimal_part_str.length(), '0') + decimal_part_str; - decimal_part_str.resize(numDecimalDigits); - time_str += decimal_part_str; - } - time_str += "Z"; - return time_str; - } - - std::string ToRfc1123(const std::chrono::system_clock::time_point& timePoint) - { - std::time_t epoch_seconds = std::chrono::system_clock::to_time_t(timePoint); - struct tm ct; -#if defined(AZ_PLATFORM_WINDOWS) - gmtime_s(&ct, &epoch_seconds); -#elif defined(AZ_PLATFORM_POSIX) - gmtime_r(&epoch_seconds, &ct); -#endif - std::stringstream ss; - ss.imbue(std::locale("C")); - ss << std::put_time(&ct, "%a, %d %b %Y %H:%M:%S GMT"); - return ss.str(); - } - - std::chrono::system_clock::time_point FromRfc1123(const std::string& timeStr) - { - std::tm t; - std::stringstream ss(timeStr); - ss.imbue(std::locale("C")); - ss >> std::get_time(&t, "%a, %d %b %Y %H:%M:%S GMT"); -#if defined(AZ_PLATFORM_WINDOWS) - time_t tt = _mkgmtime(&t); -#elif defined(AZ_PLATFORM_POSIX) - time_t tt = timegm(&t); -#endif - return std::chrono::system_clock::from_time_t(tt); - } - std::string InferSecondaryUrl(const std::string primaryUrl) { Azure::Core::Http::Url secondaryUri(primaryUrl); @@ -306,4 +246,12 @@ namespace Azure { namespace Storage { namespace Test { return secondaryUri.GetAbsoluteUrl(); } + bool IsValidTime(const Azure::Core::DateTime& datetime) + { + // We assume datetime within a week is valid. + const auto minTime = Azure::Core::DateTime::Now() - std::chrono::hours(24 * 7); + const auto maxTime = Azure::Core::DateTime::Now() + std::chrono::hours(24 * 7); + return datetime > minTime && datetime < maxTime; + } + }}} // namespace Azure::Storage::Test diff --git a/sdk/storage/azure-storage-common/test/test_base.hpp b/sdk/storage/azure-storage-common/test/test_base.hpp index b0fa61027..693eaa360 100644 --- a/sdk/storage/azure-storage-common/test/test_base.hpp +++ b/sdk/storage/azure-storage-common/test/test_base.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -78,13 +79,8 @@ namespace Azure { namespace Storage { namespace Test { void DeleteFile(const std::string& filename); - std::string ToIso8601( - const std::chrono::system_clock::time_point& timePoint, - int numDecimalDigits = 0); - std::string ToRfc1123(const std::chrono::system_clock::time_point& timePoint); - - std::chrono::system_clock::time_point FromRfc1123(const std::string& timeStr); - std::string InferSecondaryUrl(const std::string primaryUri); + bool IsValidTime(const Azure::Core::DateTime& datetime); + }}} // namespace Azure::Storage::Test diff --git a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md index 93d01c23f..0130bde0c 100644 --- a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md +++ b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md @@ -8,6 +8,12 @@ - `EncrytionKeySha256` are changed to binary(`std::vector`). - Replaced all transactional content MD5/CRC64 with `ContentHash` struct. - `DataLakeHttpHeaders` is renamed to `PathHttpHeaders`, and now contains `ContentHash` for the resource. +- All date time related strings are now changed to `Azure::Core::DateTime` type. +- `CreationTime` is renamed to `CreatedOn`. +- `AccessTierChangeTime` is renamed to `AccessTierChangedOn`. +- `CopyCompletionTime` is renamed to `CopyCompletedOn`. +- `ExpiryTime` is renamed to `ExpiresOn`. +- `LastAccessTime` is renamed to `LastAccessedOn`. ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp index 59220994f..53f7bd168 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp @@ -27,7 +27,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam struct GetFileSystemPropertiesResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; Storage::Metadata Metadata; }; @@ -82,8 +82,8 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam struct GetPathPropertiesResult { std::string ETag; - std::string LastModified; - std::string CreationTime; + Core::DateTime LastModified; + Core::DateTime CreatedOn; int64_t ContentLength; Storage::Metadata Metadata; Azure::Core::Nullable LeaseDuration; @@ -93,39 +93,39 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam Azure::Core::Nullable ServerEncrypted; Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable AccessTierInferred; - Azure::Core::Nullable AccessTierChangeTime; + Azure::Core::Nullable AccessTierChangedOn; Azure::Core::Nullable CopyId; Azure::Core::Nullable CopySource; Azure::Core::Nullable CopyStatus; Azure::Core::Nullable CopyProgress; - Azure::Core::Nullable CopyCompletionTime; - Azure::Core::Nullable ExpiryTime; - Azure::Core::Nullable LastAccessTime; + Azure::Core::Nullable CopyCompletedOn; + Azure::Core::Nullable ExpiresOn; + Azure::Core::Nullable LastAccessedOn; }; struct GetPathAccessControlResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; std::vector Acls; }; struct SetPathHttpHeadersResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; }; struct SetPathMetadataResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; }; struct CreatePathResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; Azure::Core::Nullable ContentLength; }; @@ -146,14 +146,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam Azure::Core::Nullable RangeLength; Azure::Core::Nullable TransactionalContentHash; std::string ETag; - std::string LastModified; + Core::DateTime LastModified; Azure::Core::Nullable LeaseDuration; LeaseStateType LeaseState = LeaseStateType::Unknown; LeaseStatusType LeaseStatus = LeaseStatusType::Unknown; Storage::Metadata Metadata; - std::string CreationTime; - Azure::Core::Nullable ExpiryTime; - Azure::Core::Nullable LastAccessTime; + Core::DateTime CreatedOn; + Azure::Core::Nullable ExpiresOn; + Azure::Core::Nullable LastAccessedOn; }; struct RenameFileResult @@ -167,7 +167,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam struct DownloadFileToResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; int64_t ContentLength = 0; PathHttpHeaders HttpHeaders; Storage::Metadata Metadata; diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_sas_builder.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_sas_builder.hpp index 059a6df50..1d50a3be9 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_sas_builder.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_sas_builder.hpp @@ -186,15 +186,16 @@ namespace Azure { namespace Storage { namespace Sas { /** * @brief Optionally specify the time at which the shared access signature becomes - * valid. + * valid. This timestamp will be truncated to second. */ - Azure::Core::Nullable StartsOn; + Azure::Core::Nullable StartsOn; /** * @brief The time at which the shared access signature becomes invalid. This field must - * be omitted if it has been specified in an associated stored access policy. + * be omitted if it has been specified in an associated stored access policy. This timestamp + * will be truncated to second. */ - std::string ExpiresOn; + Azure::Core::DateTime ExpiresOn; /** * @brief Specifies an IP address or a range of IP addresses from which to accept diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_service_client.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_service_client.hpp index 6d2a5586f..dfdaca9a8 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_service_client.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_service_client.hpp @@ -100,10 +100,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { * @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, in ISO date format. The time should be - * specified in UTC. - * @param expiresOn Expiration of the key's validity, in ISO date format. The time should be - * specified in UTC. + * @param startsOn Start time for the key's validity. The time should be specified in UTC, and + * will be truncated to second. + * @param expiresOn Expiration of the key's validity. The time should be specified in UTC, and + * will be truncated to second. * @param options Optional parameters to execute * this function. * @return Azure::Core::Response containing the user @@ -111,8 +111,8 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { * @remark This request is sent to blob endpoint. */ Azure::Core::Response GetUserDelegationKey( - const std::string& startsOn, - const std::string& expiresOn, + const Azure::Core::DateTime& startsOn, + const Azure::Core::DateTime& expiresOn, const GetUserDelegationKeyOptions& options = GetUserDelegationKeyOptions()) const { return m_blobServiceClient.GetUserDelegationKey(startsOn, expiresOn, options); diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp index ce4823825..3bf658e2a 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp @@ -4,6 +4,7 @@ #pragma once +#include "azure/core/datetime.hpp" #include "azure/core/http/http.hpp" #include "azure/core/http/pipeline.hpp" #include "azure/core/nullable.hpp" @@ -28,12 +29,11 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { constexpr static const char* PathDnsSuffixDefault = "dfs.core.windows.net"; constexpr static const char* QueryFileSystemResource = "resource"; constexpr static const char* QueryTimeout = "timeout"; - constexpr static const char* QueryRecursiveOptional = "recursive"; - constexpr static const char* QueryRecursiveRequired = "recursive"; + constexpr static const char* QueryRecursive = "recursive"; constexpr static const char* QueryContinuationToken = "continuation"; constexpr static const char* QueryPathSetAccessControlRecursiveMode = "mode"; constexpr static const char* QueryForceFlag = "forceflag"; - constexpr static const char* QueryDirectory = "directory"; + constexpr static const char* QueryPath = "directory"; constexpr static const char* QueryPrefix = "prefix"; constexpr static const char* QueryMaxResults = "maxresults"; constexpr static const char* QueryUpn = "upn"; @@ -47,15 +47,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { constexpr static const char* QueryAction = "action"; constexpr static const char* QueryMaxRecords = "maxrecords"; constexpr static const char* QueryComp = "comp"; - constexpr static const char* HeaderApiVersionParameter = "x-ms-version"; - constexpr static const char* HeaderClientRequestId = "x-ms-client-request-id"; + constexpr static const char* HeaderVersion = "x-ms-version"; + constexpr static const char* HeaderRequestId = "x-ms-client-request-id"; constexpr static const char* HeaderIfMatch = "if-match"; constexpr static const char* HeaderIfModifiedSince = "if-modified-since"; constexpr static const char* HeaderIfNoneMatch = "if-none-match"; constexpr static const char* HeaderIfUnmodifiedSince = "if-unmodified-since"; - constexpr static const char* HeaderLeaseIdOptional = "x-ms-lease-id"; - constexpr static const char* HeaderLeaseIdRequired = "x-ms-lease-id"; - constexpr static const char* HeaderProposedLeaseIdOptional = "x-ms-proposed-lease-id"; + constexpr static const char* HeaderLeaseId = "x-ms-lease-id"; + constexpr static const char* HeaderProposedLeaseId = "x-ms-proposed-lease-id"; constexpr static const char* HeaderProperties = "x-ms-properties"; constexpr static const char* HeaderSourceIfMatch = "x-ms-source-if-match"; constexpr static const char* HeaderSourceIfModifiedSince = "x-ms-source-if-modified-since"; @@ -67,9 +66,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { constexpr static const char* HeaderContentEncoding = "x-ms-content-encoding"; constexpr static const char* HeaderContentLanguage = "x-ms-content-language"; constexpr static const char* HeaderContentType = "x-ms-content-type"; - constexpr static const char* HeaderTransactionalContentMd5 = "content-md5"; - constexpr static const char* HeaderContentMd5 = "x-ms-content-md5"; - constexpr static const char* HeaderTransactionalContentCrc64 = "x-ms-content-crc64"; + constexpr static const char* HeaderTransactionalContentHashMd5 = "content-md5"; + constexpr static const char* HeaderContentHashMd5 = "x-ms-content-md5"; + constexpr static const char* HeaderTransactionalContentHashCrc64 = "x-ms-content-crc64"; constexpr static const char* HeaderUmask = "x-ms-umask"; constexpr static const char* HeaderPermissions = "x-ms-permissions"; constexpr static const char* HeaderRenameSource = "x-ms-rename-source"; @@ -77,38 +76,25 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { constexpr static const char* HeaderGroup = "x-ms-group"; constexpr static const char* HeaderAcl = "x-ms-acl"; constexpr static const char* HeaderContentLength = "content-length"; - constexpr static const char* HeaderPathExpiryOptions = "x-ms-expiry-option"; - constexpr static const char* HeaderPathExpiryTime = "x-ms-expiry-time"; + constexpr static const char* HeaderExpiryOptions = "x-ms-expiry-option"; + constexpr static const char* HeaderExpiresOn = "x-ms-expiry-time"; constexpr static const char* HeaderDate = "date"; - constexpr static const char* HeaderXMsRequestId = "x-ms-request-id"; - constexpr static const char* HeaderXMsClientRequestId = "x-ms-client-request-id"; - constexpr static const char* HeaderXMsVersion = "x-ms-version"; - constexpr static const char* HeaderXMsContinuation = "x-ms-continuation"; - constexpr static const char* HeaderXMsErrorCode = "x-ms-error-code"; + constexpr static const char* HeaderClientRequestId = "x-ms-client-request-id"; + constexpr static const char* HeaderContinuationToken = "x-ms-continuation"; + constexpr static const char* HeaderErrorCode = "x-ms-error-code"; constexpr static const char* HeaderETag = "etag"; constexpr static const char* HeaderLastModified = "last-modified"; - constexpr static const char* HeaderXMsNamespaceEnabled = "x-ms-namespace-enabled"; - constexpr static const char* HeaderXMsProperties = "x-ms-properties"; + constexpr static const char* HeaderNamespaceEnabled = "x-ms-namespace-enabled"; constexpr static const char* HeaderPathLeaseAction = "x-ms-lease-action"; constexpr static const char* HeaderXMsLeaseDuration = "x-ms-lease-duration"; constexpr static const char* HeaderXMsLeaseBreakPeriod = "x-ms-lease-break-period"; - constexpr static const char* HeaderXMsLeaseId = "x-ms-lease-id"; - constexpr static const char* HeaderXMsLeaseTime = "x-ms-lease-time"; - constexpr static const char* HeaderRange = "range"; - constexpr static const char* HeaderXMsRangeGetContentMd5 = "x-ms-range-get-content-md5"; + constexpr static const char* HeaderLeaseTime = "x-ms-lease-time"; constexpr static const char* HeaderAcceptRanges = "accept-ranges"; constexpr static const char* HeaderContentRange = "content-range"; - constexpr static const char* HeaderContentMD5 = "content-md5"; - constexpr static const char* HeaderXMsResourceType = "x-ms-resource-type"; - constexpr static const char* HeaderXMsLeaseState = "x-ms-lease-state"; - constexpr static const char* HeaderXMsLeaseStatus = "x-ms-lease-status"; - constexpr static const char* HeaderXMsContentMd5 = "x-ms-content-md5"; - constexpr static const char* HeaderXMsOwner = "x-ms-owner"; - constexpr static const char* HeaderXMsGroup = "x-ms-group"; - constexpr static const char* HeaderXMsPermissions = "x-ms-permissions"; - constexpr static const char* HeaderXMsAcl = "x-ms-acl"; - constexpr static const char* HeaderXMsContentCrc64 = "x-ms-content-crc64"; - constexpr static const char* HeaderXMsRequestServerEncrypted = "x-ms-request-server-encrypted"; + constexpr static const char* HeaderResourceType = "x-ms-resource-type"; + constexpr static const char* HeaderLeaseState = "x-ms-lease-state"; + constexpr static const char* HeaderLeaseStatus = "x-ms-lease-status"; + constexpr static const char* HeaderRequestIsServerEncrypted = "x-ms-request-server-encrypted"; } // namespace Details namespace Models { struct PathHttpHeaders @@ -120,6 +106,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { std::string ContentType; Storage::ContentHash ContentHash; }; + // The value must be "filesystem" for all filesystem operations. + enum class FileSystemResourceType + { + Filesystem, + Unknown + }; + // Mode "set" sets POSIX access control rights on files and directories, "modify" modifies one // or more POSIX access control rights that pre-exist on files and directories, "remove" // removes one or more POSIX access control rights that were present earlier on files and @@ -161,7 +154,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { std::string Name; bool IsDirectory = bool(); - std::string LastModified; + Core::DateTime LastModified; std::string ETag; int64_t ContentLength = int64_t(); std::string Owner; @@ -177,7 +170,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct FileSystem { std::string Name; - std::string LastModified; + Core::DateTime LastModified; std::string ETag; }; @@ -186,6 +179,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { std::vector Filesystems; }; + // The value must be "account" for all account operations. + enum class AccountResourceType + { + Account, + Unknown + }; + // Required only for Create File and Create Directory. The value must be "file" or "directory". enum class PathResourceType { @@ -223,6 +223,17 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Unknown }; + // Optional. If the value is "getStatus" only the system defined properties for the path are + // returned. If the value is "getAccessControl" the access control list is returned in the + // response headers (Hierarchical Namespace must be enabled for the account), otherwise the + // properties are returned. + enum class PathGetPropertiesAction + { + GetAccessControl, + GetStatus, + Unknown + }; + // Lease state of the resource. enum class LeaseStateType { @@ -242,40 +253,29 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Unknown }; - // Optional. If the value is "getStatus" only the system defined properties for the path are - // returned. If the value is "getAccessControl" the access control list is returned in the - // response headers (Hierarchical Namespace must be enabled for the account), otherwise the - // properties are returned. - enum class PathGetPropertiesAction - { - GetAccessControl, - GetStatus, - Unknown - }; - struct ServiceListFileSystemsResult { - Azure::Core::Nullable ContinuationToken; std::vector Filesystems; + Azure::Core::Nullable ContinuationToken; }; struct FileSystemCreateResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; std::string NamespaceEnabled; }; struct FileSystemSetPropertiesResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; }; struct FileSystemGetPropertiesResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; std::string Properties; std::string NamespaceEnabled; }; @@ -286,14 +286,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct FileSystemListPathsResult { - Azure::Core::Nullable ContinuationToken; std::vector Paths; + Azure::Core::Nullable ContinuationToken; }; struct PathCreateResult { Azure::Core::Nullable ETag; - Azure::Core::Nullable LastModified; + Azure::Core::Nullable LastModified; Azure::Core::Nullable ContinuationToken; Azure::Core::Nullable ContentLength; }; @@ -301,26 +301,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct PathLeaseResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; std::string LeaseId; - std::string LeaseTime; - }; - - struct PathReadResult - { - std::unique_ptr BodyStream; - std::string AcceptRanges; - PathHttpHeaders HttpHeaders; - int64_t ContentLength = int64_t(); - Azure::Core::Nullable ContentRange; - Azure::Core::Nullable TransactionalContentHash; - std::string ETag; - std::string LastModified; - std::string ResourceType; - Azure::Core::Nullable Properties; - Azure::Core::Nullable LeaseDuration; - Models::LeaseStateType LeaseState = Models::LeaseStateType::Unknown; - Models::LeaseStatusType LeaseStatus = Models::LeaseStatusType::Unknown; + int32_t LeaseTime = int32_t(); }; struct PathGetPropertiesResult @@ -330,7 +313,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { int64_t ContentLength = int64_t(); Azure::Core::Nullable ContentRange; std::string ETag; - std::string LastModified; + Core::DateTime LastModified; Azure::Core::Nullable ResourceType; Azure::Core::Nullable Properties; Azure::Core::Nullable Owner; @@ -338,8 +321,8 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Azure::Core::Nullable Permissions; Azure::Core::Nullable Acl; Azure::Core::Nullable LeaseDuration; - Azure::Core::Nullable LeaseState; - Azure::Core::Nullable LeaseStatus; + Azure::Core::Nullable LeaseState; + Azure::Core::Nullable LeaseStatus; }; struct PathDeleteResult @@ -350,22 +333,22 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct PathSetAccessControlResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; }; struct PathSetAccessControlRecursiveResult { - Azure::Core::Nullable ContinuationToken; int32_t DirectoriesSuccessful = int32_t(); int32_t FilesSuccessful = int32_t(); int32_t FailureCount = int32_t(); std::vector FailedEntries; + Azure::Core::Nullable ContinuationToken; }; struct PathFlushDataResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; int64_t ContentLength = int64_t(); }; @@ -378,11 +361,34 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct PathSetExpiryResult { std::string ETag; - std::string LastModified; + Core::DateTime LastModified; }; } // namespace Models namespace Details { + inline std::string FileSystemResourceTypeToString( + const Models::FileSystemResourceType& fileSystemResourceType) + { + switch (fileSystemResourceType) + { + case Models::FileSystemResourceType::Filesystem: + return "filesystem"; + default: + return std::string(); + } + } + + inline Models::FileSystemResourceType FileSystemResourceTypeFromString( + const std::string& fileSystemResourceType) + { + if (fileSystemResourceType == "filesystem") + { + return Models::FileSystemResourceType::Filesystem; + } + throw std::runtime_error( + "Cannot convert " + fileSystemResourceType + " to FileSystemResourceType"); + } + inline std::string PathSetAccessControlRecursiveModeToString( const Models::PathSetAccessControlRecursiveMode& pathSetAccessControlRecursiveMode) { @@ -458,6 +464,28 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { throw std::runtime_error("Cannot convert " + pathExpiryOptions + " to PathExpiryOptions"); } + inline std::string AccountResourceTypeToString( + const Models::AccountResourceType& accountResourceType) + { + switch (accountResourceType) + { + case Models::AccountResourceType::Account: + return "account"; + default: + return std::string(); + } + } + + inline Models::AccountResourceType AccountResourceTypeFromString( + const std::string& accountResourceType) + { + if (accountResourceType == "account") + { + return Models::AccountResourceType::Account; + } + throw std::runtime_error("Cannot convert " + accountResourceType + " to AccountResourceType"); + } + inline std::string PathResourceTypeToString(const Models::PathResourceType& pathResourceType) { switch (pathResourceType) @@ -554,6 +582,35 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { throw std::runtime_error("Cannot convert " + pathLeaseAction + " to PathLeaseAction"); } + inline std::string PathGetPropertiesActionToString( + const Models::PathGetPropertiesAction& pathGetPropertiesAction) + { + switch (pathGetPropertiesAction) + { + case Models::PathGetPropertiesAction::GetAccessControl: + return "getAccessControl"; + case Models::PathGetPropertiesAction::GetStatus: + return "getStatus"; + default: + return std::string(); + } + } + + inline Models::PathGetPropertiesAction PathGetPropertiesActionFromString( + const std::string& pathGetPropertiesAction) + { + if (pathGetPropertiesAction == "getAccessControl") + { + return Models::PathGetPropertiesAction::GetAccessControl; + } + if (pathGetPropertiesAction == "getStatus") + { + return Models::PathGetPropertiesAction::GetStatus; + } + throw std::runtime_error( + "Cannot convert " + pathGetPropertiesAction + " to PathGetPropertiesAction"); + } + inline std::string LeaseStateTypeToString(const Models::LeaseStateType& leaseStateType) { switch (leaseStateType) @@ -624,73 +681,24 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { throw std::runtime_error("Cannot convert " + leaseStatusType + " to LeaseStatusType"); } - inline std::string PathGetPropertiesActionToString( - const Models::PathGetPropertiesAction& pathGetPropertiesAction) - { - switch (pathGetPropertiesAction) - { - case Models::PathGetPropertiesAction::GetAccessControl: - return "getAccessControl"; - case Models::PathGetPropertiesAction::GetStatus: - return "getStatus"; - default: - return std::string(); - } - } - - inline Models::PathGetPropertiesAction PathGetPropertiesActionFromString( - const std::string& pathGetPropertiesAction) - { - if (pathGetPropertiesAction == "getAccessControl") - { - return Models::PathGetPropertiesAction::GetAccessControl; - } - if (pathGetPropertiesAction == "getStatus") - { - return Models::PathGetPropertiesAction::GetStatus; - } - throw std::runtime_error( - "Cannot convert " + pathGetPropertiesAction + " to PathGetPropertiesAction"); - } - class DataLakeRestClient { public: class Service { public: struct ListFileSystemsOptions { - Azure::Core::Nullable - Prefix; // Filters results to filesystems within the specified prefix. - Azure::Core::Nullable - ContinuationToken; // Optional. When deleting a directory, the number of paths that - // are deleted with each invocation is limited. If the number of - // paths to be deleted exceeds this limit, a continuation token is - // returned in this response header. When a continuation token is - // returned in the response, it must be specified in a subsequent - // invocation of the delete operation to continue deleting the - // directory. - Azure::Core::Nullable - MaxResults; // An optional value that specifies the maximum number of items to return. - // If omitted or greater than 5,000, the response will include up to 5,000 - // items. - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + Azure::Core::Nullable Prefix; + Azure::Core::Nullable ContinuationToken; + Azure::Core::Nullable MaxResults; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response ListFileSystems( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const ListFileSystemsOptions& listFileSystemsOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); @@ -719,7 +727,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (listFileSystemsOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, listFileSystemsOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, listFileSystemsOptions.ClientRequestId.GetValue()); } if (listFileSystemsOptions.Timeout.HasValue()) { @@ -728,18 +736,17 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(listFileSystemsOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, listFileSystemsOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, listFileSystemsOptions.ApiVersionParameter); return ListFileSystemsParseResult(context, pipeline.Send(context, request)); } private: static Azure::Core::Response ListFileSystemsParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // OK @@ -748,10 +755,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ? Models::ServiceListFileSystemsResult() : ServiceListFileSystemsResultFromFileSystemList( FileSystemListFromJson(nlohmann::json::parse(bodyBuffer))); - if (response.GetHeaders().find(Details::HeaderXMsContinuation) + if (response.GetHeaders().find(Details::HeaderContinuationToken) != response.GetHeaders().end()) { - result.ContinuationToken = response.GetHeaders().at(Details::HeaderXMsContinuation); + result.ContinuationToken = response.GetHeaders().at(Details::HeaderContinuationToken); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -763,20 +770,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } } - static Storage::Files::DataLake::Models::FileSystem FileSystemFromJson( - const nlohmann::json& node) + static Models::FileSystem FileSystemFromJson(const nlohmann::json& node) { - Storage::Files::DataLake::Models::FileSystem result; + Models::FileSystem result; result.Name = node["name"].get(); - result.LastModified = node["lastModified"].get(); + result.LastModified = Core::DateTime::Parse( + node["lastModified"].get(), Core::DateTime::DateFormat::Rfc1123); result.ETag = node["etag"].get(); return result; } - static Storage::Files::DataLake::Models::FileSystemList FileSystemListFromJson( - const nlohmann::json& node) + static Models::FileSystemList FileSystemListFromJson(const nlohmann::json& node) { - Storage::Files::DataLake::Models::FileSystemList result; + Models::FileSystemList result; for (const auto& element : node["filesystems"]) { result.Filesystems.emplace_back(FileSystemFromJson(element)); @@ -798,45 +804,28 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { public: struct CreateOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - Properties; // Optional. User-defined properties to be stored with the filesystem, in - // the format of a comma-separated list of name and value pairs "n1=v1, - // n2=v2, ...", where each value is a base64 encoded string. Note that the - // string may only contain ASCII characters in the ISO-8859-1 character - // set. If the filesystem exists, any properties not included in the list - // will be removed. All properties are removed if the header is omitted. - // To merge new and existing properties, first get all existing properties - // and the current E-Tag, then make a conditional request with the E-Tag - // and include values for all properties. + Models::FileSystemResourceType Resource = Models::FileSystemResourceType::Unknown; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable Properties; }; static Azure::Core::Response Create( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const CreateOptions& createOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::HeaderContentLength, "0"); request.GetUrl().AppendQueryParameter( Details::QueryFileSystemResource, - Storage::Details::UrlEncodeQueryParameter("filesystem")); + Storage::Details::UrlEncodeQueryParameter( + FileSystemResourceTypeToString(createOptions.Resource))); if (createOptions.ClientRequestId.HasValue()) { - request.AddHeader( - Details::HeaderClientRequestId, createOptions.ClientRequestId.GetValue()); + request.AddHeader(Details::HeaderRequestId, createOptions.ClientRequestId.GetValue()); } if (createOptions.Timeout.HasValue()) { @@ -845,7 +834,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(createOptions.Timeout.GetValue()))); } - request.AddHeader(Details::HeaderApiVersionParameter, createOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, createOptions.ApiVersionParameter); if (createOptions.Properties.HasValue()) { request.AddHeader(Details::HeaderProperties, createOptions.Properties.GetValue()); @@ -855,50 +844,30 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { struct SetPropertiesOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - Properties; // Optional. User-defined properties to be stored with the filesystem, in - // the format of a comma-separated list of name and value pairs "n1=v1, - // n2=v2, ...", where each value is a base64 encoded string. Note that the - // string may only contain ASCII characters in the ISO-8859-1 character - // set. If the filesystem exists, any properties not included in the list - // will be removed. All properties are removed if the header is omitted. - // To merge new and existing properties, first get all existing properties - // and the current E-Tag, then make a conditional request with the E-Tag - // and include values for all properties. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. + Models::FileSystemResourceType Resource = Models::FileSystemResourceType::Unknown; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable Properties; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; static Azure::Core::Response SetProperties( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const SetPropertiesOptions& setPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); request.GetUrl().AppendQueryParameter( Details::QueryFileSystemResource, - Storage::Details::UrlEncodeQueryParameter("filesystem")); + Storage::Details::UrlEncodeQueryParameter( + FileSystemResourceTypeToString(setPropertiesOptions.Resource))); if (setPropertiesOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, setPropertiesOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, setPropertiesOptions.ClientRequestId.GetValue()); } if (setPropertiesOptions.Timeout.HasValue()) { @@ -907,8 +876,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(setPropertiesOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, setPropertiesOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, setPropertiesOptions.ApiVersionParameter); if (setPropertiesOptions.Properties.HasValue()) { request.AddHeader( @@ -917,47 +885,43 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (setPropertiesOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, setPropertiesOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + setPropertiesOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (setPropertiesOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( Details::HeaderIfUnmodifiedSince, - setPropertiesOptions.IfUnmodifiedSince.GetValue()); + setPropertiesOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return SetPropertiesParseResult(context, pipeline.Send(context, request)); } struct GetPropertiesOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + Models::FileSystemResourceType Resource = Models::FileSystemResourceType::Unknown; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response GetProperties( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Head, url); request.GetUrl().AppendQueryParameter( Details::QueryFileSystemResource, - Storage::Details::UrlEncodeQueryParameter("filesystem")); + Storage::Details::UrlEncodeQueryParameter( + FileSystemResourceTypeToString(getPropertiesOptions.Resource))); if (getPropertiesOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, getPropertiesOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, getPropertiesOptions.ClientRequestId.GetValue()); } if (getPropertiesOptions.Timeout.HasValue()) { @@ -966,47 +930,34 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(getPropertiesOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, getPropertiesOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, getPropertiesOptions.ApiVersionParameter); return GetPropertiesParseResult(context, pipeline.Send(context, request)); } struct DeleteOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. + Models::FileSystemResourceType Resource = Models::FileSystemResourceType::Unknown; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; static Azure::Core::Response Delete( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const DeleteOptions& deleteOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); request.GetUrl().AppendQueryParameter( Details::QueryFileSystemResource, - Storage::Details::UrlEncodeQueryParameter("filesystem")); + Storage::Details::UrlEncodeQueryParameter( + FileSystemResourceTypeToString(deleteOptions.Resource))); if (deleteOptions.ClientRequestId.HasValue()) { - request.AddHeader( - Details::HeaderClientRequestId, deleteOptions.ClientRequestId.GetValue()); + request.AddHeader(Details::HeaderRequestId, deleteOptions.ClientRequestId.GetValue()); } if (deleteOptions.Timeout.HasValue()) { @@ -1015,74 +966,52 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(deleteOptions.Timeout.GetValue()))); } - request.AddHeader(Details::HeaderApiVersionParameter, deleteOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, deleteOptions.ApiVersionParameter); if (deleteOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, deleteOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + deleteOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (deleteOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfUnmodifiedSince, deleteOptions.IfUnmodifiedSince.GetValue()); + Details::HeaderIfUnmodifiedSince, + deleteOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return DeleteParseResult(context, pipeline.Send(context, request)); } struct ListPathsOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - ContinuationToken; // Optional. When deleting a directory, the number of paths that - // are deleted with each invocation is limited. If the number of - // paths to be deleted exceeds this limit, a continuation token is - // returned in this response header. When a continuation token is - // returned in the response, it must be specified in a subsequent - // invocation of the delete operation to continue deleting the - // directory. - Azure::Core::Nullable - Directory; // Optional. Filters results to paths within the specified directory. An - // error occurs if the directory does not exist. - bool RecursiveRequired = bool(); // Required - Azure::Core::Nullable - MaxResults; // An optional value that specifies the maximum number of items to return. - // If omitted or greater than 5,000, the response will include up to 5,000 - // items. - Azure::Core::Nullable - Upn; // Optional. Valid only when Hierarchical Namespace is enabled for the account. - // If "true", the user identity values returned in the x-ms-owner, x-ms-group, - // and x-ms-acl response headers will be transformed from Azure Active Directory - // Object IDs to User Principal Names. If "false", the values will be returned - // as Azure Active Directory Object IDs. The default value is false. Note that - // group and application Object IDs are not translated because they do not have - // unique friendly names. + Models::FileSystemResourceType Resource = Models::FileSystemResourceType::Unknown; + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable ContinuationToken; + Azure::Core::Nullable Directory; + bool RecursiveRequired = bool(); + Azure::Core::Nullable MaxResults; + Azure::Core::Nullable Upn; }; static Azure::Core::Response ListPaths( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const ListPathsOptions& listPathsOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter( Details::QueryFileSystemResource, - Storage::Details::UrlEncodeQueryParameter("filesystem")); + Storage::Details::UrlEncodeQueryParameter( + FileSystemResourceTypeToString(listPathsOptions.Resource))); if (listPathsOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, listPathsOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, listPathsOptions.ClientRequestId.GetValue()); } if (listPathsOptions.Timeout.HasValue()) { @@ -1091,8 +1020,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(listPathsOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, listPathsOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, listPathsOptions.ApiVersionParameter); if (listPathsOptions.ContinuationToken.HasValue()) { request.GetUrl().AppendQueryParameter( @@ -1103,11 +1031,11 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (listPathsOptions.Directory.HasValue()) { request.GetUrl().AppendQueryParameter( - Details::QueryDirectory, + Details::QueryPath, Storage::Details::UrlEncodeQueryParameter(listPathsOptions.Directory.GetValue())); } request.GetUrl().AppendQueryParameter( - Details::QueryRecursiveRequired, + Details::QueryRecursive, Storage::Details::UrlEncodeQueryParameter( (listPathsOptions.RecursiveRequired ? "true" : "false"))); if (listPathsOptions.MaxResults.HasValue()) @@ -1129,17 +1057,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { private: static Azure::Core::Response CreateParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Created) { // Created Models::FileSystemCreateResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - result.NamespaceEnabled = response.GetHeaders().at(Details::HeaderXMsNamespaceEnabled); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + result.NamespaceEnabled = response.GetHeaders().at(Details::HeaderNamespaceEnabled); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -1152,16 +1082,18 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { static Azure::Core::Response SetPropertiesParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Ok Models::FileSystemSetPropertiesResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -1174,18 +1106,20 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { static Azure::Core::Response GetPropertiesParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Ok Models::FileSystemGetPropertiesResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - result.Properties = response.GetHeaders().at(Details::HeaderXMsProperties); - result.NamespaceEnabled = response.GetHeaders().at(Details::HeaderXMsNamespaceEnabled); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + result.Properties = response.GetHeaders().at(Details::HeaderProperties); + result.NamespaceEnabled = response.GetHeaders().at(Details::HeaderNamespaceEnabled); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -1197,10 +1131,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response DeleteParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Accepted) { // Accepted @@ -1216,10 +1150,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response ListPathsParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Ok @@ -1228,10 +1162,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ? Models::FileSystemListPathsResult() : FileSystemListPathsResultFromPathList( PathListFromJson(nlohmann::json::parse(bodyBuffer))); - if (response.GetHeaders().find(Details::HeaderXMsContinuation) + if (response.GetHeaders().find(Details::HeaderContinuationToken) != response.GetHeaders().end()) { - result.ContinuationToken = response.GetHeaders().at(Details::HeaderXMsContinuation); + result.ContinuationToken = response.GetHeaders().at(Details::HeaderContinuationToken); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -1243,15 +1177,16 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } } - static Storage::Files::DataLake::Models::Path PathFromJson(const nlohmann::json& node) + static Models::Path PathFromJson(const nlohmann::json& node) { - Storage::Files::DataLake::Models::Path result; + Models::Path result; result.Name = node["name"].get(); if (node.contains("isDirectory")) { result.IsDirectory = (node["isDirectory"].get() == "true"); } - result.LastModified = node["lastModified"].get(); + result.LastModified = Core::DateTime::Parse( + node["lastModified"].get(), Core::DateTime::DateFormat::Rfc1123); result.ETag = node["etag"].get(); if (node.contains("contentLength")) { @@ -1263,10 +1198,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { return result; } - static Storage::Files::DataLake::Models::PathList PathListFromJson( - const nlohmann::json& node) + static Models::PathList PathListFromJson(const nlohmann::json& node) { - Storage::Files::DataLake::Models::PathList result; + Models::PathList result; for (const auto& element : node["paths"]) { result.Paths.emplace_back(PathFromJson(element)); @@ -1288,120 +1222,44 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { public: struct CreateOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - Resource; // Required only for Create File and Create Directory. The value must be - // "file" or "directory". - Azure::Core::Nullable - ContinuationToken; // Optional. When deleting a directory, the number of paths that - // are deleted with each invocation is limited. If the number of - // paths to be deleted exceeds this limit, a continuation token is - // returned in this response header. When a continuation token is - // returned in the response, it must be specified in a subsequent - // invocation of the delete operation to continue deleting the - // directory. - Azure::Core::Nullable - Mode; // Optional. Valid only when namespace is enabled. This parameter determines the - // behavior of the rename operation. The value must be "legacy" or "posix", and - // the default value will be "posix". - Azure::Core::Nullable - CacheControl; // Optional. Sets the blob's cache control. If specified, this property - // is stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentEncoding; // Optional. Sets the blob's content encoding. If specified, this - // property is stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentLanguage; // Optional. Set the blob's content language. If specified, this - // property is stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentDisposition; // Optional. Sets the blob's Content-Disposition header. - Azure::Core::Nullable - ContentType; // Optional. Sets the blob's content type. If specified, this property is - // stored with the blob and returned with a read request. - Azure::Core::Nullable - RenameSource; // An optional file or directory to be renamed. The value must have the - // following format: "/{filesystem}/{path}". If "x-ms-properties" is - // specified, the properties will overwrite the existing properties; - // otherwise, the existing properties will be preserved. This value must - // be a URL percent-encoded string. Note that the string may only - // contain ASCII characters in the ISO-8859-1 character set. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - SourceLeaseId; // A lease ID for the source path. If specified, the source path must - // have an active lease and the lease ID must match. - Azure::Core::Nullable - Properties; // Optional. User-defined properties to be stored with the filesystem, in - // the format of a comma-separated list of name and value pairs "n1=v1, - // n2=v2, ...", where each value is a base64 encoded string. Note that the - // string may only contain ASCII characters in the ISO-8859-1 character - // set. If the filesystem exists, any properties not included in the list - // will be removed. All properties are removed if the header is omitted. - // To merge new and existing properties, first get all existing properties - // and the current E-Tag, then make a conditional request with the E-Tag - // and include values for all properties. - Azure::Core::Nullable - Permissions; // Optional and only valid if Hierarchical Namespace is enabled for the - // account. Sets POSIX access permissions for the file owner, the file - // owning group, and others. Each class may be granted read, write, or - // execute permission. The sticky bit is also supported. Both symbolic - // (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are supported. - Azure::Core::Nullable - Umask; // Optional and only valid if Hierarchical Namespace is enabled for the - // account. When creating a file or directory and the parent folder does not - // have a default ACL, the umask restricts the permissions of the file or - // directory to be created. The resulting permission is given by p bitwise and - // not u, where p is the permission and u is the umask. For example, if p is - // 0777 and u is 0057, then the resulting permission is 0720. The default - // permission is 0777 for a directory and 0666 for a file. The default umask - // is 0027. The umask must be specified in 4-digit octal notation (e.g. 0766). - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. - Azure::Core::Nullable SourceIfMatch; // Specify an ETag value to operate only - // on blobs with a matching value. - Azure::Core::Nullable - SourceIfNoneMatch; // Specify an ETag value to operate only on blobs without a - // matching value. - Azure::Core::Nullable - SourceIfModifiedSince; // Specify this header value to operate only on a blob if it - // has been modified since the specified date/time. - Azure::Core::Nullable - SourceIfUnmodifiedSince; // Specify this header value to operate only on a blob if it - // has not been modified since the specified date/time. + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable Resource; + Azure::Core::Nullable ContinuationToken; + Azure::Core::Nullable Mode; + Azure::Core::Nullable CacheControl; + Azure::Core::Nullable ContentEncoding; + Azure::Core::Nullable ContentLanguage; + Azure::Core::Nullable ContentDisposition; + Azure::Core::Nullable ContentType; + Azure::Core::Nullable RenameSource; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable SourceLeaseId; + Azure::Core::Nullable Properties; + Azure::Core::Nullable Permissions; + Azure::Core::Nullable Umask; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable SourceIfMatch; + Azure::Core::Nullable SourceIfNoneMatch; + Azure::Core::Nullable SourceIfModifiedSince; + Azure::Core::Nullable SourceIfUnmodifiedSince; }; static Azure::Core::Response Create( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const CreateOptions& createOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::HeaderContentLength, "0"); if (createOptions.ClientRequestId.HasValue()) { - request.AddHeader( - Details::HeaderClientRequestId, createOptions.ClientRequestId.GetValue()); + request.AddHeader(Details::HeaderRequestId, createOptions.ClientRequestId.GetValue()); } if (createOptions.Timeout.HasValue()) { @@ -1410,7 +1268,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(createOptions.Timeout.GetValue()))); } - request.AddHeader(Details::HeaderApiVersionParameter, createOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, createOptions.ApiVersionParameter); if (createOptions.Resource.HasValue()) { request.GetUrl().AppendQueryParameter( @@ -1461,8 +1319,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (createOptions.LeaseIdOptional.HasValue()) { - request.AddHeader( - Details::HeaderLeaseIdOptional, createOptions.LeaseIdOptional.GetValue()); + request.AddHeader(Details::HeaderLeaseId, createOptions.LeaseIdOptional.GetValue()); } if (createOptions.SourceLeaseId.HasValue()) { @@ -1491,12 +1348,16 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (createOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, createOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + createOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (createOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfUnmodifiedSince, createOptions.IfUnmodifiedSince.GetValue()); + Details::HeaderIfUnmodifiedSince, + createOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (createOptions.SourceIfMatch.HasValue()) { @@ -1511,85 +1372,46 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { request.AddHeader( Details::HeaderSourceIfModifiedSince, - createOptions.SourceIfModifiedSince.GetValue()); + createOptions.SourceIfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (createOptions.SourceIfUnmodifiedSince.HasValue()) { request.AddHeader( Details::HeaderSourceIfUnmodifiedSince, - createOptions.SourceIfUnmodifiedSince.GetValue()); + createOptions.SourceIfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return CreateParseResult(context, pipeline.Send(context, request)); } struct LeaseOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Models::PathLeaseAction XMsLeaseAction = Models::PathLeaseAction:: - Unknown; // There are five lease actions: "acquire", "break", "change", "renew", and - // "release". Use "acquire" and specify the "x-ms-proposed-lease-id" and - // "x-ms-lease-duration" to acquire a new lease. Use "break" to break an - // existing lease. When a lease is broken, the lease break period is allowed - // to elapse, during which time no lease operation except break and release - // can be performed on the file. When a lease is successfully broken, the - // response indicates the interval in seconds until a new lease can be - // acquired. Use "change" and specify the current lease ID in "x-ms-lease-id" - // and the new lease ID in "x-ms-proposed-lease-id" to change the lease ID of - // an active lease. Use "renew" and specify the "x-ms-lease-id" to renew an - // existing lease. Use "release" and specify the "x-ms-lease-id" to release a - // lease. - Azure::Core::Nullable - XMsLeaseDuration; // The lease duration is required to acquire a lease, and specifies - // the duration of the lease in seconds. The lease duration must be - // between 15 and 60 seconds or -1 for infinite lease. - Azure::Core::Nullable - XMsLeaseBreakPeriod; // The lease break period duration is optional to break a lease, - // and specifies the break period of the lease in seconds. The - // lease break duration must be between 0 and 60 seconds. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - ProposedLeaseIdOptional; // Proposed lease ID, in a GUID string format. The Blob - // service returns 400 (Invalid request) if the proposed - // lease ID is not in the correct format. See Guid - // Constructor (String) for a list of valid GUID string - // formats. - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Models::PathLeaseAction XMsLeaseAction = Models::PathLeaseAction::Unknown; + Azure::Core::Nullable XMsLeaseDuration; + Azure::Core::Nullable XMsLeaseBreakPeriod; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable ProposedLeaseIdOptional; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; static Azure::Core::Response Lease( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const LeaseOptions& leaseOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Post, url); request.AddHeader(Details::HeaderContentLength, "0"); if (leaseOptions.ClientRequestId.HasValue()) { - request.AddHeader( - Details::HeaderClientRequestId, leaseOptions.ClientRequestId.GetValue()); + request.AddHeader(Details::HeaderRequestId, leaseOptions.ClientRequestId.GetValue()); } if (leaseOptions.Timeout.HasValue()) { @@ -1598,7 +1420,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(leaseOptions.Timeout.GetValue()))); } - request.AddHeader(Details::HeaderApiVersionParameter, leaseOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, leaseOptions.ApiVersionParameter); request.AddHeader( Details::HeaderPathLeaseAction, PathLeaseActionToString(leaseOptions.XMsLeaseAction)); if (leaseOptions.XMsLeaseDuration.HasValue()) @@ -1615,14 +1437,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (leaseOptions.LeaseIdOptional.HasValue()) { - request.AddHeader( - Details::HeaderLeaseIdOptional, leaseOptions.LeaseIdOptional.GetValue()); + request.AddHeader(Details::HeaderLeaseId, leaseOptions.LeaseIdOptional.GetValue()); } if (leaseOptions.ProposedLeaseIdOptional.HasValue()) { request.AddHeader( - Details::HeaderProposedLeaseIdOptional, - leaseOptions.ProposedLeaseIdOptional.GetValue()); + Details::HeaderProposedLeaseId, leaseOptions.ProposedLeaseIdOptional.GetValue()); } if (leaseOptions.IfMatch.HasValue()) { @@ -1635,166 +1455,45 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (leaseOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, leaseOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + leaseOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (leaseOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfUnmodifiedSince, leaseOptions.IfUnmodifiedSince.GetValue()); + Details::HeaderIfUnmodifiedSince, + leaseOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return LeaseParseResult(context, pipeline.Send(context, request)); } - struct ReadOptions - { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - Range; // The HTTP Range request header specifies one or more byte ranges of the - // resource to be retrieved. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - XMsRangeGetContentMd5; // Optional. When this header is set to "true" and specified - // together with the Range header, the service returns the MD5 - // hash for the range, as long as the range is less than or - // equal to 4MB in size. If this header is specified without - // the Range header, the service returns status code 400 (Bad - // Request). If this header is set to true when the range - // exceeds 4 MB in size, the service returns status code 400 - // (Bad Request). - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. - }; - - static Azure::Core::Response Read( - const Azure::Core::Http::Url& url, - Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, - const ReadOptions& readOptions) - { - Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url, true); - if (readOptions.ClientRequestId.HasValue()) - { - request.AddHeader( - Details::HeaderClientRequestId, readOptions.ClientRequestId.GetValue()); - } - if (readOptions.Timeout.HasValue()) - { - request.GetUrl().AppendQueryParameter( - Details::QueryTimeout, - Storage::Details::UrlEncodeQueryParameter( - std::to_string(readOptions.Timeout.GetValue()))); - } - request.AddHeader(Details::HeaderApiVersionParameter, readOptions.ApiVersionParameter); - if (readOptions.Range.HasValue()) - { - request.AddHeader(Details::HeaderRange, readOptions.Range.GetValue()); - } - if (readOptions.LeaseIdOptional.HasValue()) - { - request.AddHeader( - Details::HeaderLeaseIdOptional, readOptions.LeaseIdOptional.GetValue()); - } - if (readOptions.XMsRangeGetContentMd5.HasValue()) - { - request.AddHeader( - Details::HeaderXMsRangeGetContentMd5, - (readOptions.XMsRangeGetContentMd5.GetValue() ? "true" : "false")); - } - if (readOptions.IfMatch.HasValue()) - { - request.AddHeader(Details::HeaderIfMatch, readOptions.IfMatch.GetValue()); - } - if (readOptions.IfNoneMatch.HasValue()) - { - request.AddHeader(Details::HeaderIfNoneMatch, readOptions.IfNoneMatch.GetValue()); - } - if (readOptions.IfModifiedSince.HasValue()) - { - request.AddHeader( - Details::HeaderIfModifiedSince, readOptions.IfModifiedSince.GetValue()); - } - if (readOptions.IfUnmodifiedSince.HasValue()) - { - request.AddHeader( - Details::HeaderIfUnmodifiedSince, readOptions.IfUnmodifiedSince.GetValue()); - } - return ReadParseResult(context, pipeline.Send(context, request)); - } - struct GetPropertiesOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - Action; // Optional. If the value is "getStatus" only the system defined properties - // for the path are returned. If the value is "getAccessControl" the access - // control list is returned in the response headers (Hierarchical Namespace - // must be enabled for the account), otherwise the properties are returned. - Azure::Core::Nullable - Upn; // Optional. Valid only when Hierarchical Namespace is enabled for the account. - // If "true", the user identity values returned in the x-ms-owner, x-ms-group, - // and x-ms-acl response headers will be transformed from Azure Active Directory - // Object IDs to User Principal Names. If "false", the values will be returned - // as Azure Active Directory Object IDs. The default value is false. Note that - // group and application Object IDs are not translated because they do not have - // unique friendly names. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable Action; + Azure::Core::Nullable Upn; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; static Azure::Core::Response GetProperties( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Head, url); if (getPropertiesOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, getPropertiesOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, getPropertiesOptions.ClientRequestId.GetValue()); } if (getPropertiesOptions.Timeout.HasValue()) { @@ -1803,8 +1502,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(getPropertiesOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, getPropertiesOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, getPropertiesOptions.ApiVersionParameter); if (getPropertiesOptions.Action.HasValue()) { request.GetUrl().AppendQueryParameter( @@ -1822,7 +1520,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (getPropertiesOptions.LeaseIdOptional.HasValue()) { request.AddHeader( - Details::HeaderLeaseIdOptional, getPropertiesOptions.LeaseIdOptional.GetValue()); + Details::HeaderLeaseId, getPropertiesOptions.LeaseIdOptional.GetValue()); } if (getPropertiesOptions.IfMatch.HasValue()) { @@ -1836,66 +1534,44 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (getPropertiesOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, getPropertiesOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + getPropertiesOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (getPropertiesOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( Details::HeaderIfUnmodifiedSince, - getPropertiesOptions.IfUnmodifiedSince.GetValue()); + getPropertiesOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return GetPropertiesParseResult(context, pipeline.Send(context, request)); } struct DeleteOptions { - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable RecursiveOptional; // Required - Azure::Core::Nullable - ContinuationToken; // Optional. When deleting a directory, the number of paths that - // are deleted with each invocation is limited. If the number of - // paths to be deleted exceeds this limit, a continuation token is - // returned in this response header. When a continuation token is - // returned in the response, it must be specified in a subsequent - // invocation of the delete operation to continue deleting the - // directory. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. + Azure::Core::Nullable ClientRequestId; + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable RecursiveOptional; + Azure::Core::Nullable ContinuationToken; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; }; static Azure::Core::Response Delete( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const DeleteOptions& deleteOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); if (deleteOptions.ClientRequestId.HasValue()) { - request.AddHeader( - Details::HeaderClientRequestId, deleteOptions.ClientRequestId.GetValue()); + request.AddHeader(Details::HeaderRequestId, deleteOptions.ClientRequestId.GetValue()); } if (deleteOptions.Timeout.HasValue()) { @@ -1904,11 +1580,11 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(deleteOptions.Timeout.GetValue()))); } - request.AddHeader(Details::HeaderApiVersionParameter, deleteOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, deleteOptions.ApiVersionParameter); if (deleteOptions.RecursiveOptional.HasValue()) { request.GetUrl().AppendQueryParameter( - Details::QueryRecursiveOptional, + Details::QueryRecursive, Storage::Details::UrlEncodeQueryParameter( (deleteOptions.RecursiveOptional.GetValue() ? "true" : "false"))); } @@ -1921,8 +1597,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (deleteOptions.LeaseIdOptional.HasValue()) { - request.AddHeader( - Details::HeaderLeaseIdOptional, deleteOptions.LeaseIdOptional.GetValue()); + request.AddHeader(Details::HeaderLeaseId, deleteOptions.LeaseIdOptional.GetValue()); } if (deleteOptions.IfMatch.HasValue()) { @@ -1935,63 +1610,40 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (deleteOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, deleteOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + deleteOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (deleteOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfUnmodifiedSince, deleteOptions.IfUnmodifiedSince.GetValue()); + Details::HeaderIfUnmodifiedSince, + deleteOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } return DeleteParseResult(context, pipeline.Send(context, request)); } struct SetAccessControlOptions { - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable Owner; // Optional. The owner of the blob or directory. - Azure::Core::Nullable - Group; // Optional. The owning group of the blob or directory. - Azure::Core::Nullable - Permissions; // Optional and only valid if Hierarchical Namespace is enabled for the - // account. Sets POSIX access permissions for the file owner, the file - // owning group, and others. Each class may be granted read, write, or - // execute permission. The sticky bit is also supported. Both symbolic - // (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are supported. - Azure::Core::Nullable - Acl; // Sets POSIX access control rights on files and directories. The value is a - // comma-separated list of access control entries. Each access control entry - // (ACE) consists of a scope, a type, a user or group identifier, and permissions - // in the format "[scope:][type]:[id]:[permissions]". - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + Azure::Core::Nullable Timeout; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable Owner; + Azure::Core::Nullable Group; + Azure::Core::Nullable Permissions; + Azure::Core::Nullable Acl; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable ClientRequestId; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response SetAccessControl( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const SetAccessControlOptions& setAccessControlOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); @@ -2006,7 +1658,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (setAccessControlOptions.LeaseIdOptional.HasValue()) { request.AddHeader( - Details::HeaderLeaseIdOptional, setAccessControlOptions.LeaseIdOptional.GetValue()); + Details::HeaderLeaseId, setAccessControlOptions.LeaseIdOptional.GetValue()); } if (setAccessControlOptions.Owner.HasValue()) { @@ -2037,76 +1689,44 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (setAccessControlOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, setAccessControlOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + setAccessControlOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (setAccessControlOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( Details::HeaderIfUnmodifiedSince, - setAccessControlOptions.IfUnmodifiedSince.GetValue()); + setAccessControlOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (setAccessControlOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, setAccessControlOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, setAccessControlOptions.ClientRequestId.GetValue()); } - request.AddHeader( - Details::HeaderApiVersionParameter, setAccessControlOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, setAccessControlOptions.ApiVersionParameter); return SetAccessControlParseResult(context, pipeline.Send(context, request)); } struct SetAccessControlRecursiveOptions { - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - Azure::Core::Nullable - ContinuationToken; // Optional. When deleting a directory, the number of paths that - // are deleted with each invocation is limited. If the number of - // paths to be deleted exceeds this limit, a continuation token is - // returned in this response header. When a continuation token is - // returned in the response, it must be specified in a subsequent - // invocation of the delete operation to continue deleting the - // directory. + Azure::Core::Nullable Timeout; + Azure::Core::Nullable ContinuationToken; Models::PathSetAccessControlRecursiveMode Mode - = Models::PathSetAccessControlRecursiveMode:: - Unknown; // Mode "set" sets POSIX access control rights on files and directories, - // "modify" modifies one or more POSIX access control rights that - // pre-exist on files and directories, "remove" removes one or more POSIX - // access control rights that were present earlier on files and - // directories - Azure::Core::Nullable - ForceFlag; // Optional. Valid for "SetAccessControlRecursive" operation. If set to - // false, the operation will terminate quickly on encountering user errors - // (4XX). If true, the operation will ignore user errors and proceed with - // the operation on other sub-entities of the directory. Continuation token - // will only be returned when forceFlag is true in case of user errors. If - // not set the default value is false for this. - Azure::Core::Nullable - MaxRecords; // Optional. It specifies the maximum number of files or directories on - // which the acl change will be applied. If omitted or greater than 2,000, - // the request will process up to 2,000 items - Azure::Core::Nullable - Acl; // Sets POSIX access control rights on files and directories. The value is a - // comma-separated list of access control entries. Each access control entry - // (ACE) consists of a scope, a type, a user or group identifier, and permissions - // in the format "[scope:][type]:[id]:[permissions]". - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + = Models::PathSetAccessControlRecursiveMode::Unknown; + Azure::Core::Nullable ForceFlag; + Azure::Core::Nullable MaxRecords; + Azure::Core::Nullable Acl; + Azure::Core::Nullable ClientRequestId; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response SetAccessControlRecursive( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const SetAccessControlRecursiveOptions& setAccessControlRecursiveOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); @@ -2150,100 +1770,40 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (setAccessControlRecursiveOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, + Details::HeaderRequestId, setAccessControlRecursiveOptions.ClientRequestId.GetValue()); } request.AddHeader( - Details::HeaderApiVersionParameter, - setAccessControlRecursiveOptions.ApiVersionParameter); + Details::HeaderVersion, setAccessControlRecursiveOptions.ApiVersionParameter); return SetAccessControlRecursiveParseResult(context, pipeline.Send(context, request)); } struct FlushDataOptions { - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - Azure::Core::Nullable - Position; // This parameter allows the caller to upload data in parallel and control - // the order in which it is appended to the file. It is required when - // uploading data to be appended to the file and when flushing previously - // uploaded data to the file. The value must be the position where the data - // is to be appended. Uploaded data is not immediately flushed, or written, - // to the file. To flush, the previously uploaded data must be contiguous, - // the position parameter must be specified and equal to the length of the - // file after all data has been written, and there must not be a request - // entity body included with the request. - Azure::Core::Nullable - RetainUncommittedData; // Valid only for flush operations. If "true", uncommitted - // data is retained after the flush operation completes; - // otherwise, the uncommitted data is deleted after the flush - // operation. The default is false. Data at offsets less than - // the specified position are written to the file when flush - // succeeds, but this optional parameter allows data after the - // flush position to be retained for a future flush operation. - Azure::Core::Nullable - Close; // Azure Storage Events allow applications to receive notifications when files - // change. When Azure Storage Events are enabled, a file changed event is - // raised. This event has a property indicating whether this is the final - // change to distinguish the difference between an intermediate flush to a file - // stream and the final close of a file stream. The close query parameter is - // valid only when the action is "flush" and change notifications are enabled. - // If the value of close is "true" and the flush operation completes - // successfully, the service raises a file change notification with a property - // indicating that this is the final update (the file stream has been closed). - // If "false" a change notification is raised indicating the file has changed. - // The default is false. This query parameter is set to true by the Hadoop ABFS - // driver to indicate that the file stream has been closed." - Azure::Core::Nullable - ContentLength; // Required for "Append Data" and "Flush Data". Must be 0 for "Flush - // Data". Must be the length of the request content in bytes for - // "Append Data". - Azure::Core::Nullable - ContentMd5; // Specify the transactional md5 for the body, to be validated by the - // service. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - CacheControl; // Optional. Sets the blob's cache control. If specified, this property - // is stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentType; // Optional. Sets the blob's content type. If specified, this property is - // stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentDisposition; // Optional. Sets the blob's Content-Disposition header. - Azure::Core::Nullable - ContentEncoding; // Optional. Sets the blob's content encoding. If specified, this - // property is stored with the blob and returned with a read request. - Azure::Core::Nullable - ContentLanguage; // Optional. Set the blob's content language. If specified, this - // property is stored with the blob and returned with a read request. - Azure::Core::Nullable - IfMatch; // Specify an ETag value to operate only on blobs with a matching value. - Azure::Core::Nullable IfNoneMatch; // Specify an ETag value to operate only - // on blobs without a matching value. - Azure::Core::Nullable - IfModifiedSince; // Specify this header value to operate only on a blob if it has been - // modified since the specified date/time. - Azure::Core::Nullable - IfUnmodifiedSince; // Specify this header value to operate only on a blob if it has - // not been modified since the specified date/time. - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + Azure::Core::Nullable Timeout; + Azure::Core::Nullable Position; + Azure::Core::Nullable RetainUncommittedData; + Azure::Core::Nullable Close; + Azure::Core::Nullable ContentLength; + Azure::Core::Nullable ContentMd5; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable CacheControl; + Azure::Core::Nullable ContentType; + Azure::Core::Nullable ContentDisposition; + Azure::Core::Nullable ContentEncoding; + Azure::Core::Nullable ContentLanguage; + Azure::Core::Nullable IfMatch; + Azure::Core::Nullable IfNoneMatch; + Azure::Core::Nullable IfModifiedSince; + Azure::Core::Nullable IfUnmodifiedSince; + Azure::Core::Nullable ClientRequestId; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response FlushData( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const FlushDataOptions& flushDataOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); @@ -2285,13 +1845,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (flushDataOptions.ContentMd5.HasValue()) { request.AddHeader( - Details::HeaderContentMd5, + Details::HeaderContentHashMd5, Storage::Details::ToBase64String(flushDataOptions.ContentMd5.GetValue())); } if (flushDataOptions.LeaseIdOptional.HasValue()) { - request.AddHeader( - Details::HeaderLeaseIdOptional, flushDataOptions.LeaseIdOptional.GetValue()); + request.AddHeader(Details::HeaderLeaseId, flushDataOptions.LeaseIdOptional.GetValue()); } if (flushDataOptions.CacheControl.HasValue()) { @@ -2328,67 +1887,43 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (flushDataOptions.IfModifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfModifiedSince, flushDataOptions.IfModifiedSince.GetValue()); + Details::HeaderIfModifiedSince, + flushDataOptions.IfModifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (flushDataOptions.IfUnmodifiedSince.HasValue()) { request.AddHeader( - Details::HeaderIfUnmodifiedSince, flushDataOptions.IfUnmodifiedSince.GetValue()); + Details::HeaderIfUnmodifiedSince, + flushDataOptions.IfUnmodifiedSince.GetValue().GetString( + Core::DateTime::DateFormat::Rfc1123)); } if (flushDataOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, flushDataOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, flushDataOptions.ClientRequestId.GetValue()); } - request.AddHeader( - Details::HeaderApiVersionParameter, flushDataOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, flushDataOptions.ApiVersionParameter); return FlushDataParseResult(context, pipeline.Send(context, request)); } struct AppendDataOptions { - Azure::Core::Nullable - Position; // This parameter allows the caller to upload data in parallel and control - // the order in which it is appended to the file. It is required when - // uploading data to be appended to the file and when flushing previously - // uploaded data to the file. The value must be the position where the data - // is to be appended. Uploaded data is not immediately flushed, or written, - // to the file. To flush, the previously uploaded data must be contiguous, - // the position parameter must be specified and equal to the length of the - // file after all data has been written, and there must not be a request - // entity body included with the request. - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - Azure::Core::Nullable - ContentLength; // Required for "Append Data" and "Flush Data". Must be 0 for "Flush - // Data". Must be the length of the request content in bytes for - // "Append Data". - Azure::Core::Nullable - TransactionalContentMd5; // Specify the transactional md5 for the body, to be - // validated by the service. - Azure::Core::Nullable - TransactionalContentCrc64; // Specify the transactional crc64 for the body, to be - // validated by the service. - Azure::Core::Nullable - LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease - // is active and matches this ID. - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. + Azure::Core::Nullable Position; + Azure::Core::Nullable Timeout; + Azure::Core::Nullable ContentLength; + Azure::Core::Nullable TransactionalContentMd5; + Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable LeaseIdOptional; + Azure::Core::Nullable ClientRequestId; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; }; static Azure::Core::Response AppendData( const Azure::Core::Http::Url& url, Azure::Core::Http::BodyStream& bodyStream, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const AppendDataOptions& appendDataOptions) { Azure::Core::Http::Request request( @@ -2417,55 +1952,43 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (appendDataOptions.TransactionalContentMd5.HasValue()) { request.AddHeader( - Details::HeaderTransactionalContentMd5, + Details::HeaderTransactionalContentHashMd5, Storage::Details::ToBase64String( appendDataOptions.TransactionalContentMd5.GetValue())); } if (appendDataOptions.TransactionalContentCrc64.HasValue()) { request.AddHeader( - Details::HeaderTransactionalContentCrc64, + Details::HeaderTransactionalContentHashCrc64, Storage::Details::ToBase64String( appendDataOptions.TransactionalContentCrc64.GetValue())); } if (appendDataOptions.LeaseIdOptional.HasValue()) { - request.AddHeader( - Details::HeaderLeaseIdOptional, appendDataOptions.LeaseIdOptional.GetValue()); + request.AddHeader(Details::HeaderLeaseId, appendDataOptions.LeaseIdOptional.GetValue()); } if (appendDataOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, appendDataOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, appendDataOptions.ClientRequestId.GetValue()); } - request.AddHeader( - Details::HeaderApiVersionParameter, appendDataOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, appendDataOptions.ApiVersionParameter); return AppendDataParseResult(context, pipeline.Send(context, request)); } struct SetExpiryOptions { - Azure::Core::Nullable - Timeout; // The timeout parameter is expressed in seconds. - // For more information, see Setting - // Timeouts for Blob Service Operations. - std::string ApiVersionParameter - = Details::DefaultServiceApiVersion; // Specifies the version of the operation to use - // for this request. - Azure::Core::Nullable - ClientRequestId; // Provides a client-generated, opaque value with a 1 KB character - // limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - Models::PathExpiryOptions XMsExpiryOption - = Models::PathExpiryOptions::Unknown; // Required. Indicates mode of the expiry time - Azure::Core::Nullable PathExpiryTime; // The time to set the blob to expiry + Azure::Core::Nullable Timeout; + std::string ApiVersionParameter = Details::DefaultServiceApiVersion; + Azure::Core::Nullable ClientRequestId; + Models::PathExpiryOptions XMsExpiryOption = Models::PathExpiryOptions::Unknown; + Azure::Core::Nullable PathExpiryTime; }; static Azure::Core::Response SetExpiry( const Azure::Core::Http::Url& url, Azure::Core::Http::HttpPipeline& pipeline, - const Azure::Core::Context& context, + Azure::Core::Context context, const SetExpiryOptions& setExpiryOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); @@ -2478,30 +2001,28 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::UrlEncodeQueryParameter( std::to_string(setExpiryOptions.Timeout.GetValue()))); } - request.AddHeader( - Details::HeaderApiVersionParameter, setExpiryOptions.ApiVersionParameter); + request.AddHeader(Details::HeaderVersion, setExpiryOptions.ApiVersionParameter); if (setExpiryOptions.ClientRequestId.HasValue()) { request.AddHeader( - Details::HeaderClientRequestId, setExpiryOptions.ClientRequestId.GetValue()); + Details::HeaderRequestId, setExpiryOptions.ClientRequestId.GetValue()); } request.AddHeader( - Details::HeaderPathExpiryOptions, + Details::HeaderExpiryOptions, PathExpiryOptionsToString(setExpiryOptions.XMsExpiryOption)); if (setExpiryOptions.PathExpiryTime.HasValue()) { - request.AddHeader( - Details::HeaderPathExpiryTime, setExpiryOptions.PathExpiryTime.GetValue()); + request.AddHeader(Details::HeaderExpiresOn, setExpiryOptions.PathExpiryTime.GetValue()); } return SetExpiryParseResult(context, pipeline.Send(context, request)); } private: static Azure::Core::Response CreateParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Created) { // The file or directory was created. @@ -2513,12 +2034,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { if (response.GetHeaders().find(Details::HeaderLastModified) != response.GetHeaders().end()) { - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); } - if (response.GetHeaders().find(Details::HeaderXMsContinuation) + if (response.GetHeaders().find(Details::HeaderContinuationToken) != response.GetHeaders().end()) { - result.ContinuationToken = response.GetHeaders().at(Details::HeaderXMsContinuation); + result.ContinuationToken = response.GetHeaders().at(Details::HeaderContinuationToken); } if (response.GetHeaders().find(Details::HeaderContentLength) != response.GetHeaders().end()) @@ -2537,20 +2060,21 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response LeaseParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // The "renew", "change" or "release" action was successful. Models::PathLeaseResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - if (response.GetHeaders().find(Details::HeaderXMsLeaseId) - != response.GetHeaders().end()) + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + if (response.GetHeaders().find(Details::HeaderLeaseId) != response.GetHeaders().end()) { - result.LeaseId = response.GetHeaders().at(Details::HeaderXMsLeaseId); + result.LeaseId = response.GetHeaders().at(Details::HeaderLeaseId); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -2560,11 +2084,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { // A new lease has been created. The "acquire" action was successful. Models::PathLeaseResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - if (response.GetHeaders().find(Details::HeaderXMsLeaseId) - != response.GetHeaders().end()) + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + if (response.GetHeaders().find(Details::HeaderLeaseId) != response.GetHeaders().end()) { - result.LeaseId = response.GetHeaders().at(Details::HeaderXMsLeaseId); + result.LeaseId = response.GetHeaders().at(Details::HeaderLeaseId); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -2574,8 +2099,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { // The "break" lease action was successful. Models::PathLeaseResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - result.LeaseTime = response.GetHeaders().at(Details::HeaderXMsLeaseTime); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + result.LeaseTime = std::stoi(response.GetHeaders().at(Details::HeaderLeaseTime)); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -2586,157 +2113,11 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } } - static Azure::Core::Response ReadParseResult( - const Azure::Core::Context& context, - std::unique_ptr responsePtr) - { - /* const */ auto& response = *responsePtr; - if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) - { - // Ok - Models::PathReadResult result; - result.BodyStream = response.GetBodyStream(); - result.AcceptRanges = response.GetHeaders().at(Details::HeaderAcceptRanges); - if (response.GetHeaders().find("cache-control") != response.GetHeaders().end()) - { - result.HttpHeaders.CacheControl = response.GetHeaders().at("cache-control"); - } - if (response.GetHeaders().find("content-disposition") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentDisposition - = response.GetHeaders().at("content-disposition"); - } - if (response.GetHeaders().find("content-encoding") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentEncoding = response.GetHeaders().at("content-encoding"); - } - if (response.GetHeaders().find("content-language") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentLanguage = response.GetHeaders().at("content-language"); - } - if (response.GetHeaders().find(Details::HeaderContentLength) - != response.GetHeaders().end()) - { - result.ContentLength - = std::stoll(response.GetHeaders().at(Details::HeaderContentLength)); - } - if (response.GetHeaders().find(Details::HeaderContentRange) - != response.GetHeaders().end()) - { - result.ContentRange = response.GetHeaders().at(Details::HeaderContentRange); - } - if (response.GetHeaders().find("content-type") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentType = response.GetHeaders().at("content-type"); - } - if (response.GetHeaders().find(Details::HeaderContentMD5) - != response.GetHeaders().end()) - { - result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5); - } - result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - result.ResourceType = response.GetHeaders().at(Details::HeaderXMsResourceType); - if (response.GetHeaders().find(Details::HeaderXMsProperties) - != response.GetHeaders().end()) - { - result.Properties = response.GetHeaders().at(Details::HeaderXMsProperties); - } - if (response.GetHeaders().find(Details::HeaderXMsLeaseDuration) - != response.GetHeaders().end()) - { - result.LeaseDuration = response.GetHeaders().at(Details::HeaderXMsLeaseDuration); - } - result.LeaseState - = LeaseStateTypeFromString(response.GetHeaders().at(Details::HeaderXMsLeaseState)); - result.LeaseStatus = LeaseStatusTypeFromString( - response.GetHeaders().at(Details::HeaderXMsLeaseStatus)); - return Azure::Core::Response( - std::move(result), std::move(responsePtr)); - } - else if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::PartialContent) - { - // Partial content - Models::PathReadResult result; - result.BodyStream = response.GetBodyStream(); - result.AcceptRanges = response.GetHeaders().at(Details::HeaderAcceptRanges); - if (response.GetHeaders().find("cache-control") != response.GetHeaders().end()) - { - result.HttpHeaders.CacheControl = response.GetHeaders().at("cache-control"); - } - if (response.GetHeaders().find("content-disposition") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentDisposition - = response.GetHeaders().at("content-disposition"); - } - if (response.GetHeaders().find("content-encoding") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentEncoding = response.GetHeaders().at("content-encoding"); - } - if (response.GetHeaders().find("content-language") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentLanguage = response.GetHeaders().at("content-language"); - } - if (response.GetHeaders().find(Details::HeaderContentLength) - != response.GetHeaders().end()) - { - result.ContentLength - = std::stoll(response.GetHeaders().at(Details::HeaderContentLength)); - } - if (response.GetHeaders().find(Details::HeaderContentRange) - != response.GetHeaders().end()) - { - result.ContentRange = response.GetHeaders().at(Details::HeaderContentRange); - } - if (response.GetHeaders().find("content-type") != response.GetHeaders().end()) - { - result.HttpHeaders.ContentType = response.GetHeaders().at("content-type"); - } - if (response.GetHeaders().find(Details::HeaderContentMD5) - != response.GetHeaders().end()) - { - result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5); - } - if (response.GetHeaders().find(Details::HeaderXMsContentMd5) - != response.GetHeaders().end()) - { - result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderXMsContentMd5), HashAlgorithm::Md5); - } - result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - result.ResourceType = response.GetHeaders().at(Details::HeaderXMsResourceType); - if (response.GetHeaders().find(Details::HeaderXMsProperties) - != response.GetHeaders().end()) - { - result.Properties = response.GetHeaders().at(Details::HeaderXMsProperties); - } - if (response.GetHeaders().find(Details::HeaderXMsLeaseDuration) - != response.GetHeaders().end()) - { - result.LeaseDuration = response.GetHeaders().at(Details::HeaderXMsLeaseDuration); - } - result.LeaseState - = LeaseStateTypeFromString(response.GetHeaders().at(Details::HeaderXMsLeaseState)); - result.LeaseStatus = LeaseStatusTypeFromString( - response.GetHeaders().at(Details::HeaderXMsLeaseStatus)); - return Azure::Core::Response( - std::move(result), std::move(responsePtr)); - } - else - { - unused(context); - throw Storage::StorageException::CreateFromResponse(std::move(responsePtr)); - } - } - static Azure::Core::Response GetPropertiesParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Returns all properties for the file or directory. @@ -2778,57 +2159,59 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { result.HttpHeaders.ContentType = response.GetHeaders().at("content-type"); } - if (response.GetHeaders().find(Details::HeaderContentMD5) + if (response.GetHeaders().find(Details::HeaderContentHashMd5) != response.GetHeaders().end()) { result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5); + response.GetHeaders().at(Details::HeaderContentHashMd5), HashAlgorithm::Md5); } result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); - if (response.GetHeaders().find(Details::HeaderXMsResourceType) + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); + if (response.GetHeaders().find(Details::HeaderResourceType) != response.GetHeaders().end()) { - result.ResourceType = response.GetHeaders().at(Details::HeaderXMsResourceType); + result.ResourceType = response.GetHeaders().at(Details::HeaderResourceType); } - if (response.GetHeaders().find(Details::HeaderXMsProperties) + if (response.GetHeaders().find(Details::HeaderProperties) != response.GetHeaders().end()) { - result.Properties = response.GetHeaders().at(Details::HeaderXMsProperties); + result.Properties = response.GetHeaders().at(Details::HeaderProperties); } - if (response.GetHeaders().find(Details::HeaderXMsOwner) != response.GetHeaders().end()) + if (response.GetHeaders().find(Details::HeaderOwner) != response.GetHeaders().end()) { - result.Owner = response.GetHeaders().at(Details::HeaderXMsOwner); + result.Owner = response.GetHeaders().at(Details::HeaderOwner); } - if (response.GetHeaders().find(Details::HeaderXMsGroup) != response.GetHeaders().end()) + if (response.GetHeaders().find(Details::HeaderGroup) != response.GetHeaders().end()) { - result.Group = response.GetHeaders().at(Details::HeaderXMsGroup); + result.Group = response.GetHeaders().at(Details::HeaderGroup); } - if (response.GetHeaders().find(Details::HeaderXMsPermissions) + if (response.GetHeaders().find(Details::HeaderPermissions) != response.GetHeaders().end()) { - result.Permissions = response.GetHeaders().at(Details::HeaderXMsPermissions); + result.Permissions = response.GetHeaders().at(Details::HeaderPermissions); } - if (response.GetHeaders().find(Details::HeaderXMsAcl) != response.GetHeaders().end()) + if (response.GetHeaders().find(Details::HeaderAcl) != response.GetHeaders().end()) { - result.Acl = response.GetHeaders().at(Details::HeaderXMsAcl); + result.Acl = response.GetHeaders().at(Details::HeaderAcl); } if (response.GetHeaders().find(Details::HeaderXMsLeaseDuration) != response.GetHeaders().end()) { result.LeaseDuration = response.GetHeaders().at(Details::HeaderXMsLeaseDuration); } - if (response.GetHeaders().find(Details::HeaderXMsLeaseState) + if (response.GetHeaders().find(Details::HeaderLeaseState) != response.GetHeaders().end()) { - result.LeaseState = LeaseStateTypeFromString( - response.GetHeaders().at(Details::HeaderXMsLeaseState)); + result.LeaseState + = LeaseStateTypeFromString(response.GetHeaders().at(Details::HeaderLeaseState)); } - if (response.GetHeaders().find(Details::HeaderXMsLeaseStatus) + if (response.GetHeaders().find(Details::HeaderLeaseStatus) != response.GetHeaders().end()) { - result.LeaseStatus = LeaseStatusTypeFromString( - response.GetHeaders().at(Details::HeaderXMsLeaseStatus)); + result.LeaseStatus + = LeaseStatusTypeFromString(response.GetHeaders().at(Details::HeaderLeaseStatus)); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -2841,18 +2224,18 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response DeleteParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // The file was deleted. Models::PathDeleteResult result; - if (response.GetHeaders().find(Details::HeaderXMsContinuation) + if (response.GetHeaders().find(Details::HeaderContinuationToken) != response.GetHeaders().end()) { - result.ContinuationToken = response.GetHeaders().at(Details::HeaderXMsContinuation); + result.ContinuationToken = response.GetHeaders().at(Details::HeaderContinuationToken); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -2866,16 +2249,18 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { static Azure::Core::Response SetAccessControlParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Set directory access control response. Models::PathSetAccessControlResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -2888,10 +2273,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { static Azure::Core::Response SetAccessControlRecursiveParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // Set directory access control recursive response. @@ -2900,10 +2285,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ? Models::PathSetAccessControlRecursiveResult() : PathSetAccessControlRecursiveResultFromSetAccessControlRecursiveResponse( SetAccessControlRecursiveResponseFromJson(nlohmann::json::parse(bodyBuffer))); - if (response.GetHeaders().find(Details::HeaderXMsContinuation) + if (response.GetHeaders().find(Details::HeaderContinuationToken) != response.GetHeaders().end()) { - result.ContinuationToken = response.GetHeaders().at(Details::HeaderXMsContinuation); + result.ContinuationToken = response.GetHeaders().at(Details::HeaderContinuationToken); } return Azure::Core::Response( std::move(result), std::move(responsePtr)); @@ -2915,20 +2300,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } } - static Storage::Files::DataLake::Models::AclFailedEntry AclFailedEntryFromJson( - const nlohmann::json& node) + static Models::AclFailedEntry AclFailedEntryFromJson(const nlohmann::json& node) { - Storage::Files::DataLake::Models::AclFailedEntry result; + Models::AclFailedEntry result; result.Name = node["name"].get(); result.Type = node["type"].get(); result.ErrorMessage = node["errorMessage"].get(); return result; } - static Storage::Files::DataLake::Models::SetAccessControlRecursiveResponse - SetAccessControlRecursiveResponseFromJson(const nlohmann::json& node) + static Models::SetAccessControlRecursiveResponse SetAccessControlRecursiveResponseFromJson( + const nlohmann::json& node) { - Storage::Files::DataLake::Models::SetAccessControlRecursiveResponse result; + Models::SetAccessControlRecursiveResponse result; result.DirectoriesSuccessful = node["directoriesSuccessful"].get(); result.FilesSuccessful = node["filesSuccessful"].get(); result.FailureCount = node["failureCount"].get(); @@ -2952,16 +2336,18 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { return result; } static Azure::Core::Response FlushDataParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // The data was flushed (written) to the file successfully. Models::PathFlushDataResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); if (response.GetHeaders().find(Details::HeaderContentLength) != response.GetHeaders().end()) { @@ -2979,28 +2365,29 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response AppendDataParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Accepted) { // Append data to file control response. Models::PathAppendDataResult result; - if (response.GetHeaders().find(Details::HeaderContentMD5) + if (response.GetHeaders().find(Details::HeaderContentHashMd5) != response.GetHeaders().end()) { result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5); + response.GetHeaders().at(Details::HeaderContentHashMd5), HashAlgorithm::Md5); } - if (response.GetHeaders().find(Details::HeaderXMsContentCrc64) + if (response.GetHeaders().find(Details::HeaderTransactionalContentHashCrc64) != response.GetHeaders().end()) { result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderXMsContentCrc64), HashAlgorithm::Crc64); + response.GetHeaders().at(Details::HeaderTransactionalContentHashCrc64), + HashAlgorithm::Crc64); } result.IsServerEncrypted - = response.GetHeaders().at(Details::HeaderXMsRequestServerEncrypted) == "true"; + = response.GetHeaders().at(Details::HeaderRequestIsServerEncrypted) == "true"; return Azure::Core::Response( std::move(result), std::move(responsePtr)); } @@ -3012,16 +2399,18 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } static Azure::Core::Response SetExpiryParseResult( - const Azure::Core::Context& context, + Azure::Core::Context context, std::unique_ptr responsePtr) { - /* const */ auto& response = *responsePtr; + auto& response = *responsePtr; if (response.GetStatusCode() == Azure::Core::Http::HttpStatusCode::Ok) { // The blob expiry was set successfully. Models::PathSetExpiryResult result; result.ETag = response.GetHeaders().at(Details::HeaderETag); - result.LastModified = response.GetHeaders().at(Details::HeaderLastModified); + result.LastModified = Core::DateTime::Parse( + response.GetHeaders().at(Details::HeaderLastModified), + Core::DateTime::DateFormat::Rfc1123); return Azure::Core::Response( std::move(result), std::move(responsePtr)); } diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp index a1f2bdf19..3445bb776 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp @@ -52,6 +52,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ret.ContentEncoding = std::move(headers.ContentEncoding); ret.ContentLanguage = std::move(headers.ContentLanguage); ret.ContentType = std::move(headers.ContentType); + ret.ContentHash = std::move(headers.ContentHash); return ret; } @@ -350,9 +351,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ? FromBlobLeaseStatus(result->LeaseStatus.GetValue()) : ret.LeaseStatus; ret.Metadata = std::move(result->Metadata); - ret.CreationTime = std::move(result->CreationTime); - ret.ExpiryTime = std::move(result->ExpiryTime); - ret.LastAccessTime = std::move(result->LastAccessTime); + ret.CreatedOn = std::move(result->CreatedOn); + ret.ExpiresOn = std::move(result->ExpiriesOn); + ret.LastAccessedOn = std::move(result->LastAccessedOn); return Azure::Core::Response( std::move(ret), result.ExtractRawResponse()); } diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_file_system_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_file_system_client.cpp index 988fb032d..cb068813c 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_file_system_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_file_system_client.cpp @@ -248,6 +248,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const ListPathsOptions& options) const { Details::DataLakeRestClient::FileSystem::ListPathsOptions protocolLayerOptions; + protocolLayerOptions.Resource = Models::FileSystemResourceType::Filesystem; protocolLayerOptions.Upn = options.UserPrincipalName; protocolLayerOptions.ContinuationToken = options.ContinuationToken; protocolLayerOptions.MaxResults = options.MaxResults; diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp index 9a3df72d9..243878be2 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp @@ -292,7 +292,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Models::GetPathPropertiesResult ret; ret.ETag = std::move(result->ETag); ret.LastModified = std::move(result->LastModified); - ret.CreationTime = std::move(result->CreationTime); + ret.CreatedOn = std::move(result->CreatedOn); ret.Metadata = std::move(result->Metadata); ret.LeaseDuration = std::move(result->LeaseDuration); ret.LeaseState = result->LeaseState.HasValue() @@ -309,14 +309,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { ret.ServerEncrypted = result->IsServerEncrypted; ret.EncryptionKeySha256 = std::move(result->EncryptionKeySha256); ret.AccessTierInferred = std::move(result->IsAccessTierInferred); - ret.AccessTierChangeTime = std::move(result->AccessTierChangeTime); + ret.AccessTierChangedOn = std::move(result->AccessTierChangedOn); ret.CopyId = std::move(result->CopyId); ret.CopySource = std::move(result->CopySource); ret.CopyStatus = std::move(result->CopyStatus); ret.CopyProgress = std::move(result->CopyProgress); - ret.CopyCompletionTime = std::move(result->CopyCompletionTime); - ret.ExpiryTime = std::move(result->ExpiryTime); - ret.LastAccessTime = std::move(result->LastAccessTime); + ret.CopyCompletedOn = std::move(result->CopyCompletedOn); + ret.ExpiresOn = std::move(result->ExpiriesOn); + ret.LastAccessedOn = std::move(result->LastAccessedOn); ret.ContentLength = result->ContentLength; return Azure::Core::Response( std::move(ret), result.ExtractRawResponse()); diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp index 49ca5bd75..8cca0969d 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp @@ -123,11 +123,18 @@ namespace Azure { namespace Storage { namespace Sas { std::string protocol = Details::SasProtocolToString(Protocol); std::string resource = DataLakeSasResourceToString(Resource); - std::string stringToSign = Permissions + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") - + "\n" + ExpiresOn + "\n" + canonicalName + "\n" + Identifier + "\n" - + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" - + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + "\n" + CacheControl + "\n" - + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr = Identifier.empty() + ? ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + + std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + canonicalName + "\n" + Identifier + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + + ContentLanguage + "\n" + ContentType; std::string signature = Base64Encode(Storage::Details::HmacSha256( std::vector(stringToSign.begin(), stringToSign.end()), @@ -137,14 +144,13 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sv", Storage::Details::UrlEncodeQueryParameter(Storage::Details::DefaultSasVersion)); builder.AppendQueryParameter("spr", Storage::Details::UrlEncodeQueryParameter(protocol)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", Storage::Details::UrlEncodeQueryParameter(startsOnStr)); } - if (!ExpiresOn.empty()) + if (!expiresOnStr.empty()) { - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(expiresOnStr)); } if (IPRange.HasValue()) { @@ -200,15 +206,24 @@ namespace Azure { namespace Storage { namespace Sas { std::string protocol = Details::SasProtocolToString(Protocol); std::string resource = DataLakeSasResourceToString(Resource); - std::string stringToSign = Permissions + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") - + "\n" + ExpiresOn + "\n" + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" - + userDelegationKey.SignedTenantId + "\n" + userDelegationKey.SignedStartsOn + "\n" - + userDelegationKey.SignedExpiresOn + "\n" + userDelegationKey.SignedService + "\n" - + userDelegationKey.SignedVersion + "\n" + PreauthorizedAgentObjectId + "\n" + AgentObjectId - + "\n" + CorrelationId + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" - + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + "\n" - + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage - + "\n" + ContentType; + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr + = ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate); + std::string signedStartsOnStr = userDelegationKey.SignedStartsOn.GetRfc3339String( + Azure::Core::DateTime::TimeFractionFormat::Truncate); + std::string signedExpiresOnStr = userDelegationKey.SignedExpiresOn.GetRfc3339String( + Azure::Core::DateTime::TimeFractionFormat::Truncate); + + std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" + + userDelegationKey.SignedTenantId + "\n" + signedStartsOnStr + "\n" + signedExpiresOnStr + + "\n" + userDelegationKey.SignedService + "\n" + userDelegationKey.SignedVersion + "\n" + + PreauthorizedAgentObjectId + "\n" + AgentObjectId + "\n" + CorrelationId + "\n" + + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + "\n" + CacheControl + "\n" + + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; std::string signature = Base64Encode(Storage::Details::HmacSha256( std::vector(stringToSign.begin(), stringToSign.end()), @@ -218,12 +233,11 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sv", Storage::Details::UrlEncodeQueryParameter(Storage::Details::DefaultSasVersion)); builder.AppendQueryParameter("sr", Storage::Details::UrlEncodeQueryParameter(resource)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", Storage::Details::UrlEncodeQueryParameter(startsOnStr)); } - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(expiresOnStr)); builder.AppendQueryParameter("sp", Permissions); if (IPRange.HasValue()) { @@ -236,9 +250,9 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sktid", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedTenantId)); builder.AppendQueryParameter( - "skt", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedStartsOn)); + "skt", Storage::Details::UrlEncodeQueryParameter(signedStartsOnStr)); builder.AppendQueryParameter( - "ske", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedExpiresOn)); + "ske", Storage::Details::UrlEncodeQueryParameter(signedExpiresOnStr)); builder.AppendQueryParameter( "sks", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedService)); builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp index 7ab13c859..1883f48bc 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp @@ -59,6 +59,7 @@ namespace Azure { namespace Storage { namespace Test { auto response = client.GetProperties(); Files::DataLake::DeleteDirectoryOptions options1; options1.AccessConditions.IfModifiedSince = response->LastModified; + EXPECT_TRUE(IsValidTime(response->LastModified)); EXPECT_THROW(client.Delete(false, options1), StorageException); Files::DataLake::DeleteDirectoryOptions options2; options2.AccessConditions.IfUnmodifiedSince = response->LastModified; @@ -145,6 +146,7 @@ namespace Azure { namespace Storage { namespace Test { auto response = client.GetProperties(); Files::DataLake::RenameDirectoryOptions options1; options1.SourceAccessConditions.IfModifiedSince = response->LastModified; + EXPECT_TRUE(IsValidTime(response->LastModified)); EXPECT_THROW(client.Rename(LowercaseRandomString(), options1), StorageException); Files::DataLake::RenameDirectoryOptions options2; options2.SourceAccessConditions.IfUnmodifiedSince = response->LastModified; @@ -266,6 +268,7 @@ namespace Azure { namespace Storage { namespace Test { auto properties1 = m_directoryClient->GetProperties(); auto properties2 = m_directoryClient->GetProperties(); EXPECT_EQ(properties1->ETag, properties2->ETag); + EXPECT_TRUE(IsValidTime(properties1->LastModified)); EXPECT_EQ(properties1->LastModified, properties2->LastModified); // This operation changes ETag/LastModified. diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_file_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_file_client_test.cpp index 75042ed86..501b18e7b 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_file_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_file_client_test.cpp @@ -75,6 +75,7 @@ namespace Azure { namespace Storage { namespace Test { auto response = client.GetProperties(); Files::DataLake::FileDeleteOptions options1; options1.AccessConditions.IfModifiedSince = response->LastModified; + EXPECT_TRUE(IsValidTime(response->LastModified)); EXPECT_THROW(client.Delete(options1), StorageException); Files::DataLake::FileDeleteOptions options2; options2.AccessConditions.IfUnmodifiedSince = response->LastModified; @@ -263,6 +264,7 @@ namespace Azure { namespace Storage { namespace Test { auto properties1 = m_fileClient->GetProperties(); auto properties2 = m_fileClient->GetProperties(); EXPECT_EQ(properties1->ETag, properties2->ETag); + EXPECT_TRUE(IsValidTime(properties1->LastModified)); EXPECT_EQ(properties1->LastModified, properties2->LastModified); // This operation changes ETag/LastModified. @@ -309,6 +311,7 @@ namespace Azure { namespace Storage { namespace Test { auto properties2 = m_fileClient->GetProperties(); // Append does not change etag because not committed yet. EXPECT_EQ(properties1->ETag, properties2->ETag); + EXPECT_TRUE(IsValidTime(properties1->LastModified)); EXPECT_EQ(properties1->LastModified, properties2->LastModified); // Flush @@ -339,6 +342,7 @@ namespace Azure { namespace Storage { namespace Test { auto properties2 = newFileClient->GetProperties(); // Append does not change etag because not committed yet. EXPECT_EQ(properties1->ETag, properties2->ETag); + EXPECT_TRUE(IsValidTime(properties1->LastModified)); EXPECT_EQ(properties1->LastModified, properties2->LastModified); // Flush @@ -376,6 +380,7 @@ namespace Azure { namespace Storage { namespace Test { auto response = newFileClient->GetProperties(); Files::DataLake::ReadFileOptions options1; options1.AccessConditions.IfModifiedSince = response->LastModified; + EXPECT_TRUE(IsValidTime(response->LastModified)); EXPECT_THROW(newFileClient->Read(options1), StorageException); Files::DataLake::ReadFileOptions options2; options2.AccessConditions.IfUnmodifiedSince = response->LastModified; @@ -452,13 +457,16 @@ namespace Azure { namespace Storage { namespace Test { options.Metadata = RandomMetadata(); auto res = fileClient.UploadFrom(fileContent.data(), static_cast(fileSize), options); + auto lastModified = fileClient.GetProperties()->LastModified; EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); + EXPECT_EQ(res->LastModified, lastModified); auto properties = *fileClient.GetProperties(); EXPECT_EQ(properties.ContentLength, fileSize); EXPECT_EQ(properties.HttpHeaders, options.HttpHeaders); EXPECT_EQ(properties.Metadata, options.Metadata); EXPECT_EQ(properties.ETag, res->ETag); + EXPECT_TRUE(IsValidTime(res->LastModified)); EXPECT_EQ(properties.LastModified, res->LastModified); std::vector downloadContent(static_cast(fileSize), '\x00'); fileClient.DownloadTo(downloadContent.data(), static_cast(fileSize)); @@ -483,8 +491,10 @@ namespace Azure { namespace Storage { namespace Test { fileWriter.Write(fileContent.data(), fileSize, 0); } auto res = fileClient.UploadFrom(tempFilename, options); + auto lastModified = fileClient.GetProperties()->LastModified; EXPECT_FALSE(res->ETag.empty()); - EXPECT_FALSE(res->LastModified.empty()); + EXPECT_TRUE(IsValidTime(res->LastModified)); + EXPECT_EQ(res->LastModified, lastModified); auto properties = *fileClient.GetProperties(); EXPECT_EQ(properties.ContentLength, fileSize); EXPECT_EQ(properties.HttpHeaders, options.HttpHeaders); diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_path_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_path_client_test.cpp index 1af49777a..22e3822c3 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_path_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_path_client_test.cpp @@ -241,13 +241,14 @@ namespace Azure { namespace Storage { namespace Test { { std::string leaseId1 = CreateUniqueLeaseId(); int32_t leaseDuration = 20; + auto lastModified = m_pathClient->GetProperties()->LastModified; auto aLease = *m_pathClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_FALSE(aLease.LastModified > lastModified); EXPECT_EQ(aLease.LeaseId, leaseId1); aLease = *m_pathClient->AcquireLease(leaseId1, leaseDuration); EXPECT_FALSE(aLease.ETag.empty()); - EXPECT_FALSE(aLease.LastModified.empty()); + EXPECT_FALSE(aLease.LastModified > lastModified); EXPECT_EQ(aLease.LeaseId, leaseId1); auto properties = *m_pathClient->GetProperties(); @@ -255,36 +256,41 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(properties.LeaseStatus.GetValue(), Files::DataLake::Models::LeaseStatusType::Locked); EXPECT_FALSE(properties.LeaseDuration.GetValue().empty()); + lastModified = properties.LastModified; auto rLease = *m_pathClient->RenewLease(leaseId1); EXPECT_FALSE(rLease.ETag.empty()); - EXPECT_FALSE(rLease.LastModified.empty()); + EXPECT_FALSE(rLease.LastModified > lastModified); EXPECT_EQ(rLease.LeaseId, leaseId1); std::string leaseId2 = CreateUniqueLeaseId(); EXPECT_NE(leaseId1, leaseId2); + lastModified = m_pathClient->GetProperties()->LastModified; auto cLease = *m_pathClient->ChangeLease(leaseId1, leaseId2); EXPECT_FALSE(cLease.ETag.empty()); - EXPECT_FALSE(cLease.LastModified.empty()); + EXPECT_FALSE(cLease.LastModified > lastModified); EXPECT_EQ(cLease.LeaseId, leaseId2); + lastModified = m_pathClient->GetProperties()->LastModified; auto pathInfo = *m_pathClient->ReleaseLease(leaseId2); EXPECT_FALSE(pathInfo.ETag.empty()); - EXPECT_FALSE(pathInfo.LastModified.empty()); + EXPECT_FALSE(pathInfo.LastModified > lastModified); + lastModified = m_pathClient->GetProperties()->LastModified; aLease = *m_pathClient->AcquireLease(CreateUniqueLeaseId(), InfiniteLeaseDuration); properties = *m_pathClient->GetProperties(); EXPECT_FALSE(properties.LeaseDuration.GetValue().empty()); auto brokenLease = *m_pathClient->BreakLease(); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_FALSE(brokenLease.LastModified > lastModified); EXPECT_EQ(brokenLease.LeaseTime, 0); aLease = *m_pathClient->AcquireLease(CreateUniqueLeaseId(), leaseDuration); Files::DataLake::BreakPathLeaseOptions breakOptions; breakOptions.BreakPeriod = 30; + lastModified = m_pathClient->GetProperties()->LastModified; brokenLease = *m_pathClient->BreakLease(breakOptions); EXPECT_FALSE(brokenLease.ETag.empty()); - EXPECT_FALSE(brokenLease.LastModified.empty()); + EXPECT_FALSE(brokenLease.LastModified > lastModified); EXPECT_NE(brokenLease.LeaseTime, 0); Files::DataLake::BreakPathLeaseOptions options; diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_sas_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_sas_test.cpp index 1f8e2ff47..04b6b5254 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_sas_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_sas_test.cpp @@ -11,14 +11,17 @@ namespace Azure { namespace Storage { namespace Test { TEST_F(DataLakeFileSystemClientTest, DataLakeSasTest) { + auto sasStartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(5); + auto sasExpiredOn = Azure::Core::DateTime::Now() - std::chrono::minutes(1); + auto sasExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(60); + std::string directory1Name = RandomString(); std::string directory2Name = RandomString(); std::string fileName = RandomString(); Sas::DataLakeSasBuilder fileSasBuilder; fileSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - fileSasBuilder.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - fileSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + fileSasBuilder.StartsOn = sasStartsOn; + fileSasBuilder.ExpiresOn = sasExpiresOn; fileSasBuilder.FileSystemName = m_fileSystemName; fileSasBuilder.Path = directory1Name + "/" + directory2Name + "/" + fileName; fileSasBuilder.Resource = Sas::DataLakeSasResource::File; @@ -56,9 +59,7 @@ namespace Azure { namespace Storage { namespace Test { serviceUri, std::make_shared( AadTenantId(), AadClientId(), AadClientSecret())); - auto userDelegationKey = *serviceClient1.GetUserDelegationKey( - ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)), - ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60))); + auto userDelegationKey = *serviceClient1.GetUserDelegationKey(sasStartsOn, sasExpiresOn); auto verify_file_read = [&](const std::string& sas) { EXPECT_NO_THROW(fileClient0.Create()); @@ -332,8 +333,8 @@ namespace Azure { namespace Storage { namespace Test { // Expires { Sas::DataLakeSasBuilder builder2 = fileSasBuilder; - builder2.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - builder2.ExpiresOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(1)); + builder2.StartsOn = sasStartsOn; + builder2.ExpiresOn = sasExpiredOn; auto sasToken = builder2.GenerateSasToken(*keyCredential); EXPECT_THROW(verify_file_create(sasToken), StorageException); @@ -383,15 +384,15 @@ namespace Azure { namespace Storage { namespace Test { options.AccessType = Blobs::Models::PublicAccessType::Blob; Blobs::Models::BlobSignedIdentifier identifier; identifier.Id = RandomString(64); - identifier.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - identifier.ExpiresOn = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + identifier.StartsOn = sasStartsOn; + identifier.ExpiresOn = sasExpiresOn; identifier.Permissions = "r"; options.SignedIdentifiers.emplace_back(identifier); containerClinet0.SetAccessPolicy(options); Sas::DataLakeSasBuilder builder2 = fileSasBuilder; builder2.StartsOn.Reset(); - builder2.ExpiresOn.clear(); + builder2.ExpiresOn = Azure::Core::DateTime(); builder2.SetPermissions(static_cast(0)); builder2.Identifier = identifier.Id; diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_service_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_service_client_test.cpp index ff5d6570d..a91f5d8f6 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_service_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_service_client_test.cpp @@ -143,10 +143,8 @@ namespace Azure { namespace Storage { namespace Test { = Azure::Storage::Details::ParseConnectionString(AdlsGen2ConnectionString()).KeyCredential; Sas::AccountSasBuilder accountSasBuilder; accountSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - accountSasBuilder.StartsOn - = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - accountSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + accountSasBuilder.StartsOn = Core::DateTime::Now() - std::chrono::minutes(5); + accountSasBuilder.ExpiresOn = Core::DateTime::Now() + std::chrono::minutes(60); accountSasBuilder.Services = Sas::AccountSasServices::Blobs; accountSasBuilder.ResourceTypes = Sas::AccountSasResource::All; accountSasBuilder.SetPermissions(Sas::AccountSasPermissions::All); diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp index 2b545ba8f..761a4c80d 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp @@ -40,7 +40,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { constexpr static const char* HeaderVersion = "x-ms-version"; constexpr static const char* HeaderRequestId = "x-ms-client-request-id"; constexpr static const char* HeaderContentLength = "content-length"; - constexpr static const char* HeaderContentHash = "content-md5"; + constexpr static const char* HeaderContentHashMd5 = "content-md5"; constexpr static const char* HeaderCopyActionAbortConstant = "x-ms-copy-action"; constexpr static const char* HeaderCopySource = "x-ms-copy-source"; constexpr static const char* HeaderFilePermissionCopyMode = "x-ms-file-permission-copy-mode"; @@ -72,9 +72,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { constexpr static const char* HeaderRange = "x-ms-range"; constexpr static const char* HeaderRecursive = "x-ms-recursive"; constexpr static const char* HeaderQuota = "x-ms-share-quota"; - constexpr static const char* HeaderSourceContentHash = "x-ms-source-content-crc64"; - constexpr static const char* HeaderSourceIfMatchHash = "x-ms-source-if-match-crc64"; - constexpr static const char* HeaderSourceIfNoneMatchHash = "x-ms-source-if-none-match-crc64"; + constexpr static const char* HeaderSourceContentHashCrc64 = "x-ms-source-content-crc64"; + constexpr static const char* HeaderSourceIfMatchHashCrc64 = "x-ms-source-if-match-crc64"; + constexpr static const char* HeaderSourceIfNoneMatchHashCrc64 + = "x-ms-source-if-none-match-crc64"; constexpr static const char* HeaderSourceRange = "x-ms-source-range"; constexpr static const char* HeaderErrorCode = "x-ms-error-code"; constexpr static const char* HeaderETag = "etag"; @@ -105,7 +106,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { = "x-ms-number-of-handles-failed"; constexpr static const char* HeaderXMsContentLength = "x-ms-content-length"; constexpr static const char* HeaderContentRange = "content-range"; - constexpr static const char* HeaderTransactionalContentHash = "content-md5"; + constexpr static const char* HeaderTransactionalContentHashMd5 = "content-md5"; constexpr static const char* HeaderContentEncoding = "content-encoding"; constexpr static const char* HeaderCacheControl = "cache-control"; constexpr static const char* HeaderContentDisposition = "content-disposition"; @@ -120,6 +121,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { constexpr static const char* HeaderXMsRange = "x-ms-range"; constexpr static const char* HeaderFileRangeWrite = "x-ms-write"; constexpr static const char* HeaderFileRangeWriteTypeDefault = "update"; + constexpr static const char* HeaderTransactionalContentHashCrc64 = "x-ms-content-crc64"; } // namespace Details namespace Models { struct ShareFileHttpHeaders @@ -5351,7 +5353,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { if (createOptions.ContentMd5.HasValue()) { request.AddHeader( - Details::HeaderContentHash, + Details::HeaderContentHashMd5, Storage::Details::ToBase64String(createOptions.ContentMd5.GetValue())); } if (createOptions.FileContentDisposition.HasValue()) @@ -5559,7 +5561,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { if (setHttpHeadersOptions.ContentMd5.HasValue()) { request.AddHeader( - Details::HeaderContentHash, + Details::HeaderContentHashMd5, Storage::Details::ToBase64String(setHttpHeadersOptions.ContentMd5.GetValue())); } if (setHttpHeadersOptions.FileContentDisposition.HasValue()) @@ -5822,7 +5824,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { if (uploadRangeOptions.ContentMd5.HasValue()) { request.AddHeader( - Details::HeaderContentHash, + Details::HeaderContentHashMd5, Storage::Details::ToBase64String(uploadRangeOptions.ContentMd5.GetValue())); } request.AddHeader(Details::HeaderVersion, uploadRangeOptions.ApiVersionParameter); @@ -5881,21 +5883,21 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { if (uploadRangeFromUrlOptions.SourceContentCrc64.HasValue()) { request.AddHeader( - Details::HeaderSourceContentHash, + Details::HeaderSourceContentHashCrc64, Storage::Details::ToBase64String( uploadRangeFromUrlOptions.SourceContentCrc64.GetValue())); } if (uploadRangeFromUrlOptions.SourceIfMatchCrc64.HasValue()) { request.AddHeader( - Details::HeaderSourceIfMatchHash, + Details::HeaderSourceIfMatchHashCrc64, Storage::Details::ToBase64String( uploadRangeFromUrlOptions.SourceIfMatchCrc64.GetValue())); } if (uploadRangeFromUrlOptions.SourceIfNoneMatchCrc64.HasValue()) { request.AddHeader( - Details::HeaderSourceIfNoneMatchHash, + Details::HeaderSourceIfNoneMatchHashCrc64, Storage::Details::ToBase64String( uploadRangeFromUrlOptions.SourceIfNoneMatchCrc64.GetValue())); } @@ -6248,11 +6250,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.ContentRange = response.GetHeaders().at(Details::HeaderContentRange); } result.ETag = response.GetHeaders().at(Details::HeaderETag); - if (response.GetHeaders().find(Details::HeaderTransactionalContentHash) + if (response.GetHeaders().find(Details::HeaderTransactionalContentHashMd5) != response.GetHeaders().end()) { result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderTransactionalContentHash), + response.GetHeaders().at(Details::HeaderTransactionalContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderContentEncoding) @@ -6313,11 +6315,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.CopyStatus = CopyStatusTypeFromString(response.GetHeaders().at(Details::HeaderCopyStatus)); } - if (response.GetHeaders().find(Details::HeaderContentHash) + if (response.GetHeaders().find(Details::HeaderContentHashMd5) != response.GetHeaders().end()) { result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentHash), HashAlgorithm::Md5); + response.GetHeaders().at(Details::HeaderContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderIsServerEncrypted) != response.GetHeaders().end()) @@ -6384,11 +6386,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.ContentRange = response.GetHeaders().at(Details::HeaderContentRange); } result.ETag = response.GetHeaders().at(Details::HeaderETag); - if (response.GetHeaders().find(Details::HeaderTransactionalContentHash) + if (response.GetHeaders().find(Details::HeaderTransactionalContentHashMd5) != response.GetHeaders().end()) { result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderTransactionalContentHash), + response.GetHeaders().at(Details::HeaderTransactionalContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderContentEncoding) @@ -6449,11 +6451,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.CopyStatus = CopyStatusTypeFromString(response.GetHeaders().at(Details::HeaderCopyStatus)); } - if (response.GetHeaders().find(Details::HeaderContentHash) + if (response.GetHeaders().find(Details::HeaderContentHashMd5) != response.GetHeaders().end()) { result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderContentHash), HashAlgorithm::Md5); + response.GetHeaders().at(Details::HeaderContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderIsServerEncrypted) != response.GetHeaders().end()) @@ -6531,11 +6533,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.HttpHeaders.ContentType = response.GetHeaders().at(Details::HeaderContentType); } result.ETag = response.GetHeaders().at(Details::HeaderETag); - if (response.GetHeaders().find(Details::HeaderTransactionalContentHash) + if (response.GetHeaders().find(Details::HeaderTransactionalContentHashMd5) != response.GetHeaders().end()) { result.HttpHeaders.ContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderTransactionalContentHash), + response.GetHeaders().at(Details::HeaderTransactionalContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderContentEncoding) @@ -6832,11 +6834,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { result.LastModified = Core::DateTime::Parse( response.GetHeaders().at(Details::HeaderLastModified), Core::DateTime::DateFormat::Rfc1123); - if (response.GetHeaders().find(Details::HeaderTransactionalContentHash) + if (response.GetHeaders().find(Details::HeaderTransactionalContentHashMd5) != response.GetHeaders().end()) { result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderTransactionalContentHash), + response.GetHeaders().at(Details::HeaderTransactionalContentHashMd5), HashAlgorithm::Md5); } if (response.GetHeaders().find(Details::HeaderRequestIsServerEncrypted) @@ -6870,7 +6872,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { response.GetHeaders().at(Details::HeaderLastModified), Core::DateTime::DateFormat::Rfc1123); result.TransactionalContentHash = Storage::Details::FromBase64String( - response.GetHeaders().at(Details::HeaderTransactionalContentHash), + response.GetHeaders().at(Details::HeaderTransactionalContentHashCrc64), HashAlgorithm::Crc64); result.IsServerEncrypted = response.GetHeaders().at(Details::HeaderRequestIsServerEncrypted) == "true"; diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_sas_builder.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_sas_builder.hpp index 8e3356810..e74c44b6d 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_sas_builder.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_sas_builder.hpp @@ -135,15 +135,16 @@ namespace Azure { namespace Storage { namespace Sas { /** * @brief Optionally specify the time at which the shared access signature becomes - * valid. + * valid. This timestamp will be truncated to second. */ - Azure::Core::Nullable StartsOn; + Azure::Core::Nullable StartsOn; /** * @brief The time at which the shared access signature becomes invalid. This field must - * be omitted if it has been specified in an associated stored access policy. + * be omitted if it has been specified in an associated stored access policy. This timestamp + * will be truncated to second. */ - std::string ExpiresOn; + Azure::Core::DateTime ExpiresOn; /** * @brief Specifies an IP address or a range of IP addresses from which to accept diff --git a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp index 60f5eb7e5..407325bf9 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp @@ -84,11 +84,17 @@ namespace Azure { namespace Storage { namespace Sas { std::string protocol = Details::SasProtocolToString(Protocol); std::string resource = ShareSasResourceToString(Resource); - std::string stringToSign = Permissions + "\n" + (StartsOn.HasValue() ? StartsOn.GetValue() : "") - + "\n" + ExpiresOn + "\n" + canonicalName + "\n" + Identifier + "\n" - + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" - + Storage::Details::DefaultSasVersion + "\n" + CacheControl + "\n" + ContentDisposition - + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; + std::string startsOnStr = StartsOn.HasValue() + ? StartsOn.GetValue().GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + std::string expiresOnStr = Identifier.empty() + ? ExpiresOn.GetRfc3339String(Azure::Core::DateTime::TimeFractionFormat::Truncate) + : ""; + + std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + + canonicalName + "\n" + Identifier + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n" + CacheControl + "\n" + + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; std::string signature = Base64Encode(Storage::Details::HmacSha256( std::vector(stringToSign.begin(), stringToSign.end()), @@ -98,14 +104,13 @@ namespace Azure { namespace Storage { namespace Sas { builder.AppendQueryParameter( "sv", Storage::Details::UrlEncodeQueryParameter(Storage::Details::DefaultSasVersion)); builder.AppendQueryParameter("spr", Storage::Details::UrlEncodeQueryParameter(protocol)); - if (StartsOn.HasValue()) + if (!startsOnStr.empty()) { - builder.AppendQueryParameter( - "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); + builder.AppendQueryParameter("st", Storage::Details::UrlEncodeQueryParameter(startsOnStr)); } - if (!ExpiresOn.empty()) + if (!expiresOnStr.empty()) { - builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(expiresOnStr)); } if (IPRange.HasValue()) { diff --git a/sdk/storage/azure-storage-files-shares/test/share_sas_test.cpp b/sdk/storage/azure-storage-files-shares/test/share_sas_test.cpp index ad058302b..d37f9debf 100644 --- a/sdk/storage/azure-storage-files-shares/test/share_sas_test.cpp +++ b/sdk/storage/azure-storage-files-shares/test/share_sas_test.cpp @@ -9,12 +9,15 @@ namespace Azure { namespace Storage { namespace Test { TEST_F(FileShareClientTest, FileSasTest) { + auto sasStartsOn = Azure::Core::DateTime::Now() - std::chrono::minutes(5); + auto sasExpiredOn = Azure::Core::DateTime::Now() - std::chrono::minutes(1); + auto sasExpiresOn = Azure::Core::DateTime::Now() + std::chrono::minutes(60); + std::string fileName = RandomString(); Sas::ShareSasBuilder fileSasBuilder; fileSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; - fileSasBuilder.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - fileSasBuilder.ExpiresOn - = ToIso8601(std::chrono::system_clock::now() + std::chrono::minutes(60)); + fileSasBuilder.StartsOn = sasStartsOn; + fileSasBuilder.ExpiresOn = sasExpiresOn; fileSasBuilder.ShareName = m_shareName; fileSasBuilder.FilePath = fileName; fileSasBuilder.Resource = Sas::ShareSasResource::File; @@ -137,8 +140,8 @@ namespace Azure { namespace Storage { namespace Test { // Expires { Sas::ShareSasBuilder builder2 = fileSasBuilder; - builder2.StartsOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(5)); - builder2.ExpiresOn = ToIso8601(std::chrono::system_clock::now() - std::chrono::minutes(1)); + builder2.StartsOn = sasStartsOn; + builder2.ExpiresOn = sasExpiredOn; auto sasToken = builder2.GenerateSasToken(*keyCredential); EXPECT_THROW(verifyFileRead(sasToken), StorageException); } @@ -168,14 +171,14 @@ namespace Azure { namespace Storage { namespace Test { { Files::Shares::Models::SignedIdentifier identifier; identifier.Id = RandomString(64); - identifier.Policy.StartsOn = Core::DateTime::Now() - std::chrono::minutes(5); - identifier.Policy.ExpiresOn = Core::DateTime::Now() + std::chrono::minutes(60); + identifier.Policy.StartsOn = sasStartsOn; + identifier.Policy.ExpiresOn = sasExpiresOn; identifier.Policy.Permission = "r"; m_shareClient->SetAccessPolicy({identifier}); Sas::ShareSasBuilder builder2 = fileSasBuilder; builder2.StartsOn.Reset(); - builder2.ExpiresOn.clear(); + builder2.ExpiresOn = Azure::Core::DateTime(); builder2.SetPermissions(static_cast(0)); builder2.Identifier = identifier.Id;