Kit.Core/LibExternal/Minio/DataModel/Args/CopyObjectRequestArgs.cs

190 lines
8.0 KiB
C#

/*
* MinIO .NET Library for Amazon S3 Compatible Cloud Storage, (C) 2020, 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Minio.DataModel.ObjectLock;
using Minio.DataModel.Result;
using Minio.Helper;
namespace Minio.DataModel.Args;
internal class CopyObjectRequestArgs : ObjectWriteArgs<CopyObjectRequestArgs>
{
internal CopyObjectRequestArgs()
{
RequestMethod = HttpMethod.Put;
Headers = new Dictionary<string, string>(StringComparer.Ordinal);
CopyOperationObjectType = typeof(CopyObjectResult);
}
internal CopySourceObjectArgs SourceObject { get; set; }
internal ObjectStat SourceObjectInfo { get; set; }
internal Type CopyOperationObjectType { get; set; }
internal bool ReplaceTagsDirective { get; set; }
internal bool ReplaceMetadataDirective { get; set; }
internal string StorageClass { get; set; }
internal Dictionary<string, string> QueryMap { get; set; }
internal CopyConditions CopyCondition { get; set; }
internal ObjectRetentionMode ObjectLockRetentionMode { get; set; }
internal DateTime RetentionUntilDate { get; set; }
internal bool ObjectLockSet { get; set; }
internal CopyObjectRequestArgs WithQueryMap(IDictionary<string, string> queryMap)
{
QueryMap = new Dictionary<string, string>(queryMap, StringComparer.Ordinal);
return this;
}
internal CopyObjectRequestArgs WithPartCondition(CopyConditions partCondition)
{
CopyCondition = partCondition.Clone();
Headers ??= new Dictionary<string, string>(StringComparer.Ordinal);
Headers["x-amz-copy-source-range"] = "bytes=" + partCondition.byteRangeStart + "-" + partCondition.byteRangeEnd;
return this;
}
internal CopyObjectRequestArgs WithReplaceMetadataDirective(bool replace)
{
ReplaceMetadataDirective = replace;
return this;
}
internal CopyObjectRequestArgs WithReplaceTagsDirective(bool replace)
{
ReplaceTagsDirective = replace;
return this;
}
public CopyObjectRequestArgs WithCopyObjectSource(CopySourceObjectArgs cs)
{
if (cs is null)
throw new InvalidOperationException("The copy source object needed for copy operation is not initialized.");
SourceObject ??= new CopySourceObjectArgs();
SourceObject.RequestMethod = HttpMethod.Put;
SourceObject.BucketName = cs.BucketName;
SourceObject.ObjectName = cs.ObjectName;
SourceObject.VersionId = cs.VersionId;
SourceObject.SSE = cs.SSE;
SourceObject.Headers = new Dictionary<string, string>(cs.Headers, StringComparer.Ordinal);
SourceObject.MatchETag = cs.MatchETag;
SourceObject.ModifiedSince = cs.ModifiedSince;
SourceObject.NotMatchETag = cs.NotMatchETag;
SourceObject.UnModifiedSince = cs.UnModifiedSince;
SourceObject.CopySourceObjectPath = $"{cs.BucketName}/{Utils.UrlEncode(cs.ObjectName)}";
SourceObject.CopyOperationConditions = cs.CopyOperationConditions?.Clone();
return this;
}
public CopyObjectRequestArgs WithSourceObjectInfo(ObjectStat stat)
{
SourceObjectInfo = stat;
return this;
}
internal override HttpRequestMessageBuilder BuildRequest(HttpRequestMessageBuilder requestMessageBuilder)
{
var sourceObjectPath = SourceObject.BucketName + "/" + Utils.UrlEncode(SourceObject.ObjectName);
if (!string.IsNullOrEmpty(SourceObject.VersionId)) sourceObjectPath += "?versionId=" + SourceObject.VersionId;
// Set the object source
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-copy-source", sourceObjectPath);
if (QueryMap is not null)
foreach (var query in QueryMap)
requestMessageBuilder.AddQueryParameter(query.Key, query.Value);
if (SourceObject.CopyOperationConditions is not null)
foreach (var item in SourceObject.CopyOperationConditions.Conditions)
requestMessageBuilder.AddOrUpdateHeaderParameter(item.Key, item.Value);
if (!string.IsNullOrEmpty(MatchETag))
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-copy-source-if-match", MatchETag);
if (!string.IsNullOrEmpty(NotMatchETag))
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-copy-source-if-none-match", NotMatchETag);
if (ModifiedSince != default)
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-copy-source-if-unmodified-since",
Utils.To8601String(ModifiedSince));
if (UnModifiedSince != default)
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-copy-source-if-modified-since",
Utils.To8601String(UnModifiedSince));
if (ObjectTags?.TaggingSet?.Tag.Count > 0)
{
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-tagging", ObjectTags.GetTagString());
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-tagging-directive",
ReplaceTagsDirective ? "REPLACE" : "COPY");
if (ReplaceMetadataDirective)
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-tagging-directive", "REPLACE");
}
if (ReplaceMetadataDirective)
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-metadata-directive", "REPLACE");
if (!string.IsNullOrEmpty(StorageClass))
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-storage-class", StorageClass);
if (ObjectLockSet)
{
if (!RetentionUntilDate.Equals(default))
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-object-lock-retain-until-date",
Utils.To8601String(RetentionUntilDate));
requestMessageBuilder.AddOrUpdateHeaderParameter("x-amz-object-lock-mode",
ObjectLockRetentionMode == ObjectRetentionMode.GOVERNANCE ? "GOVERNANCE" : "COMPLIANCE");
}
if (!RequestBody.IsEmpty) requestMessageBuilder.SetBody(RequestBody);
return requestMessageBuilder;
}
internal CopyObjectRequestArgs WithCopyOperationObjectType(Type cp)
{
CopyOperationObjectType = cp;
return this;
}
public CopyObjectRequestArgs WithObjectLockMode(ObjectRetentionMode mode)
{
ObjectLockSet = true;
ObjectLockRetentionMode = mode;
return this;
}
public CopyObjectRequestArgs WithObjectLockRetentionDate(DateTime untilDate)
{
ObjectLockSet = true;
RetentionUntilDate = new DateTime(untilDate.Year, untilDate.Month, untilDate.Day,
untilDate.Hour, untilDate.Minute, untilDate.Second, untilDate.Kind);
return this;
}
internal override void Validate()
{
Utils.ValidateBucketName(BucketName); //Object name can be same as that of source.
if (SourceObject is null) throw new InvalidOperationException(nameof(SourceObject) + " has not been assigned.");
Populate();
}
internal void Populate()
{
ObjectName = string.IsNullOrEmpty(ObjectName) ? SourceObject.ObjectName : ObjectName;
// Opting for concat as Headers may have byte range info .etc.
if (!ReplaceMetadataDirective && SourceObjectInfo.MetaData is not null)
Headers = SourceObjectInfo.MetaData.Concat(Headers).GroupBy(item => item.Key, StringComparer.Ordinal)
.ToDictionary(item => item.Key, item => item.First().Value, StringComparer.Ordinal);
else if (ReplaceMetadataDirective) Headers ??= new Dictionary<string, string>(StringComparer.Ordinal);
}
}