azure-sdk-for-cpp/sdk/storage/src/blobs/blob_client.cpp
JinmingHu 4366159c50
Add more APIs in storage sdk (#169)
* Add xml serializer/deserializer

* Add blob service client, add undelete, set access tier, start copy, abort copy, create snapshot, stage block from uri

* add support for conditional headers

* support range download

* Change the helper functions order to alphabetical

so that we always get the same result in different environemnts.

* use c++ casting

* Add support for append blob and page blob

* remove redundant ; added by auto-generator

* Remove BlobType in BlockBlob::Upload

* Rename blob_client_options.hpp->blob_options.hpp

* Remove API version in request options
2020-06-15 17:31:36 +08:00

289 lines
11 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "blobs/blob_client.hpp"
#include "common/common_headers_request_policy.hpp"
#include "common/shared_key_policy.hpp"
#include "common/storage_common.hpp"
#include "http/curl/curl.hpp"
namespace Azure { namespace Storage { namespace Blobs {
BlobClient BlobClient::CreateFromConnectionString(
const std::string& connectionString,
const std::string& containerName,
const std::string& blobName,
const BlobClientOptions& options)
{
auto parsedConnectionString = ParseConnectionString(connectionString);
std::string accountName;
std::string accountKey;
std::string blobEndpoint;
std::string EndpointSuffix;
std::string defaultEndpointsProtocol = ".core.windows.net";
auto ite = parsedConnectionString.find("AccountName");
if (ite != parsedConnectionString.end())
{
accountName = ite->second;
}
ite = parsedConnectionString.find("AccountKey");
if (ite != parsedConnectionString.end())
{
accountKey = ite->second;
}
ite = parsedConnectionString.find("BlobEndpoint");
if (ite != parsedConnectionString.end())
{
blobEndpoint = ite->second;
}
ite = parsedConnectionString.find("EndpointSuffix");
if (ite != parsedConnectionString.end())
{
EndpointSuffix = ite->second;
}
ite = parsedConnectionString.find("DefaultEndpointsProtocol");
if (ite != parsedConnectionString.end())
{
defaultEndpointsProtocol = ite->second;
}
UrlBuilder builder;
builder.SetScheme(defaultEndpointsProtocol);
if (!blobEndpoint.empty())
{
builder = UrlBuilder(blobEndpoint);
}
else if (!accountName.empty())
{
builder.SetHost(accountName + ".blob." + EndpointSuffix);
}
else
{
throw std::runtime_error("invalid connection string");
}
builder.AppendPath(containerName, true);
builder.AppendPath(blobName, true);
auto credential = std::make_shared<SharedKeyCredential>(accountName, accountKey);
return BlobClient(builder.to_string(), credential, options);
}
BlobClient::BlobClient(
const std::string& blobUri,
std::shared_ptr<SharedKeyCredential> credential,
const BlobClientOptions& options)
: m_blobUrl(blobUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
policies.emplace_back(std::make_unique<SharedKeyPolicy>(credential));
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobClient::BlobClient(
const std::string& blobUri,
std::shared_ptr<TokenCredential> credential,
const BlobClientOptions& options)
: m_blobUrl(blobUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
// not implemented yet
unused(credential);
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobClient::BlobClient(const std::string& blobUri, const BlobClientOptions& options)
: m_blobUrl(blobUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobClient BlobClient::WithSnapshot(const std::string& snapshot) const
{
BlobClient newClient(*this);
if (snapshot.empty())
{
newClient.m_blobUrl.RemoveQuery("snapshot");
}
else
{
newClient.m_blobUrl.AppendQuery("snapshot", snapshot);
}
return newClient;
}
FlattenedDownloadProperties BlobClient::Download(const DownloadBlobOptions& options) const
{
BlobRestClient::Blob::DownloadOptions protocolLayerOptions;
if (options.Offset != std::numeric_limits<decltype(options.Offset)>::max())
{
if (options.Length == 0)
{
protocolLayerOptions.Range
= std::make_pair(options.Offset, std::numeric_limits<decltype(options.Offset)>::max());
}
else
{
protocolLayerOptions.Range
= std::make_pair(options.Offset, options.Offset + options.Length - 1);
}
}
else
{
protocolLayerOptions.Range
= std::make_pair(std::numeric_limits<uint64_t>::max(), uint64_t(0));
}
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::Download(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobProperties BlobClient::GetProperties(const GetBlobPropertiesOptions& options) const
{
BlobRestClient::Blob::GetPropertiesOptions protocolLayerOptions;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::GetProperties(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobInfo BlobClient::SetHttpHeaders(const SetBlobHttpHeadersOptions& options) const
{
BlobRestClient::Blob::SetHttpHeadersOptions protocolLayerOptions;
protocolLayerOptions.ContentType = options.ContentType;
protocolLayerOptions.ContentEncoding = options.ContentEncoding;
protocolLayerOptions.ContentLanguage = options.ContentLanguage;
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.CacheControl = options.CacheControl;
protocolLayerOptions.ContentDisposition = options.ContentDisposition;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::SetHttpHeaders(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobInfo BlobClient::SetMetadata(
std::map<std::string, std::string> metadata,
const SetBlobMetadataOptions& options) const
{
BlobRestClient::Blob::SetMetadataOptions protocolLayerOptions;
protocolLayerOptions.Metadata = std::move(metadata);
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::SetMetadata(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::SetAccessTier(AccessTier Tier, const SetAccessTierOptions& options)
const
{
BlobRestClient::Blob::SetAccessTierOptions protocolLayerOptions;
protocolLayerOptions.Tier = Tier;
protocolLayerOptions.RehydratePriority = options.RehydratePriority;
return BlobRestClient::Blob::SetAccessTier(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobCopyInfo BlobClient::StartCopyFromUri(
const std::string& sourceUri,
const StartCopyFromUriOptions& options) const
{
BlobRestClient::Blob::StartCopyFromUriOptions protocolLayerOptions;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.SourceUri = sourceUri;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.SourceLeaseId = options.SourceLeaseId;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.RehydratePriority = options.RehydratePriority;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceIfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.SourceIfMatch = options.SourceIfMatch;
protocolLayerOptions.SourceIfNoneMatch = options.SourceIfNoneMatch;
return BlobRestClient::Blob::StartCopyFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::AbortCopyFromUri(
const std::string& copyId,
const AbortCopyFromUriOptions& options) const
{
BlobRestClient::Blob::AbortCopyFromUriOptions protocolLayerOptions;
protocolLayerOptions.CopyId = copyId;
protocolLayerOptions.LeaseId = options.LeaseId;
return BlobRestClient::Blob::AbortCopyFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobSnapshotInfo BlobClient::CreateSnapshot(const CreateSnapshotOptions& options) const
{
BlobRestClient::Blob::CreateSnapshotOptions protocolLayerOptions;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::CreateSnapshot(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::Delete(const DeleteBlobOptions& options) const
{
BlobRestClient::Blob::DeleteOptions protocolLayerOptions;
protocolLayerOptions.DeleteSnapshots = options.DeleteSnapshots;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::Delete(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::Undelete(const UndeleteBlobOptions& options) const
{
BlobRestClient::Blob::UndeleteOptions protocolLayerOptions;
return BlobRestClient::Blob::Undelete(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
}}} // namespace Azure::Storage::Blobs