ContentHash integration for File/DataLake (#1236)
* Integrate content hash for file/datalake * Changelog update for content hash in file/datalake * Resolve minor build error/warning. * Resolved review comments
This commit is contained in:
parent
9a59445888
commit
d9c65ac445
@ -58,4 +58,22 @@ namespace Azure { namespace Storage {
|
||||
Azure::Core::Nullable<std::string> LeaseId;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specifies HTTP options for conditional requests based on ContentHash.
|
||||
*/
|
||||
struct ContentHashAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Specify this header to perform the operation only if the resource's ContentHash
|
||||
* matches the value specified.
|
||||
*/
|
||||
Azure::Core::Nullable<ContentHash> IfMatchContentHash;
|
||||
|
||||
/**
|
||||
* @brief Specify this header to perform the operation only if the resource's ContentHash does
|
||||
* not match the value specified.
|
||||
*/
|
||||
Azure::Core::Nullable<ContentHash> IfNoneMatchContentHash;
|
||||
};
|
||||
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -21,20 +21,6 @@ namespace Azure { namespace Storage {
|
||||
|
||||
std::string CreateUniqueLeaseId();
|
||||
|
||||
namespace Details {
|
||||
struct CaseInsensitiveComparator
|
||||
{
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const
|
||||
{
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](char c1, char c2) {
|
||||
return Core::Strings::ToLower(c1) < Core::Strings::ToLower(c2);
|
||||
});
|
||||
}
|
||||
};
|
||||
} // namespace Details
|
||||
using Metadata = std::map<std::string, std::string, Details::CaseInsensitiveComparator>;
|
||||
|
||||
/**
|
||||
* @brief The algorithm used for hash.
|
||||
*/
|
||||
@ -64,7 +50,25 @@ namespace Azure { namespace Storage {
|
||||
/**
|
||||
* @brief The algorithm used for hash.
|
||||
*/
|
||||
HashAlgorithm Algorithm;
|
||||
HashAlgorithm Algorithm = HashAlgorithm::Md5;
|
||||
};
|
||||
|
||||
|
||||
namespace Details {
|
||||
struct CaseInsensitiveComparator
|
||||
{
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const
|
||||
{
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](char c1, char c2) {
|
||||
return Core::Strings::ToLower(c1) < Core::Strings::ToLower(c2);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ContentHash FromBase64String(const std::string& base64String, HashAlgorithm algorithm);
|
||||
std::string ToBase64String(const ContentHash& hash);
|
||||
} // namespace Details
|
||||
using Metadata = std::map<std::string, std::string, Details::CaseInsensitiveComparator>;
|
||||
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "azure/storage/common/storage_common.hpp"
|
||||
|
||||
#include "azure/core/uuid.hpp"
|
||||
#include "azure/storage/common/crypt.hpp"
|
||||
|
||||
namespace Azure { namespace Storage {
|
||||
|
||||
@ -13,4 +14,16 @@ namespace Azure { namespace Storage {
|
||||
return uuid.GetUuidString();
|
||||
}
|
||||
|
||||
namespace Details {
|
||||
ContentHash FromBase64String(const std::string& base64String, HashAlgorithm algorithm)
|
||||
{
|
||||
ContentHash hash;
|
||||
hash.Value = Base64Decode(base64String);
|
||||
hash.Algorithm = algorithm;
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string ToBase64String(const ContentHash& hash) { return Base64Encode(hash.Value); }
|
||||
} // namespace Details
|
||||
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
|
||||
- Move DataLake SAS into `Azure::Storage::Sas` namespace.
|
||||
- `EncrytionKeySha256` are changed to binary(`std::vector<uint8_t>`).
|
||||
- Replaced all transactional content MD5/CRC64 with `ContentHash` struct.
|
||||
- `DataLakeHttpHeaders` is renamed to `PathHttpHeaders`, and now contains `ContentHash` for the resource.
|
||||
|
||||
## 12.0.0-beta.5 (2020-11-13)
|
||||
|
||||
|
||||
@ -218,9 +218,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Context Context;
|
||||
|
||||
/**
|
||||
* @brief Specify the transactional md5 for the body, to be validated by the service.
|
||||
* @brief Specify the transactional hash for the body, to be validated by the service.
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> ContentMd5;
|
||||
Azure::Core::Nullable<Storage::ContentHash> TransactionalContentHash;
|
||||
|
||||
/**
|
||||
* @brief Specify the lease access conditions.
|
||||
@ -263,18 +263,17 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Nullable<bool> Close;
|
||||
|
||||
/**
|
||||
* @brief The service stores this value and includes it in the "Content-Md5" response header for
|
||||
* "Read & Get Properties" operations. If this property is not specified on the request,
|
||||
* then the property will be cleared for the file. Subsequent calls to "Read & Get
|
||||
* Properties" will not return this property unless it is explicitly set on that file
|
||||
* again.
|
||||
* @brief The service stores this value and is returned for "Read & Get Properties" operations.
|
||||
* If this property is not specified on the request, then the property will be cleared
|
||||
* for the file. Subsequent calls to "Read & Get Properties" will not return this
|
||||
* property unless it is explicitly set on that file again.
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> ContentMd5;
|
||||
Azure::Core::Nullable<Storage::ContentHash> ContentHash;
|
||||
|
||||
/**
|
||||
* @brief Specify the http headers for this path.
|
||||
*/
|
||||
Models::DataLakeHttpHeaders HttpHeaders;
|
||||
Models::PathHttpHeaders HttpHeaders;
|
||||
|
||||
/**
|
||||
* @brief Specify the access condition for the path.
|
||||
@ -365,7 +364,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
/**
|
||||
* @brief Specify the http headers for this path.
|
||||
*/
|
||||
Models::DataLakeHttpHeaders HttpHeaders;
|
||||
Models::PathHttpHeaders HttpHeaders;
|
||||
|
||||
/**
|
||||
* @brief User-defined metadata to be stored with the path. Note that the string may only
|
||||
@ -687,7 +686,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
/**
|
||||
* @brief The standard HTTP header system properties to set.
|
||||
*/
|
||||
Models::DataLakeHttpHeaders HttpHeaders;
|
||||
Models::PathHttpHeaders HttpHeaders;
|
||||
|
||||
/**
|
||||
* @brief Name-value pairs associated with the blob as metadata.
|
||||
|
||||
@ -131,7 +131,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
* @remark This request is sent to blob endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::SetPathHttpHeadersResult> SetHttpHeaders(
|
||||
Models::DataLakeHttpHeaders httpHeaders,
|
||||
Models::PathHttpHeaders httpHeaders,
|
||||
const SetPathHttpHeadersOptions& options = SetPathHttpHeadersOptions()) const;
|
||||
|
||||
/**
|
||||
|
||||
@ -84,7 +84,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
Azure::Core::Nullable<std::string> LeaseDuration;
|
||||
Azure::Core::Nullable<LeaseStateType> LeaseState;
|
||||
Azure::Core::Nullable<LeaseStatusType> LeaseStatus;
|
||||
DataLakeHttpHeaders HttpHeaders;
|
||||
PathHttpHeaders HttpHeaders;
|
||||
Azure::Core::Nullable<bool> ServerEncrypted;
|
||||
Azure::Core::Nullable<std::vector<uint8_t>> EncryptionKeySha256;
|
||||
Azure::Core::Nullable<bool> AccessTierInferred;
|
||||
@ -136,16 +136,15 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
struct ReadFileResult
|
||||
{
|
||||
std::unique_ptr<Azure::Core::Http::BodyStream> Body;
|
||||
DataLakeHttpHeaders HttpHeaders;
|
||||
PathHttpHeaders HttpHeaders;
|
||||
Azure::Core::Nullable<int64_t> RangeOffset;
|
||||
Azure::Core::Nullable<int64_t> RangeLength;
|
||||
Azure::Core::Nullable<std::string> TransactionalMd5;
|
||||
Azure::Core::Nullable<Storage::ContentHash> TransactionalContentHash;
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
Azure::Core::Nullable<std::string> LeaseDuration;
|
||||
LeaseStateType LeaseState = LeaseStateType::Unknown;
|
||||
LeaseStatusType LeaseStatus = LeaseStatusType::Unknown;
|
||||
Azure::Core::Nullable<std::string> ContentMd5;
|
||||
Storage::Metadata Metadata;
|
||||
std::string CreationTime;
|
||||
Azure::Core::Nullable<std::string> ExpiryTime;
|
||||
@ -165,7 +164,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
int64_t ContentLength = 0;
|
||||
DataLakeHttpHeaders HttpHeaders;
|
||||
PathHttpHeaders HttpHeaders;
|
||||
Storage::Metadata Metadata;
|
||||
Azure::Core::Nullable<bool> ServerEncrypted;
|
||||
Azure::Core::Nullable<std::vector<uint8_t>> EncryptionKeySha256;
|
||||
|
||||
@ -69,7 +69,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
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* HeaderContentCrc64 = "x-ms-content-crc64";
|
||||
constexpr static const char* HeaderTransactionalContentCrc64 = "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";
|
||||
@ -111,13 +111,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
constexpr static const char* HeaderXMsRequestServerEncrypted = "x-ms-request-server-encrypted";
|
||||
} // namespace Details
|
||||
namespace Models {
|
||||
struct DataLakeHttpHeaders
|
||||
struct PathHttpHeaders
|
||||
{
|
||||
std::string CacheControl;
|
||||
std::string ContentDisposition;
|
||||
std::string ContentEncoding;
|
||||
std::string ContentLanguage;
|
||||
std::string ContentType;
|
||||
Storage::ContentHash ContentHash;
|
||||
};
|
||||
// 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"
|
||||
@ -309,10 +310,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
{
|
||||
std::unique_ptr<Azure::Core::Http::BodyStream> BodyStream;
|
||||
std::string AcceptRanges;
|
||||
DataLakeHttpHeaders HttpHeaders;
|
||||
PathHttpHeaders HttpHeaders;
|
||||
int64_t ContentLength = int64_t();
|
||||
Azure::Core::Nullable<std::string> ContentRange;
|
||||
Azure::Core::Nullable<std::string> TransactionalMd5;
|
||||
Azure::Core::Nullable<Storage::ContentHash> TransactionalContentHash;
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
std::string ResourceType;
|
||||
@ -320,16 +321,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Nullable<std::string> LeaseDuration;
|
||||
Models::LeaseStateType LeaseState = Models::LeaseStateType::Unknown;
|
||||
Models::LeaseStatusType LeaseStatus = Models::LeaseStatusType::Unknown;
|
||||
Azure::Core::Nullable<std::string> ContentMd5;
|
||||
};
|
||||
|
||||
struct PathGetPropertiesResult
|
||||
{
|
||||
Azure::Core::Nullable<std::string> AcceptRanges;
|
||||
DataLakeHttpHeaders HttpHeaders;
|
||||
PathHttpHeaders HttpHeaders;
|
||||
int64_t ContentLength = int64_t();
|
||||
Azure::Core::Nullable<std::string> ContentRange;
|
||||
Azure::Core::Nullable<std::string> ContentMd5;
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
Azure::Core::Nullable<std::string> ResourceType;
|
||||
@ -372,8 +371,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
|
||||
struct PathAppendDataResult
|
||||
{
|
||||
Azure::Core::Nullable<std::string> ContentMD5;
|
||||
Azure::Core::Nullable<std::string> ContentCrc64;
|
||||
Azure::Core::Nullable<Storage::ContentHash> TransactionalContentHash;
|
||||
bool IsServerEncrypted = bool();
|
||||
};
|
||||
|
||||
@ -2203,8 +2201,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
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<std::string> ContentMd5; // Specify the transactional md5 for the
|
||||
// body, to be validated by the service.
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
ContentMd5; // Specify the transactional md5 for the body, to be validated by the
|
||||
// service.
|
||||
Azure::Core::Nullable<std::string>
|
||||
LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease
|
||||
// is active and matches this ID.
|
||||
@ -2285,7 +2284,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
}
|
||||
if (flushDataOptions.ContentMd5.HasValue())
|
||||
{
|
||||
request.AddHeader(Details::HeaderContentMd5, flushDataOptions.ContentMd5.GetValue());
|
||||
request.AddHeader(
|
||||
Details::HeaderContentMd5,
|
||||
Storage::Details::ToBase64String(flushDataOptions.ContentMd5.GetValue()));
|
||||
}
|
||||
if (flushDataOptions.LeaseIdOptional.HasValue())
|
||||
{
|
||||
@ -2365,12 +2366,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
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<std::string>
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
TransactionalContentMd5; // Specify the transactional md5 for the body, to be
|
||||
// validated by the service.
|
||||
Azure::Core::Nullable<std::string>
|
||||
ContentCrc64; // Specify the transactional crc64 for the body, to be validated by the
|
||||
// service.
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
TransactionalContentCrc64; // Specify the transactional crc64 for the body, to be
|
||||
// validated by the service.
|
||||
Azure::Core::Nullable<std::string>
|
||||
LeaseIdOptional; // If specified, the operation only succeeds if the resource's lease
|
||||
// is active and matches this ID.
|
||||
@ -2417,12 +2418,15 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderTransactionalContentMd5,
|
||||
appendDataOptions.TransactionalContentMd5.GetValue());
|
||||
Storage::Details::ToBase64String(
|
||||
appendDataOptions.TransactionalContentMd5.GetValue()));
|
||||
}
|
||||
if (appendDataOptions.ContentCrc64.HasValue())
|
||||
if (appendDataOptions.TransactionalContentCrc64.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderContentCrc64, appendDataOptions.ContentCrc64.GetValue());
|
||||
Details::HeaderTransactionalContentCrc64,
|
||||
Storage::Details::ToBase64String(
|
||||
appendDataOptions.TransactionalContentCrc64.GetValue()));
|
||||
}
|
||||
if (appendDataOptions.LeaseIdOptional.HasValue())
|
||||
{
|
||||
@ -2628,7 +2632,8 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
if (response.GetHeaders().find(Details::HeaderContentMD5)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.ContentMd5 = response.GetHeaders().at(Details::HeaderContentMD5);
|
||||
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);
|
||||
@ -2691,12 +2696,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
if (response.GetHeaders().find(Details::HeaderContentMD5)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.TransactionalMd5 = response.GetHeaders().at(Details::HeaderContentMD5);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderXMsContentMd5)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.ContentMd5 = response.GetHeaders().at(Details::HeaderXMsContentMd5);
|
||||
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);
|
||||
@ -2774,7 +2781,8 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
if (response.GetHeaders().find(Details::HeaderContentMD5)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.ContentMd5 = response.GetHeaders().at(Details::HeaderContentMD5);
|
||||
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);
|
||||
@ -2982,12 +2990,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
if (response.GetHeaders().find(Details::HeaderContentMD5)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.ContentMD5 = response.GetHeaders().at(Details::HeaderContentMD5);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderContentMD5), HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderXMsContentCrc64)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.ContentCrc64 = response.GetHeaders().at(Details::HeaderXMsContentCrc64);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderXMsContentCrc64), HashAlgorithm::Crc64);
|
||||
}
|
||||
result.IsServerEncrypted
|
||||
= response.GetHeaders().at(Details::HeaderXMsRequestServerEncrypted) == "true";
|
||||
|
||||
@ -42,9 +42,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
return std::make_pair(offset, length);
|
||||
}
|
||||
|
||||
Models::DataLakeHttpHeaders FromBlobHttpHeaders(Blobs::Models::BlobHttpHeaders headers)
|
||||
Models::PathHttpHeaders FromBlobHttpHeaders(Blobs::Models::BlobHttpHeaders headers)
|
||||
{
|
||||
Models::DataLakeHttpHeaders ret;
|
||||
Models::PathHttpHeaders ret;
|
||||
ret.CacheControl = std::move(headers.CacheControl);
|
||||
ret.ContentDisposition = std::move(headers.ContentDisposition);
|
||||
ret.ContentEncoding = std::move(headers.ContentEncoding);
|
||||
@ -53,7 +53,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blobs::Models::BlobHttpHeaders FromDataLakeHttpHeaders(Models::DataLakeHttpHeaders headers)
|
||||
Blobs::Models::BlobHttpHeaders FromPathHttpHeaders(Models::PathHttpHeaders headers)
|
||||
{
|
||||
Blobs::Models::BlobHttpHeaders ret;
|
||||
ret.CacheControl = std::move(headers.CacheControl);
|
||||
@ -215,7 +215,17 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Details::DataLakeRestClient::Path::AppendDataOptions protocolLayerOptions;
|
||||
protocolLayerOptions.Position = offset;
|
||||
protocolLayerOptions.ContentLength = content->Length();
|
||||
protocolLayerOptions.TransactionalContentMd5 = options.ContentMd5;
|
||||
if (options.TransactionalContentHash.HasValue())
|
||||
{
|
||||
if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64)
|
||||
{
|
||||
protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentHash;
|
||||
}
|
||||
}
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
return Details::DataLakeRestClient::Path::AppendData(
|
||||
m_dfsUri, *content, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
@ -230,7 +240,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
protocolLayerOptions.RetainUncommittedData = options.RetainUncommittedData;
|
||||
protocolLayerOptions.Close = options.Close;
|
||||
protocolLayerOptions.ContentLength = 0;
|
||||
protocolLayerOptions.ContentMd5 = options.ContentMd5;
|
||||
if (options.ContentHash.HasValue()
|
||||
&& options.ContentHash.GetValue().Algorithm != HashAlgorithm::Md5)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
protocolLayerOptions.ContentMd5 = options.ContentHash;
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
protocolLayerOptions.CacheControl = options.HttpHeaders.CacheControl;
|
||||
protocolLayerOptions.ContentType = options.HttpHeaders.ContentType;
|
||||
@ -322,10 +337,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
}
|
||||
ret.RangeOffset = RangeOffset;
|
||||
ret.RangeLength = RangeLength;
|
||||
if (result->TransactionalContentHash.HasValue())
|
||||
{
|
||||
ret.TransactionalMd5 = Base64Encode(result->TransactionalContentHash.GetValue().Value);
|
||||
}
|
||||
ret.TransactionalContentHash = std::move(result->TransactionalContentHash);
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
ret.LeaseDuration = std::move(result->LeaseDuration);
|
||||
@ -350,7 +362,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Blobs::UploadBlockBlobFromOptions blobOptions;
|
||||
blobOptions.Context = options.Context;
|
||||
blobOptions.ChunkSize = options.ChunkSize;
|
||||
blobOptions.HttpHeaders = FromDataLakeHttpHeaders(options.HttpHeaders);
|
||||
blobOptions.HttpHeaders = FromPathHttpHeaders(options.HttpHeaders);
|
||||
blobOptions.Metadata = options.Metadata;
|
||||
blobOptions.Concurrency = options.Concurrency;
|
||||
return m_blockBlobClient.UploadFrom(fileName, blobOptions);
|
||||
@ -364,7 +376,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Blobs::UploadBlockBlobFromOptions blobOptions;
|
||||
blobOptions.Context = options.Context;
|
||||
blobOptions.ChunkSize = options.ChunkSize;
|
||||
blobOptions.HttpHeaders = FromDataLakeHttpHeaders(options.HttpHeaders);
|
||||
blobOptions.HttpHeaders = FromPathHttpHeaders(options.HttpHeaders);
|
||||
blobOptions.Metadata = options.Metadata;
|
||||
blobOptions.Concurrency = options.Concurrency;
|
||||
return m_blockBlobClient.UploadFrom(buffer, bufferSize, blobOptions);
|
||||
|
||||
@ -212,7 +212,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::SetPathHttpHeadersResult> PathClient::SetHttpHeaders(
|
||||
Models::DataLakeHttpHeaders httpHeaders,
|
||||
Models::PathHttpHeaders httpHeaders,
|
||||
const SetPathHttpHeadersOptions& options) const
|
||||
{
|
||||
Blobs::SetBlobHttpHeadersOptions blobOptions;
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
namespace Azure { namespace Storage { namespace Files { namespace DataLake { namespace Models {
|
||||
|
||||
bool operator==(const DataLakeHttpHeaders& lhs, const DataLakeHttpHeaders& rhs)
|
||||
bool operator==(const PathHttpHeaders& lhs, const PathHttpHeaders& rhs)
|
||||
{
|
||||
return lhs.ContentType == rhs.ContentType && lhs.ContentEncoding == rhs.ContentEncoding
|
||||
&& lhs.ContentLanguage == rhs.ContentLanguage && lhs.CacheControl == rhs.CacheControl
|
||||
|
||||
@ -78,11 +78,11 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
return result;
|
||||
}
|
||||
|
||||
Files::DataLake::Models::DataLakeHttpHeaders
|
||||
Files::DataLake::Models::PathHttpHeaders
|
||||
DataLakeFileSystemClientTest::GetInterestingHttpHeaders()
|
||||
{
|
||||
static Files::DataLake::Models::DataLakeHttpHeaders result = []() {
|
||||
Files::DataLake::Models::DataLakeHttpHeaders ret;
|
||||
static Files::DataLake::Models::PathHttpHeaders result = []() {
|
||||
Files::DataLake::Models::PathHttpHeaders ret;
|
||||
ret.CacheControl = std::string("no-cache");
|
||||
ret.ContentDisposition = std::string("attachment");
|
||||
ret.ContentEncoding = std::string("deflate");
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
bool recursive,
|
||||
const std::string& directory = std::string());
|
||||
|
||||
static Files::DataLake::Models::DataLakeHttpHeaders GetInterestingHttpHeaders();
|
||||
static Files::DataLake::Models::PathHttpHeaders GetInterestingHttpHeaders();
|
||||
|
||||
static std::shared_ptr<Files::DataLake::FileSystemClient> m_fileSystemClient;
|
||||
static std::string m_fileSystemName;
|
||||
|
||||
@ -401,7 +401,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
// response headers override
|
||||
{
|
||||
Files::DataLake::Models::DataLakeHttpHeaders headers;
|
||||
Files::DataLake::Models::PathHttpHeaders headers;
|
||||
headers.ContentType = "application/x-binary";
|
||||
headers.ContentLanguage = "en-US";
|
||||
headers.ContentDisposition = "attachment";
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
- ShareClient::BreakLease
|
||||
- ShareClient::RenewLease
|
||||
- Move File SAS into `Azure::Storage::Sas` namespace.
|
||||
- Replaced all transactional content MD5/CRC64 with `ContentHash` struct.
|
||||
- `FileShareHttpHeaders` is renamed to `ShareFileHttpHeaders`, and member `std::string ContentMd5` is changed to `Storage::ContentHash ContentHash`.
|
||||
|
||||
## 12.0.0-beta.5 (2020-11-13)
|
||||
|
||||
|
||||
@ -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* HeaderContentMd5 = "content-md5";
|
||||
constexpr static const char* HeaderContentHash = "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,9 @@ 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* HeaderSourceContentCrc64 = "x-ms-source-content-crc64";
|
||||
constexpr static const char* HeaderSourceIfMatchCrc64 = "x-ms-source-if-match-crc64";
|
||||
constexpr static const char* HeaderSourceIfNoneMatchCrc64 = "x-ms-source-if-none-match-crc64";
|
||||
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* HeaderSourceRange = "x-ms-source-range";
|
||||
constexpr static const char* HeaderErrorCode = "x-ms-error-code";
|
||||
constexpr static const char* HeaderETag = "etag";
|
||||
@ -105,7 +105,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* HeaderTransactionalContentMd5 = "content-md5";
|
||||
constexpr static const char* HeaderTransactionalContentHash = "content-md5";
|
||||
constexpr static const char* HeaderContentEncoding = "content-encoding";
|
||||
constexpr static const char* HeaderCacheControl = "cache-control";
|
||||
constexpr static const char* HeaderContentDisposition = "content-disposition";
|
||||
@ -120,17 +120,16 @@ 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* HeaderXMsContentCrc64 = "x-ms-content-crc64";
|
||||
} // namespace Details
|
||||
namespace Models {
|
||||
struct FileShareHttpHeaders
|
||||
struct ShareFileHttpHeaders
|
||||
{
|
||||
std::string CacheControl;
|
||||
std::string ContentDisposition;
|
||||
std::string ContentEncoding;
|
||||
std::string ContentLanguage;
|
||||
std::string ContentType;
|
||||
std::string ContentMd5;
|
||||
Storage::ContentHash ContentHash;
|
||||
};
|
||||
// Specifies the option to copy file security descriptor from source file or to set it using the
|
||||
// value which is defined by the header value of x-ms-file-permission or
|
||||
@ -650,14 +649,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
int32_t MaxResults = int32_t();
|
||||
Models::FilesAndDirectoriesListSegment Segment;
|
||||
std::string ContinuationToken;
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
};
|
||||
|
||||
struct DirectoryListHandlesResult
|
||||
{
|
||||
std::vector<Models::HandleItem> HandleList;
|
||||
std::string ContinuationToken;
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
};
|
||||
|
||||
struct DirectoryForceCloseHandlesResult
|
||||
@ -687,10 +686,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
std::string LastModified;
|
||||
Storage::Metadata Metadata;
|
||||
int64_t ContentLength = int64_t();
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
Azure::Core::Nullable<std::string> ContentRange;
|
||||
std::string ETag;
|
||||
Azure::Core::Nullable<std::string> TransactionalContentMd5;
|
||||
Azure::Core::Nullable<Storage::ContentHash> TransactionalContentHash;
|
||||
std::string AcceptRanges;
|
||||
Azure::Core::Nullable<std::string> CopyCompletionTime;
|
||||
Azure::Core::Nullable<std::string> CopyStatusDescription;
|
||||
@ -717,7 +716,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Storage::Metadata Metadata;
|
||||
std::string FileType;
|
||||
int64_t ContentLength = int64_t();
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
std::string ETag;
|
||||
Azure::Core::Nullable<std::string> CopyCompletionTime;
|
||||
Azure::Core::Nullable<std::string> CopyStatusDescription;
|
||||
@ -793,7 +792,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
std::string TransactionalContentMd5;
|
||||
Storage::ContentHash TransactionalContentHash;
|
||||
bool IsServerEncrypted = bool();
|
||||
};
|
||||
|
||||
@ -801,7 +800,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
std::string XMsContentCrc64;
|
||||
Storage::ContentHash TransactionalContentHash;
|
||||
bool IsServerEncrypted = bool();
|
||||
};
|
||||
|
||||
@ -830,7 +829,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
std::vector<Models::HandleItem> HandleList;
|
||||
std::string ContinuationToken;
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
};
|
||||
|
||||
struct FileForceCloseHandlesResult
|
||||
@ -1371,9 +1370,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
writer.Write(
|
||||
Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Days"});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
std::to_string(object.Days.GetValue()).data()});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
std::to_string(object.Days.GetValue()).data()});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
}
|
||||
}
|
||||
@ -1394,14 +1394,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
writer.Write(
|
||||
Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "IncludeAPIs"});
|
||||
writer.Write(
|
||||
Storage::Details::XmlNode{Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
object.IncludeApis.GetValue() ? "true" : "false"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
object.IncludeApis.GetValue() ? "true" : "false"});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
}
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"RetentionPolicy"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "RetentionPolicy"});
|
||||
ShareRetentionPolicyToXml(writer, object.RetentionPolicy);
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
}
|
||||
@ -1432,11 +1432,12 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::Text, nullptr, object.ExposedHeaders.data()});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"MaxAgeInSeconds"});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
std::to_string(object.MaxAgeInSeconds).data()});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "MaxAgeInSeconds"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::Text,
|
||||
nullptr,
|
||||
std::to_string(object.MaxAgeInSeconds).data()});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
}
|
||||
@ -1468,8 +1469,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Storage::Details::XmlWriter& writer,
|
||||
const Models::ShareProtocolSettings& object)
|
||||
{
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"ProtocolSettings"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "ProtocolSettings"});
|
||||
SmbSettingsToXml(writer, object.Settings);
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::EndTag});
|
||||
}
|
||||
@ -1478,8 +1479,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Storage::Details::XmlWriter& writer,
|
||||
const Models::StorageServiceProperties& object)
|
||||
{
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"StorageServiceProperties"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "StorageServiceProperties"});
|
||||
writer.Write(
|
||||
Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "HourMetrics"});
|
||||
MetricsToXml(writer, object.HourMetrics);
|
||||
@ -4147,8 +4148,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Storage::Details::XmlWriter& writer,
|
||||
const Models::SignedIdentifier& object)
|
||||
{
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"SignedIdentifier"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "SignedIdentifier"});
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag, "Id"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::Text, nullptr, object.Id.data()});
|
||||
@ -4161,8 +4162,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Storage::Details::XmlWriter& writer,
|
||||
const std::vector<Models::SignedIdentifier>& object)
|
||||
{
|
||||
writer.Write(Storage::Details::XmlNode{Storage::Details::XmlNodeType::StartTag,
|
||||
"SignedIdentifiers"});
|
||||
writer.Write(Storage::Details::XmlNode{
|
||||
Storage::Details::XmlNodeType::StartTag, "SignedIdentifiers"});
|
||||
for (const auto& item : object)
|
||||
{
|
||||
SignedIdentifierToXml(writer, item);
|
||||
@ -5566,7 +5567,12 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Nullable<std::string>
|
||||
FileCacheControl; // Sets the file's cache control. The File service stores this value
|
||||
// but does not use or modify it.
|
||||
Azure::Core::Nullable<std::string> FileContentMd5; // Sets the file's MD5 hash.
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
ContentMd5; // An MD5 hash of the content. This hash is used to verify the integrity
|
||||
// of the data during transport. When the Content-MD5 header is specified,
|
||||
// the File service compares the hash of the content that has arrived with
|
||||
// the header value that was sent. If the two hashes do not match, the
|
||||
// operation will fail with error code 400 (Bad Request).
|
||||
Azure::Core::Nullable<std::string>
|
||||
FileContentDisposition; // Sets the file's Content-Disposition header.
|
||||
Storage::Metadata Metadata; // A name-value pair to associate with a file storage object.
|
||||
@ -5631,9 +5637,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
request.AddHeader(
|
||||
Details::HeaderFileCacheControl, createOptions.FileCacheControl.GetValue());
|
||||
}
|
||||
if (createOptions.FileContentMd5.HasValue())
|
||||
if (createOptions.ContentMd5.HasValue())
|
||||
{
|
||||
request.AddHeader(Details::HeaderContentMd5, createOptions.FileContentMd5.GetValue());
|
||||
request.AddHeader(
|
||||
Details::HeaderContentHash,
|
||||
Storage::Details::ToBase64String(createOptions.ContentMd5.GetValue()));
|
||||
}
|
||||
if (createOptions.FileContentDisposition.HasValue())
|
||||
{
|
||||
@ -5828,7 +5836,12 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Nullable<std::string>
|
||||
FileCacheControl; // Sets the file's cache control. The File service stores this value
|
||||
// but does not use or modify it.
|
||||
Azure::Core::Nullable<std::string> FileContentMd5; // Sets the file's MD5 hash.
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
ContentMd5; // An MD5 hash of the content. This hash is used to verify the integrity
|
||||
// of the data during transport. When the Content-MD5 header is specified,
|
||||
// the File service compares the hash of the content that has arrived with
|
||||
// the header value that was sent. If the two hashes do not match, the
|
||||
// operation will fail with error code 400 (Bad Request).
|
||||
Azure::Core::Nullable<std::string>
|
||||
FileContentDisposition; // Sets the file's Content-Disposition header.
|
||||
Azure::Core::Nullable<std::string>
|
||||
@ -5898,10 +5911,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
request.AddHeader(
|
||||
Details::HeaderFileCacheControl, setHttpHeadersOptions.FileCacheControl.GetValue());
|
||||
}
|
||||
if (setHttpHeadersOptions.FileContentMd5.HasValue())
|
||||
if (setHttpHeadersOptions.ContentMd5.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderContentMd5, setHttpHeadersOptions.FileContentMd5.GetValue());
|
||||
Details::HeaderContentHash,
|
||||
Storage::Details::ToBase64String(setHttpHeadersOptions.ContentMd5.GetValue()));
|
||||
}
|
||||
if (setHttpHeadersOptions.FileContentDisposition.HasValue())
|
||||
{
|
||||
@ -6213,7 +6227,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
= int64_t(); // Specifies the number of bytes being transmitted in the request body.
|
||||
// When the x-ms-write header is set to clear, the value of this header
|
||||
// must be set to zero.
|
||||
Azure::Core::Nullable<std::string>
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
ContentMd5; // An MD5 hash of the content. This hash is used to verify the integrity
|
||||
// of the data during transport. When the Content-MD5 header is specified,
|
||||
// the File service compares the hash of the content that has arrived with
|
||||
@ -6251,7 +6265,9 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Details::HeaderContentLength, std::to_string(uploadRangeOptions.ContentLength));
|
||||
if (uploadRangeOptions.ContentMd5.HasValue())
|
||||
{
|
||||
request.AddHeader(Details::HeaderContentMd5, uploadRangeOptions.ContentMd5.GetValue());
|
||||
request.AddHeader(
|
||||
Details::HeaderContentHash,
|
||||
Storage::Details::ToBase64String(uploadRangeOptions.ContentMd5.GetValue()));
|
||||
}
|
||||
request.AddHeader(Details::HeaderVersion, uploadRangeOptions.ApiVersionParameter);
|
||||
if (uploadRangeOptions.LeaseIdOptional.HasValue())
|
||||
@ -6289,13 +6305,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
= int64_t(); // Specifies the number of bytes being transmitted in the request body.
|
||||
// When the x-ms-write header is set to clear, the value of this header
|
||||
// must be set to zero.
|
||||
Azure::Core::Nullable<std::string>
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
SourceContentCrc64; // Specify the crc64 calculated for the range of bytes that must
|
||||
// be read from the copy source.
|
||||
Azure::Core::Nullable<std::string>
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
SourceIfMatchCrc64; // Specify the crc64 value to operate only on range with a
|
||||
// matching crc64 checksum.
|
||||
Azure::Core::Nullable<std::string>
|
||||
Azure::Core::Nullable<Storage::ContentHash>
|
||||
SourceIfNoneMatchCrc64; // Specify the crc64 value to operate only on range without a
|
||||
// matching crc64 checksum.
|
||||
std::string ApiVersionParameter
|
||||
@ -6338,20 +6354,23 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
if (uploadRangeFromUrlOptions.SourceContentCrc64.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderSourceContentCrc64,
|
||||
uploadRangeFromUrlOptions.SourceContentCrc64.GetValue());
|
||||
Details::HeaderSourceContentHash,
|
||||
Storage::Details::ToBase64String(
|
||||
uploadRangeFromUrlOptions.SourceContentCrc64.GetValue()));
|
||||
}
|
||||
if (uploadRangeFromUrlOptions.SourceIfMatchCrc64.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderSourceIfMatchCrc64,
|
||||
uploadRangeFromUrlOptions.SourceIfMatchCrc64.GetValue());
|
||||
Details::HeaderSourceIfMatchHash,
|
||||
Storage::Details::ToBase64String(
|
||||
uploadRangeFromUrlOptions.SourceIfMatchCrc64.GetValue()));
|
||||
}
|
||||
if (uploadRangeFromUrlOptions.SourceIfNoneMatchCrc64.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
Details::HeaderSourceIfNoneMatchCrc64,
|
||||
uploadRangeFromUrlOptions.SourceIfNoneMatchCrc64.GetValue());
|
||||
Details::HeaderSourceIfNoneMatchHash,
|
||||
Storage::Details::ToBase64String(
|
||||
uploadRangeFromUrlOptions.SourceIfNoneMatchCrc64.GetValue()));
|
||||
}
|
||||
request.AddHeader(Details::HeaderVersion, uploadRangeFromUrlOptions.ApiVersionParameter);
|
||||
if (uploadRangeFromUrlOptions.LeaseIdOptional.HasValue())
|
||||
@ -6794,11 +6813,12 @@ 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::HeaderTransactionalContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderTransactionalContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.TransactionalContentMd5
|
||||
= response.GetHeaders().at(Details::HeaderTransactionalContentMd5);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderTransactionalContentHash),
|
||||
HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderContentEncoding)
|
||||
!= response.GetHeaders().end())
|
||||
@ -6857,10 +6877,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
result.CopyStatus
|
||||
= CopyStatusTypeFromString(response.GetHeaders().at(Details::HeaderCopyStatus));
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.HttpHeaders.ContentMd5 = response.GetHeaders().at(Details::HeaderContentMd5);
|
||||
result.HttpHeaders.ContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderContentHash), HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderIsServerEncrypted)
|
||||
!= response.GetHeaders().end())
|
||||
@ -6919,11 +6940,12 @@ 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::HeaderTransactionalContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderTransactionalContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.TransactionalContentMd5
|
||||
= response.GetHeaders().at(Details::HeaderTransactionalContentMd5);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderTransactionalContentHash),
|
||||
HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderContentEncoding)
|
||||
!= response.GetHeaders().end())
|
||||
@ -6982,10 +7004,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
result.CopyStatus
|
||||
= CopyStatusTypeFromString(response.GetHeaders().at(Details::HeaderCopyStatus));
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.HttpHeaders.ContentMd5 = response.GetHeaders().at(Details::HeaderContentMd5);
|
||||
result.HttpHeaders.ContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderContentHash), HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderIsServerEncrypted)
|
||||
!= response.GetHeaders().end())
|
||||
@ -7055,11 +7078,12 @@ 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::HeaderTransactionalContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderTransactionalContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.HttpHeaders.ContentMd5
|
||||
= response.GetHeaders().at(Details::HeaderTransactionalContentMd5);
|
||||
result.HttpHeaders.ContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderTransactionalContentHash),
|
||||
HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderContentEncoding)
|
||||
!= response.GetHeaders().end())
|
||||
@ -7330,11 +7354,12 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Models::FileUploadRangeResult result;
|
||||
result.ETag = response.GetHeaders().at(Details::HeaderETag);
|
||||
result.LastModified = response.GetHeaders().at(Details::HeaderLastModified);
|
||||
if (response.GetHeaders().find(Details::HeaderTransactionalContentMd5)
|
||||
if (response.GetHeaders().find(Details::HeaderTransactionalContentHash)
|
||||
!= response.GetHeaders().end())
|
||||
{
|
||||
result.TransactionalContentMd5
|
||||
= response.GetHeaders().at(Details::HeaderTransactionalContentMd5);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderTransactionalContentHash),
|
||||
HashAlgorithm::Md5);
|
||||
}
|
||||
if (response.GetHeaders().find(Details::HeaderRequestIsServerEncrypted)
|
||||
!= response.GetHeaders().end())
|
||||
@ -7364,7 +7389,9 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Models::FileUploadRangeFromUrlResult result;
|
||||
result.ETag = response.GetHeaders().at(Details::HeaderETag);
|
||||
result.LastModified = response.GetHeaders().at(Details::HeaderLastModified);
|
||||
result.XMsContentCrc64 = response.GetHeaders().at(Details::HeaderXMsContentCrc64);
|
||||
result.TransactionalContentHash = Storage::Details::FromBase64String(
|
||||
response.GetHeaders().at(Details::HeaderTransactionalContentHash),
|
||||
HashAlgorithm::Crc64);
|
||||
result.IsServerEncrypted
|
||||
= response.GetHeaders().at(Details::HeaderRequestIsServerEncrypted) == "true";
|
||||
return Azure::Core::Response<Models::FileUploadRangeFromUrlResult>(
|
||||
|
||||
@ -207,7 +207,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
* the file returned from the server.
|
||||
*/
|
||||
Azure::Core::Response<Models::SetFilePropertiesResult> SetProperties(
|
||||
Models::FileShareHttpHeaders httpHeaders,
|
||||
Models::ShareFileHttpHeaders httpHeaders,
|
||||
Models::FileShareSmbProperties smbProperties,
|
||||
const SetFilePropertiesOptions& options = SetFilePropertiesOptions()) const;
|
||||
|
||||
|
||||
@ -440,7 +440,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
/**
|
||||
* @brief Specifies the HttpHeaders of the file.
|
||||
*/
|
||||
Models::FileShareHttpHeaders HttpHeaders;
|
||||
Models::ShareFileHttpHeaders HttpHeaders;
|
||||
|
||||
/**
|
||||
* @brief A name-value pair to associate with a file storage object.
|
||||
@ -616,11 +616,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
|
||||
/**
|
||||
* @brief An MD5 hash of the content. This hash is used to verify the integrity of the data
|
||||
* during transport. When the ContentMD5 parameter is specified, the File service compares the
|
||||
* hash of the content that has arrived with the header value that was sent. If the two hashes
|
||||
* do not match, the operation will fail with error code 400 (Bad Request).
|
||||
* during transport. When the TransactionalContentHash parameter is specified, the File service
|
||||
* compares the hash of the content that has arrived with the header value that was sent. If the
|
||||
* two hashes do not match, the operation will fail with error code 400 (Bad Request).
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> TransactionalMd5;
|
||||
Azure::Core::Nullable<ContentHash> TransactionalContentHash;
|
||||
|
||||
/**
|
||||
* @brief The operation will only succeed if the access condition is met.
|
||||
@ -662,20 +662,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
* @brief Specify the crc64 calculated for the range of bytes that must be read from the copy
|
||||
* source.
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> SourceContentCrc64;
|
||||
Azure::Core::Nullable<ContentHash> SourceContentHash;
|
||||
|
||||
/**
|
||||
* @brief Specify the crc64 value to operate only on range with a matching crc64 checksum.
|
||||
* @brief Specify the access condition for the source. Only ContentHash with Crc64 is supported.
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> SourceIfMatchCrc64;
|
||||
ContentHashAccessConditions SourceAccessCondition;
|
||||
|
||||
/**
|
||||
* @brief Specify the crc64 value to operate only on range without a matching crc64 checksum.
|
||||
*/
|
||||
Azure::Core::Nullable<std::string> SourceIfNoneMatchCrc64;
|
||||
|
||||
/**
|
||||
* @brief The operation will only succeed if the access condition is met.
|
||||
* @brief The operation will only succeed if the lease access condition is met.
|
||||
*/
|
||||
LeaseAccessConditions AccessConditions;
|
||||
};
|
||||
@ -853,7 +848,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
/**
|
||||
* @brief The standard HTTP header system properties to set.
|
||||
*/
|
||||
Models::FileShareHttpHeaders HttpHeaders;
|
||||
Models::ShareFileHttpHeaders HttpHeaders;
|
||||
|
||||
/**
|
||||
* @brief Name-value pairs associated with the file as metadata.
|
||||
|
||||
@ -116,7 +116,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { names
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
int64_t ContentLength = 0;
|
||||
FileShareHttpHeaders HttpHeaders;
|
||||
ShareFileHttpHeaders HttpHeaders;
|
||||
Storage::Metadata Metadata;
|
||||
Azure::Core::Nullable<bool> IsServerEncrypted;
|
||||
};
|
||||
|
||||
@ -171,9 +171,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.FileContentDisposition = options.HttpHeaders.ContentDisposition;
|
||||
}
|
||||
if (!options.HttpHeaders.ContentMd5.empty())
|
||||
if (!options.HttpHeaders.ContentHash.Value.empty())
|
||||
{
|
||||
protocolLayerOptions.FileContentMd5 = options.HttpHeaders.ContentMd5;
|
||||
if (options.HttpHeaders.ContentHash.Algorithm != HashAlgorithm::Md5)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
protocolLayerOptions.ContentMd5 = options.HttpHeaders.ContentHash;
|
||||
}
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
return Details::ShareRestClient::File::Create(
|
||||
@ -327,7 +331,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::SetFilePropertiesResult> ShareFileClient::SetProperties(
|
||||
Models::FileShareHttpHeaders httpHeaders,
|
||||
Models::ShareFileHttpHeaders httpHeaders,
|
||||
Models::FileShareSmbProperties smbProperties,
|
||||
const SetFilePropertiesOptions& options) const
|
||||
{
|
||||
@ -410,7 +414,12 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
protocolLayerOptions.ContentLength = content->Length();
|
||||
protocolLayerOptions.XMsRange = std::string("bytes=") + std::to_string(offset)
|
||||
+ std::string("-") + std::to_string(offset + content->Length() - 1);
|
||||
protocolLayerOptions.ContentMd5 = options.TransactionalMd5;
|
||||
if (options.TransactionalContentHash.HasValue()
|
||||
&& options.TransactionalContentHash.GetValue().Algorithm != HashAlgorithm::Md5)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
protocolLayerOptions.ContentMd5 = options.TransactionalContentHash;
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
return Details::ShareRestClient::File::UploadRange(
|
||||
m_shareFileUri, *content, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
@ -853,9 +862,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.FileContentDisposition = options.HttpHeaders.ContentDisposition;
|
||||
}
|
||||
if (!options.HttpHeaders.ContentMd5.empty())
|
||||
if (!options.HttpHeaders.ContentHash.Value.empty())
|
||||
{
|
||||
protocolLayerOptions.FileContentMd5 = options.HttpHeaders.ContentMd5;
|
||||
if (options.HttpHeaders.ContentHash.Algorithm != HashAlgorithm::Md5)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
protocolLayerOptions.ContentMd5 = options.HttpHeaders.ContentHash;
|
||||
}
|
||||
protocolLayerOptions.Metadata = options.Metadata;
|
||||
auto createResult = Details::ShareRestClient::File::Create(
|
||||
@ -946,9 +959,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.FileContentDisposition = options.HttpHeaders.ContentDisposition;
|
||||
}
|
||||
if (!options.HttpHeaders.ContentMd5.empty())
|
||||
if (!options.HttpHeaders.ContentHash.Value.empty())
|
||||
{
|
||||
protocolLayerOptions.FileContentMd5 = options.HttpHeaders.ContentMd5;
|
||||
if (options.HttpHeaders.ContentHash.Algorithm != HashAlgorithm::Md5)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
protocolLayerOptions.ContentMd5 = options.HttpHeaders.ContentHash;
|
||||
}
|
||||
protocolLayerOptions.Metadata = options.Metadata;
|
||||
auto createResult = Details::ShareRestClient::File::Create(
|
||||
|
||||
@ -39,10 +39,10 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
m_shareClient->Delete(deleteOptions);
|
||||
}
|
||||
|
||||
Files::Shares::Models::FileShareHttpHeaders FileShareClientTest::GetInterestingHttpHeaders()
|
||||
Files::Shares::Models::ShareFileHttpHeaders FileShareClientTest::GetInterestingHttpHeaders()
|
||||
{
|
||||
static Files::Shares::Models::FileShareHttpHeaders result = []() {
|
||||
Files::Shares::Models::FileShareHttpHeaders ret;
|
||||
static Files::Shares::Models::ShareFileHttpHeaders result = []() {
|
||||
Files::Shares::Models::ShareFileHttpHeaders ret;
|
||||
ret.CacheControl = std::string("no-cache");
|
||||
ret.ContentDisposition = std::string("attachment");
|
||||
ret.ContentEncoding = std::string("deflate");
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
static void SetUpTestSuite();
|
||||
static void TearDownTestSuite();
|
||||
|
||||
static Files::Shares::Models::FileShareHttpHeaders GetInterestingHttpHeaders();
|
||||
static Files::Shares::Models::ShareFileHttpHeaders GetInterestingHttpHeaders();
|
||||
|
||||
static std::shared_ptr<Files::Shares::ShareClient> m_shareClient;
|
||||
static std::string m_shareName;
|
||||
|
||||
@ -26,11 +26,11 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
void FileShareDirectoryClientTest::TearDownTestSuite() { m_shareClient->Delete(); }
|
||||
|
||||
Files::Shares::Models::FileShareHttpHeaders
|
||||
Files::Shares::Models::ShareFileHttpHeaders
|
||||
FileShareDirectoryClientTest::GetInterestingHttpHeaders()
|
||||
{
|
||||
static Files::Shares::Models::FileShareHttpHeaders result = []() {
|
||||
Files::Shares::Models::FileShareHttpHeaders ret;
|
||||
static Files::Shares::Models::ShareFileHttpHeaders result = []() {
|
||||
Files::Shares::Models::ShareFileHttpHeaders ret;
|
||||
ret.CacheControl = std::string("no-cache");
|
||||
ret.ContentDisposition = std::string("attachment");
|
||||
ret.ContentEncoding = std::string("deflate");
|
||||
|
||||
@ -19,7 +19,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
const std::string& directoryPath = std::string(),
|
||||
const std::string& prefix = std::string());
|
||||
|
||||
static Files::Shares::Models::FileShareHttpHeaders GetInterestingHttpHeaders();
|
||||
static Files::Shares::Models::ShareFileHttpHeaders GetInterestingHttpHeaders();
|
||||
|
||||
static std::shared_ptr<Files::Shares::ShareDirectoryClient> m_fileShareDirectoryClient;
|
||||
static std::string m_directoryName;
|
||||
|
||||
@ -560,14 +560,18 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
{
|
||||
// MD5 works.
|
||||
memBodyStream.Rewind();
|
||||
auto md5String = Base64Encode(Md5::Hash(rangeContent.data(), rangeContent.size()));
|
||||
auto invalidMd5String = Base64Encode(Md5::Hash(std::string("This is garbage.")));
|
||||
auto md5 = Md5::Hash(rangeContent.data(), rangeContent.size());
|
||||
auto invalidMd5 = Md5::Hash(std::string("This is garbage."));
|
||||
auto fileClient = m_shareClient->GetShareFileClient(LowercaseRandomString(10));
|
||||
Files::Shares::UploadFileRangeOptions uploadOptions;
|
||||
fileClient.Create(static_cast<int64_t>(numOfChunks) * rangeSize);
|
||||
uploadOptions.TransactionalMd5 = md5String;
|
||||
ContentHash hash;
|
||||
hash.Value = md5;
|
||||
hash.Algorithm = HashAlgorithm::Md5;
|
||||
uploadOptions.TransactionalContentHash = hash;
|
||||
EXPECT_NO_THROW(fileClient.UploadRange(0, &memBodyStream, uploadOptions));
|
||||
uploadOptions.TransactionalMd5 = invalidMd5String;
|
||||
hash.Value = invalidMd5;
|
||||
uploadOptions.TransactionalContentHash = hash;
|
||||
memBodyStream.Rewind();
|
||||
EXPECT_THROW(fileClient.UploadRange(0, &memBodyStream, uploadOptions), StorageException);
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
// response headers override
|
||||
{
|
||||
Files::Shares::Models::FileShareHttpHeaders headers;
|
||||
Files::Shares::Models::ShareFileHttpHeaders headers;
|
||||
headers.ContentType = "application/x-binary";
|
||||
headers.ContentLanguage = "en-US";
|
||||
headers.ContentDisposition = "attachment";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user