From 6c578d1706f0e08de7b6c541da018df079212677 Mon Sep 17 00:00:00 2001 From: poornas Date: Mon, 6 Feb 2017 14:36:18 -0800 Subject: [PATCH] support virtual hosted-style requests for AWS --- Minio.Api/ApiEndpoints/BucketOperations.cs | 125 +++--------- Minio.Api/ApiEndpoints/ObjectOperations.cs | 103 ++++++---- Minio.Api/ApiEndpoints/RequestHelper.cs | 15 ++ Minio.Api/BucketRegionCache.cs | 12 +- Minio.Api/Helper/utils.cs | 4 + Minio.Api/MinioApi.csproj | 1 + Minio.Api/MinioRestClient.cs | 183 ++++++++++++++++-- Minio.Api/Regions.cs | 64 +++--- Minio.Examples/Cases/BucketExists.cs | 5 +- Minio.Examples/Cases/CopyObject.cs | 13 +- Minio.Examples/Cases/FGetObject.cs | 11 +- Minio.Examples/Cases/FPutObject.cs | 21 +- Minio.Examples/Cases/GetBucketPolicy.cs | 8 +- Minio.Examples/Cases/GetObject.cs | 7 +- Minio.Examples/Cases/ListBuckets.cs | 4 +- Minio.Examples/Cases/ListIncompleteUploads.cs | 20 +- Minio.Examples/Cases/ListObjects.cs | 16 +- Minio.Examples/Cases/MakeBucket.cs | 11 +- Minio.Examples/Cases/PutObject.cs | 35 ++-- Minio.Examples/Cases/RemoveBucket.cs | 6 +- .../Cases/RemoveIncompleteUpload.cs | 14 +- Minio.Examples/Cases/RemoveObject.cs | 11 +- Minio.Examples/Cases/SetBucketPolicy.cs | 13 +- Minio.Examples/Cases/StatObject.cs | 13 +- Minio.Examples/Program.cs | 74 +++---- SimpleTest/Program.cs | 14 +- d5ozndk4.2pt.txt | 31 +++ i2c2nxk1.mwo.txt | 34 ++++ 28 files changed, 542 insertions(+), 326 deletions(-) create mode 100644 Minio.Api/ApiEndpoints/RequestHelper.cs create mode 100644 d5ozndk4.2pt.txt create mode 100644 i2c2nxk1.mwo.txt diff --git a/Minio.Api/ApiEndpoints/BucketOperations.cs b/Minio.Api/ApiEndpoints/BucketOperations.cs index 3c8b8a1e5..fa92bdc84 100644 --- a/Minio.Api/ApiEndpoints/BucketOperations.cs +++ b/Minio.Api/ApiEndpoints/BucketOperations.cs @@ -85,74 +85,7 @@ public async Task MakeBucketAsync(string bucketName, string location = "us return false; } - /// - /// Updates Region cache for given bucket. - /// - /// - internal async Task updateRegionCache(string bucketName) - { - string region = null; - - if (bucketName != null && s3utils.IsAmazonEndPoint(this.client.BaseUrl) && this.client.AccessKey != null - && this.client.SecretKey != null && !BucketRegionCache.Instance.Exists(bucketName)) - { - string location = null; - var path = bucketName + "?location"; - var request = new RestRequest(path, Method.GET); - var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); - - if (HttpStatusCode.OK.Equals(response.StatusCode)) - { - var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content); - var stream = new MemoryStream(contentBytes); - XDocument root = XDocument.Parse(response.Content); - location = root.Root.Value; - - } - if (location == null || location == "") - { - region = "us-east-1"; - } - else - { - // eu-west-1 can be sometimes 'EU'. - if ("EU".Equals(location)) - { - region = "eu-west-1"; - } - else - { - region = location; - } - } - - // Add the new location. - BucketRegionCache.Instance.Add(bucketName, region); - } - return region; - - } - private async Task ModifyTargetURL(RestRequest request, string bucketName) - { - var resource_url = this.client.Endpoint; - - if (s3utils.IsAmazonEndPoint(this.client.BaseUrl)) - { - // ``us-east-1`` is not a valid location constraint according to amazon, so we skip it. - string location = await updateRegionCache(bucketName); - // if (location != "us-east-1") - { - this.client.ModifyAWSEndpointFor(location, bucketName); - resource_url = this.client.MakeTargetURL(location, bucketName); - } - //else - //{ // use default request - // resource_url = ""; - // } - } - return resource_url; - - } + /// /// Returns true if the specified bucketName exists, otherwise returns false. /// @@ -160,18 +93,11 @@ private async Task ModifyTargetURL(RestRequest request, string bucketNam /// true if exists and user has access public async Task BucketExistsAsync(string bucketName) { - //request.Resource = bucketName; - string resource_url = await ModifyTargetURL(null, bucketName); - - RestRequest request; - if (BucketRegionCache.Instance.Region(bucketName) == "us-east-1") - { - request = new RestRequest(bucketName, Method.HEAD); - } - else - { - request = new RestRequest(resource_url, Method.HEAD); - } + + var request = await client.CreateRequest(Method.HEAD, + bucketName, + region: BucketRegionCache.Instance.Region(bucketName)); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); if (response.StatusCode != HttpStatusCode.OK) @@ -199,9 +125,9 @@ public async Task BucketExistsAsync(string bucketName) /// Name of bucket to remove public async Task RemoveBucketAsync(string bucketName) { - var request = new RestRequest(bucketName, Method.DELETE); - await ModifyTargetURL(request, bucketName); - + var request =await client.CreateRequest(Method.DELETE, bucketName, + region: BucketRegionCache.Instance.Region(bucketName), + resourcePath:"/"); var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); @@ -238,7 +164,7 @@ public IObservable ListObjectsAsync(string bucketName, string prefix = nul { marker = result.Item1.NextMarker; } - else + else if (lastItem != null) { marker = lastItem.Key; } @@ -278,9 +204,13 @@ private async Task>> GetObjectListAsync(strin { path += "?" + query; } - var request = new RestRequest(path, Method.GET); - await ModifyTargetURL(request, bucketName); + + var request = await client.CreateRequest(Method.GET, + bucketName, + region: BucketRegionCache.Instance.Region(bucketName), + resourcePath:"?" + query); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); @@ -324,12 +254,17 @@ private async Task GetPolicyAsync(string bucketName) { BucketPolicy policy = null; IRestResponse response = null; + var path =bucketName + "?policy"; var request = new RestRequest(path, Method.GET); request.AddHeader("Content-Type", "application/json"); - await ModifyTargetURL(request, bucketName); + await this.client.ModifyTargetURL(request, bucketName); + request = await client.CreateRequest(Method.GET, bucketName, + region: BucketRegionCache.Instance.Region(bucketName), + contentType:"application/json", + resourcePath:"?policy"); response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); if (response.StatusCode != HttpStatusCode.OK) { @@ -354,7 +289,7 @@ private async Task GetPolicyAsync(string bucketName) /// Bucket name. /// Name of the object prefix /// Returns the PolicyType - public async Task GetPolicyAsync(String bucketName, String objectPrefix = null) + public async Task GetPolicyAsync(string bucketName, string objectPrefix ="") { BucketPolicy policy = await GetPolicyAsync(bucketName); return policy.getPolicy(objectPrefix); @@ -366,15 +301,15 @@ public async Task GetPolicyAsync(String bucketName, String objectPre /// Bucket Name. /// Valid Json policy object /// - private async Task setPolicyAsync(String bucketName, BucketPolicy policy) + private async Task setPolicyAsync(string bucketName, BucketPolicy policy) { - var path = bucketName + "?policy"; - var request = new RestRequest(path, Method.PUT); - request.AddHeader("Content-Type", "application/json"); - await ModifyTargetURL(request, bucketName); - + string policyJson = policy.getJson(); - request.AddParameter("application/json", policyJson, ParameterType.RequestBody); + var request = await client.CreateRequest(Method.PUT, bucketName, + resourcePath:"?policy", + region: BucketRegionCache.Instance.Region(bucketName), + contentType: "application/json", + body:policyJson); IRestResponse response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); } diff --git a/Minio.Api/ApiEndpoints/ObjectOperations.cs b/Minio.Api/ApiEndpoints/ObjectOperations.cs index 4e7657c7f..af53fcff4 100644 --- a/Minio.Api/ApiEndpoints/ObjectOperations.cs +++ b/Minio.Api/ApiEndpoints/ObjectOperations.cs @@ -45,13 +45,16 @@ public partial class ClientApiOperations : IObjectOperations public async Task GetObjectAsync(string bucketName, string objectName, Action cb) { - RestRequest request = new RestRequest(bucketName + "/" + utils.UrlEncode(objectName), Method.GET); + var request = await client.CreateRequest(Method.GET, + bucketName, + objectName: objectName, + region: BucketRegionCache.Instance.Region(bucketName) + ); request.ResponseWriter = cb; var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); if (response.StatusCode != HttpStatusCode.OK) - { - + { this.client.ParseError(response); } @@ -142,7 +145,6 @@ public async Task PutObjectAsync(string bucketName, string objectName, string fi utils.ValidateFile(filePath, contentType); FileInfo fileInfo = new FileInfo(filePath); long size = fileInfo.Length; - using (MemoryStream ms = new MemoryStream()) using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { await PutObjectAsync(bucketName, objectName, file, size, contentType); @@ -256,9 +258,14 @@ public async Task PutObjectAsync(string bucketName, string objectName, Stream da /// private async Task CompleteMultipartUploadAsync(string bucketName, string objectName, string uploadId, Dictionary etags) { - var path = bucketName + "/" + utils.UrlEncode(objectName) + "?uploadId=" + uploadId; - var request = new RestRequest(path, Method.POST); + string resourcePath = "?uploadId=" + uploadId; + var request = await client.CreateRequest(Method.POST, bucketName, + objectName: objectName, + resourcePath:resourcePath, + region: BucketRegionCache.Instance.Region(bucketName) + ); + List parts = new List(); for (int i = 1; i <= etags.Count; i++) @@ -343,14 +350,18 @@ private IObservable ListParts(string bucketName, string objectName, string /// private async Task>> GetListPartsAsync(string bucketName, string objectName, string uploadId, int partNumberMarker) { - var path = bucketName + "/" + utils.UrlEncode(objectName) + "?uploadId=" + uploadId; + var resourcePath = "?uploadId=" + uploadId; if (partNumberMarker > 0) { - path += "&part-number-marker=" + partNumberMarker; + resourcePath += "&part-number-marker=" + partNumberMarker; } - path += "&max-parts=1000"; - var request = new RestRequest(path, Method.GET); - + resourcePath += "&max-parts=1000"; + var request = await client.CreateRequest(Method.GET, bucketName, + objectName: objectName, + resourcePath: resourcePath, + region: BucketRegionCache.Instance.Region(bucketName) + ); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers,request); if (!response.StatusCode.Equals(HttpStatusCode.OK)) { @@ -362,7 +373,7 @@ private async Task>> GetListPartsAsync(string XDocument root = XDocument.Parse(response.Content); - var uploads = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Part") + var uploads = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Part") select new Part() { PartNumber = int.Parse(c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}PartNumber").Value, CultureInfo.CurrentCulture), @@ -377,13 +388,16 @@ private async Task>> GetListPartsAsync(string //starts a multi-part upload request private async Task NewMultipartUploadAsync(string bucketName, string objectName, string contentType) { - var path = bucketName + "/" + utils.UrlEncode(objectName) + "?uploads"; - var request = new RestRequest(path, Method.POST); + var resource = "?uploads"; if (string.IsNullOrWhiteSpace(contentType)) { contentType = "application/octet-stream"; } - request.AddHeader("Content-Type", contentType); + + var request = await client.CreateRequest(Method.POST, bucketName, objectName: objectName, + contentType: contentType, resourcePath: resource, + region: BucketRegionCache.Instance.Region(bucketName) + ); var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers,request); if (!response.StatusCode.Equals(HttpStatusCode.OK)) { @@ -394,22 +408,23 @@ private async Task NewMultipartUploadAsync(string bucketName, string obj InitiateMultipartUploadResult newUpload = (InitiateMultipartUploadResult)(new XmlSerializer(typeof(InitiateMultipartUploadResult)).Deserialize(stream)); return newUpload.UploadId; } + //Actual doer private async Task PutObjectAsync(string bucketName, string objectName, string uploadId, int partNumber, byte[] data, string contentType) { - var path = bucketName + "/" + utils.UrlEncode(objectName); + var resource = ""; if (!string.IsNullOrEmpty(uploadId) && partNumber > 0) { - path += "?uploadId=" + uploadId + "&partNumber=" + partNumber; - } - var request = new RestRequest(path, Method.PUT); - if (string.IsNullOrWhiteSpace(contentType)) - { - contentType = "application/octet-stream"; + resource += "?uploadId=" + uploadId + "&partNumber=" + partNumber; } - - request.AddHeader("Content-Type", contentType); - request.AddParameter(contentType, data, RestSharp.ParameterType.RequestBody); + var request = await client.CreateRequest(Method.PUT, bucketName, + objectName: objectName, + contentType: contentType, + body: data, + resourcePath: resource, + region: BucketRegionCache.Instance.Region(bucketName) + ); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers,request); if (!response.StatusCode.Equals(HttpStatusCode.OK)) { @@ -456,10 +471,11 @@ private async Task>> GetMultipart queries.Add("max-uploads=1000"); string query = string.Join("&", queries); - string path = bucketName; - path += "?" + query; - var request = new RestRequest(path, Method.GET); + var request = await client.CreateRequest(Method.GET, bucketName, + region: BucketRegionCache.Instance.Region(bucketName), + resourcePath:"?" + query); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers,request); if (response.StatusCode != HttpStatusCode.OK) { @@ -487,7 +503,7 @@ private async Task>> GetMultipart /// Lists all incomplete uploads in a given bucket and prefix recursively /// /// Bucket to list all incomplepte uploads from - /// prefix to list all incomplepte uploads + /// prefix to list all incomplete uploads /// option to list incomplete uploads recursively /// A lazily populated list of incomplete uploads public IObservable ListIncompleteUploads(string bucketName, string prefix="", bool recursive=true) @@ -571,8 +587,15 @@ public async Task RemoveIncompleteUploadAsync(string bucketName, string objectNa } private async Task RemoveUploadAsync(string bucketName, string objectName, string uploadId) { - var path = bucketName + "/" + utils.UrlEncode(objectName) + "?uploadId=" + uploadId; - var request = new RestRequest(path, Method.DELETE); + // var resourcePath = "/" + utils.UrlEncode(objectName) + "?uploadId=" + uploadId; + var resourcePath = "?uploadId=" + uploadId; + + var request = await client.CreateRequest(Method.DELETE, bucketName, + objectName: objectName, + region: BucketRegionCache.Instance.Region(bucketName), + resourcePath: resourcePath + ); + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers,request); if (response.StatusCode != HttpStatusCode.NoContent) @@ -588,9 +611,13 @@ private async Task RemoveUploadAsync(string bucketName, string objectName, strin /// public async Task RemoveObjectAsync(string bucketName, string objectName) { - var request = new RestRequest(bucketName + "/" + utils.UrlEncode(objectName), Method.DELETE); - var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); + var request = await client.CreateRequest(Method.DELETE, bucketName, + objectName: objectName, + region: BucketRegionCache.Instance.Region(bucketName) + ); + + var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); if (!response.StatusCode.Equals(HttpStatusCode.NoContent)) { @@ -605,7 +632,10 @@ public async Task RemoveObjectAsync(string bucketName, string objectName) /// Facts about the object public async Task StatObjectAsync(string bucketName, string objectName) { - var request = new RestRequest(bucketName + "/" + utils.UrlEncode(objectName), Method.HEAD); + var request = await client.CreateRequest(Method.HEAD, bucketName, + objectName: objectName, + region: BucketRegionCache.Instance.Region(bucketName) + ); var response = await this.client.ExecuteTaskAsync(this.client.NoErrorHandlers, request); if (response.StatusCode != HttpStatusCode.OK) @@ -711,7 +741,10 @@ public async Task CopyObjectAsync(string bucketName, string ob } var path = destBucketName + "/" + utils.UrlEncode(destObjectName); - var request = new RestRequest(path, Method.PUT); + var request = await client.CreateRequest(Method.PUT, bucketName, + objectName: objectName, + region: BucketRegionCache.Instance.Region(bucketName), resourcePath:path + ); // Set the object source request.AddHeader("x-amz-copy-source", sourceObjectPath); diff --git a/Minio.Api/ApiEndpoints/RequestHelper.cs b/Minio.Api/ApiEndpoints/RequestHelper.cs new file mode 100644 index 000000000..838f0768a --- /dev/null +++ b/Minio.Api/ApiEndpoints/RequestHelper.cs @@ -0,0 +1,15 @@ +using RestSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Minio.Helper +{ + public partial class ClientApiOperations + { + + + } +} diff --git a/Minio.Api/BucketRegionCache.cs b/Minio.Api/BucketRegionCache.cs index cc9acc3bd..e72df28b6 100644 --- a/Minio.Api/BucketRegionCache.cs +++ b/Minio.Api/BucketRegionCache.cs @@ -14,7 +14,6 @@ * limitations under the License. */ - using Minio.Helper; using RestSharp; using System; @@ -81,13 +80,14 @@ public bool Exists(String bucketName) string value = null; this.regionMap.TryGetValue(bucketName, out value); return value != null; + } /// /// Updates Region cache for given bucket. /// /// - internal async Task Update(MinioRestClient client, string bucketName) + internal async Task Update(MinioRestClient client,string bucketName) { string region = null; @@ -97,7 +97,7 @@ internal async Task Update(MinioRestClient client, string bucketName) string location = null; var path = bucketName + "?location"; var request = new RestRequest(path, Method.GET); - + var response = await client.ExecuteTaskAsync(client.NoErrorHandlers, request); if (HttpStatusCode.OK.Equals(response.StatusCode)) @@ -131,5 +131,11 @@ internal async Task Update(MinioRestClient client, string bucketName) return region; } + + /// + /// Updates Region cache for given bucket. + /// + /// + } } diff --git a/Minio.Api/Helper/utils.cs b/Minio.Api/Helper/utils.cs index a7617f790..ae7895c2d 100644 --- a/Minio.Api/Helper/utils.cs +++ b/Minio.Api/Helper/utils.cs @@ -55,6 +55,10 @@ internal static void validateBucketName(string bucketName) { throw new InvalidBucketNameException(bucketName,"Bucket name cannot start or end with a '.' dot."); } + if (bucketName.Any(c => char.IsUpper(c))) + { + throw new InvalidBucketNameException(bucketName, "Bucket name cannot have upper case characters"); + } if (invalidDotBucketName.IsMatch(bucketName)) { throw new InvalidBucketNameException(bucketName,"Bucket name cannot have successive periods."); diff --git a/Minio.Api/MinioApi.csproj b/Minio.Api/MinioApi.csproj index 0c39f7335..ce8494b46 100644 --- a/Minio.Api/MinioApi.csproj +++ b/Minio.Api/MinioApi.csproj @@ -131,6 +131,7 @@ + diff --git a/Minio.Api/MinioRestClient.cs b/Minio.Api/MinioRestClient.cs index 9d273bd7a..68a152d06 100644 --- a/Minio.Api/MinioRestClient.cs +++ b/Minio.Api/MinioRestClient.cs @@ -20,14 +20,11 @@ using RestSharp; using System.Net; using System.Linq; -using System.Text; -using RestSharp.Extensions; using System.IO; using System.Xml.Serialization; using System.Threading; using System.Threading.Tasks; using Minio.Helper; -using System.Diagnostics; using Newtonsoft.Json; namespace Minio @@ -46,6 +43,7 @@ public sealed class MinioRestClient internal string s3AccelerateEndpoint; internal RestClient restClient; internal V4Authenticator authenticator; + internal BucketRegionCache regionCache; public ClientApiOperations Api; internal readonly IEnumerable NoErrorHandlers = Enumerable.Empty(); @@ -80,16 +78,150 @@ private string FullUserAgent } /// - /// Constructs a new URI from the endpoint and method path + /// Constructs a RestRequest. For AWS, this function overrides the baseUrl in the RestClient + /// with region specific host path or virtual style path. /// - /// + /// HTTP method + /// Bucket Name + /// Object Name + /// Region - applies only to AWS + /// unused headerMap + /// unused queryParamMap + /// Content Type + /// request body + /// query string /// - internal UriBuilder GetUriBuilder(string methodPath) + internal async Task CreateRequest(Method method, string bucketName, string objectName = null, + string region = null, Dictionary headerMap = null, + string contentType = "application/xml", + Object body = null, string resourcePath=null) { - var uripath = new UriBuilder(this.Endpoint); - uripath.Path += methodPath; - return uripath; + if (bucketName == null && objectName == null) + { + throw new InvalidBucketNameException(bucketName, "null bucket name for object '" + objectName + "'"); + } + utils.validateBucketName(bucketName); + if (objectName != null) + { + utils.validateObjectName(objectName); + + } + string host = this.BaseUrl; + + //Fetch correct region for bucket + if (!BucketRegionCache.Instance.Exists(bucketName)) + { + region = await BucketRegionCache.Instance.Update(this, bucketName); + } + + string baseUrl = null; //Base url path + string resource = null; //Resource being requested + bool usePathStyle = false; + if (s3utils.IsAmazonEndPoint(this.BaseUrl)) + { + if (this.s3AccelerateEndpoint != null && bucketName != null) + { + // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html + // Disable transfer acceleration for non-compliant bucket names. + if (bucketName.Contains(".")) + { + throw new InvalidTransferAccelerationBucketException(bucketName); + } + // If transfer acceleration is requested set new host. + // For more details about enabling transfer acceleration read here. + // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html + host = s3AccelerateEndpoint; + } + else + { + // Fetch new host based on the bucket location. + host = AWSS3Endpoints.Instance.endpoint(region); + + } + + usePathStyle = false; + var scheme = this.Secure ? Uri.UriSchemeHttps : Uri.UriSchemeHttp; + + if (method == Method.PUT && objectName == null && resourcePath == null) + { + // use path style for make bucket to workaround "AuthorizationHeaderMalformed" error from s3.amazonaws.com + usePathStyle = true; + } + else if (resourcePath != null && resourcePath.Contains("location")) + { + // use path style for location query + usePathStyle = true; + } + else if (bucketName.Contains(".") && this.Secure) + { + // use path style where '.' in bucketName causes SSL certificate validation error + usePathStyle = true; + } + else if (method == Method.HEAD) + { + usePathStyle = true; + } + + if (usePathStyle) + { + resource = utils.UrlEncode(bucketName) + "/"; + } + else + { + baseUrl = scheme + "://" + utils.UrlEncode(bucketName) + "." + utils.UrlEncode(host) + "/"; + resource = "/"; + } + } + else + { + resource = utils.UrlEncode(bucketName) + "/"; + } + + if (s3utils.IsAmazonEndPoint(this.BaseUrl) && region != null) + { + //override the baseUrl in RestClient with virtual style path or region + // specific deviation from AWS default url. + _constructUri(region, bucketName); + this.restClient.BaseUrl = usePathStyle == true ? this.uri : new Uri(baseUrl); + + } + if (objectName != null) + { + // Limitation: OkHttp does not allow to add '.' and '..' as path segment. + foreach (String pathSegment in objectName.Split('/')) + { + resource += utils.UrlEncode(pathSegment); + } + + } + if (resourcePath != null) + { + resource += resourcePath; + } + + RestRequest request = new RestRequest(resource,method); + + if (body != null) + { + request.AddParameter(contentType, body, RestSharp.ParameterType.RequestBody); + + } + + if (contentType != null) + { + request.AddHeader("Content-Type", contentType); + } + if (headerMap != null) + { + foreach (KeyValuePair entry in headerMap) + { + request.AddHeader(entry.Key, entry.Value); + } + } + + return request; } + internal void ModifyAWSEndpointFor(string region, string bucketName = null) { @@ -97,10 +229,31 @@ internal void ModifyAWSEndpointFor(string region, string bucketName = null) { _constructUri(region, bucketName); this.restClient.BaseUrl = this.uri; + + } + } + internal async Task ModifyTargetURL(IRestRequest request, string bucketName,bool usePathStyle=false) + { + var resource_url = this.Endpoint; + if (s3utils.IsAmazonEndPoint(this.BaseUrl)) + { + // ``us-east-1`` is not a valid location constraint according to amazon, so we skip it. + string location = await BucketRegionCache.Instance.Update(this,bucketName); + // if (location != "us-east-1") + { + ModifyAWSEndpointFor(location, bucketName); + resource_url = MakeTargetURL(location, bucketName,usePathStyle); + } + //else + //{ // use default request + // resource_url = ""; + // } } + return resource_url; + } - internal string MakeTargetURL(string region = null, string bucketName = null) + internal string MakeTargetURL(string region = null, string bucketName = null,bool usePathStyle=false) { string targetUrl = null; string host = this.BaseUrl; @@ -132,14 +285,21 @@ internal string MakeTargetURL(string region = null, string bucketName = null) // endpoint URL. if (bucketName != null && s3utils.IsAmazonEndPoint(this.BaseUrl)) { + // Save if target url will have buckets which suppport virtual host. bool isVirtualHostStyle = s3utils.IsVirtualHostSupported(uri, bucketName); + if (bucketName.Contains(".") && this.Secure) + { + // use path style where '.' in bucketName causes SSL certificate validation error + usePathStyle = true; + } // If endpoint supports virtual host style use that always. // Currently only S3 and Google Cloud Storage would support // virtual host style. string urlStr = null; - if (isVirtualHostStyle) + + if (isVirtualHostStyle || !usePathStyle) { targetUrl = scheme + "://" + bucketName + "." + host + "/"; } @@ -314,6 +474,7 @@ public MinioRestClient(string endpoint, string accessKey = "", string secretKey this.AccessKey = accessKey; this.SecretKey = secretKey; this.s3AccelerateEndpoint = null; + this.regionCache = BucketRegionCache.Instance; this.Anonymous = utils.isAnonymousClient(accessKey, secretKey); _constructUri(); _validateUri(); diff --git a/Minio.Api/Regions.cs b/Minio.Api/Regions.cs index 5deb7074d..b20536e3c 100644 --- a/Minio.Api/Regions.cs +++ b/Minio.Api/Regions.cs @@ -14,9 +14,11 @@ * limitations under the License. */ +using System; +using System.Text.RegularExpressions; namespace Minio { - class Regions + public class Regions { private Regions() { @@ -29,29 +31,45 @@ private Regions() /// Region corresponding to the endpoint. Default is 'us-east-1' internal static string GetRegion(string endpoint) { - switch (endpoint) - { - case "s3-ap-northeast-1.amazonaws.com": - return "ap-northeast-1"; - case "s3-ap-southeast-1.amazonaws.com": - return "ap-southeast-1"; - case "s3-ap-southeast-2.amazonaws.com": - return "ap-southeast-2"; - case "s3-eu-central-1.amazonaws.com": - return "eu-central-1"; - case "s3-eu-west-1.amazonaws.com": - return "eu-west-1"; - case "s3-sa-east-1.amazonaws.com": - return "sa-east-1"; - case "s3.amazonaws.com": - return "us-east-1"; - case "s3-us-west-1.amazonaws.com": - return "us-west-1"; - case "s3-us-west-2.amazonaws.com": - return "us-west-2"; - default: - return "us-east-1"; + if (endpoint.EndsWith("s3 - ap - northeast - 1.amazonaws.com")) + { + return "ap-northeast-1"; + } + if (endpoint.EndsWith("s3-ap-southeast-1.amazonaws.com")) + { + return "ap-southeast-1"; + } + if (endpoint.EndsWith("s3-ap-southeast-2.amazonaws.com")) + { + return "ap-southeast-2"; + + } + if (endpoint.EndsWith("s3-eu-central-1.amazonaws.com")) + { + return "eu-central-1"; + } + if (endpoint.EndsWith("s3-eu-west-1.amazonaws.com")) + { + return "eu-west-1"; + } + if (endpoint.EndsWith("s3-sa-east-1.amazonaws.com")) + { + return "sa-east-1"; + } + if (endpoint.EndsWith("s3.amazonaws.com")) + { + return "us-east-1"; + } + if (endpoint.EndsWith("s3-us-west-1.amazonaws.com")) + { + return "us-west-1"; + } + if (endpoint.EndsWith("s3-us-west-2.amazonaws.com")) + { + return "us-west-2"; } + return "us-east-1"; } + } } diff --git a/Minio.Examples/Cases/BucketExists.cs b/Minio.Examples/Cases/BucketExists.cs index 3ad39f0be..c65277156 100644 --- a/Minio.Examples/Cases/BucketExists.cs +++ b/Minio.Examples/Cases/BucketExists.cs @@ -9,11 +9,12 @@ namespace Minio.Examples.Cases class BucketExists { //Check if a bucket exists - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name") { try { - bool found = await minio.Api.BucketExistsAsync("mountshasta"); + bool found = await minio.Api.BucketExistsAsync(bucketName); Console.Out.WriteLine("bucket-name was " + ((found == true) ? "found" : "not found")); } catch (Exception e) diff --git a/Minio.Examples/Cases/CopyObject.cs b/Minio.Examples/Cases/CopyObject.cs index d8327acd2..527fcd3b4 100644 --- a/Minio.Examples/Cases/CopyObject.cs +++ b/Minio.Examples/Cases/CopyObject.cs @@ -9,11 +9,20 @@ namespace Minio.Examples.Cases class CopyObject { //copy object from one bucket to another - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string fromBucketName="from-bucket-name", + string fromObjectName="from-object-name", + string destBucketName="dest-bucket", + string destObjectName="to-object-name") { try { - await minio.Api.CopyObjectAsync("mountshasta", "testobject", "bobcat2t", "copi2dobj", null); + //Optionally pass copy conditions + await minio.Api.CopyObjectAsync(fromBucketName, + fromObjectName, + destBucketName, + destObjectName, + copyConditions:null); Console.Out.WriteLine("done copying"); } catch (Exception e) diff --git a/Minio.Examples/Cases/FGetObject.cs b/Minio.Examples/Cases/FGetObject.cs index d06cfc2c7..88d9b5349 100644 --- a/Minio.Examples/Cases/FGetObject.cs +++ b/Minio.Examples/Cases/FGetObject.cs @@ -8,14 +8,15 @@ namespace Minio.Examples.Cases { class FGetObject { - //get object in a bucket - public async static Task Run(Minio.MinioRestClient minio) + //Download object from bucket into local file + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectName = "my-object-name", + string fileName="local-filename") { try { - string fileName = "C:\\Users\\vagrant\\Downloads\\sDownload3"; - - await minio.Api.GetObjectAsync("mountshasta", "full-upload-multi", fileName); + await minio.Api.GetObjectAsync(bucketName, objectName, fileName); } catch (Exception e) diff --git a/Minio.Examples/Cases/FPutObject.cs b/Minio.Examples/Cases/FPutObject.cs index 0a3c3577c..1d3178d4c 100644 --- a/Minio.Examples/Cases/FPutObject.cs +++ b/Minio.Examples/Cases/FPutObject.cs @@ -9,21 +9,18 @@ namespace Minio.Examples.Cases class FPutObject { - //get object in a bucket - public async static Task Run(Minio.MinioRestClient minio) + //Upload object to bucket from file + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectName = "my-object-name", + string fileName = "from where") { try { - //TODO uncomment later - //await minio.Objects.PutObjectAsync("bucket-name", "object-name", "fileName", "optional-content-type-or-null"); - - //TODO end uncomment - - //TODO comment out for release - // String fileName = "C:\\Users\\vagrant\\Downloads\\go1.7.4.windows-amd64.msi"; - String fileName = "C:\\Users\\vagrant\\Downloads\\multipart-2parts"; - await minio.Api.PutObjectAsync("mountshasta", "full-upload-fromfile2", fileName,contentType: "application/octet-stream"); - //TODO end comment out for release + await minio.Api.PutObjectAsync(bucketName, + objectName, + fileName, + contentType: "application/octet-stream"); Console.Out.WriteLine("done uploading"); } catch (Exception e) diff --git a/Minio.Examples/Cases/GetBucketPolicy.cs b/Minio.Examples/Cases/GetBucketPolicy.cs index 284631358..f11b2a7ae 100644 --- a/Minio.Examples/Cases/GetBucketPolicy.cs +++ b/Minio.Examples/Cases/GetBucketPolicy.cs @@ -8,12 +8,14 @@ namespace Minio.Examples.Cases { class GetBucketPolicy { - //get bucket policy - public async static Task Run(Minio.MinioRestClient minio) + //get bucket policy + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string prefix="") { try { - PolicyType policy = await minio.Api.GetPolicyAsync("mountshasta2",objectPrefix:"bnds"); + PolicyType policy = await minio.Api.GetPolicyAsync(bucketName,objectPrefix:prefix); Console.Out.WriteLine("POLICY: " + policy.GetType().ToString()); } catch (Exception e) diff --git a/Minio.Examples/Cases/GetObject.cs b/Minio.Examples/Cases/GetObject.cs index 3e2817106..1408c9b03 100644 --- a/Minio.Examples/Cases/GetObject.cs +++ b/Minio.Examples/Cases/GetObject.cs @@ -10,11 +10,14 @@ namespace Minio.Examples.Cases class GetObject { //get object in a bucket - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string bucketName="my-bucket-name", + string objectName="my-object-name") { try { - await minio.Api.GetObjectAsync("mountshasta", "copyright.txt", (stream) => + await minio.Api.GetObjectAsync(bucketName, objectName, + (stream) => { stream.CopyTo(Console.OpenStandardOutput()); }); diff --git a/Minio.Examples/Cases/ListBuckets.cs b/Minio.Examples/Cases/ListBuckets.cs index 1e645e564..3fb98d65d 100644 --- a/Minio.Examples/Cases/ListBuckets.cs +++ b/Minio.Examples/Cases/ListBuckets.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Minio.DataModel; @@ -9,6 +6,7 @@ namespace Minio.Examples.Cases { class ListBuckets { + // List all buckets on host public async static Task Run(Minio.MinioRestClient minio) { try diff --git a/Minio.Examples/Cases/ListIncompleteUploads.cs b/Minio.Examples/Cases/ListIncompleteUploads.cs index c5254a44e..612d0195d 100644 --- a/Minio.Examples/Cases/ListIncompleteUploads.cs +++ b/Minio.Examples/Cases/ListIncompleteUploads.cs @@ -1,32 +1,26 @@ using Minio.DataModel; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; + namespace Minio.Examples.Cases { class ListIncompleteUploads { - public static void Run(Minio.MinioRestClient minio) + //List incomplete uploads on the bucket matching specified prefix + public static void Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string prefix = "my-object-name", + bool recursive = true) { try { - var bucketName = "bucket-name"; - var bucketObject = "bucket-object"; - - bucketName = "mountshasta"; - bucketObject = "multi1112"; - IObservable observable = minio.Api.ListIncompleteUploads(bucketName, bucketObject, true); + IObservable observable = minio.Api.ListIncompleteUploads(bucketName, prefix, recursive); IDisposable subscription = observable.Subscribe( item => Console.WriteLine("OnNext: {0}", item.Key), ex => Console.WriteLine("OnError: {0}", ex.Message), () => Console.WriteLine("OnComplete: {0}")); - // subscription.Dispose(); - } catch (Exception e) { diff --git a/Minio.Examples/Cases/ListObjects.cs b/Minio.Examples/Cases/ListObjects.cs index 9fdf6e6a5..27640df0e 100644 --- a/Minio.Examples/Cases/ListObjects.cs +++ b/Minio.Examples/Cases/ListObjects.cs @@ -1,20 +1,19 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Minio.DataModel; + namespace Minio.Examples.Cases { + class ListObjects { - public async static Task Run(Minio.MinioRestClient minio) + //List objects matching optional prefix in a specified bucket. + public static void Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string prefix = null, + bool recursive = false) { try { - var bucketName = "bucket-name"; - var prefix = "object-prefix"; - var recursive = false; bucketName = "mountshasta"; prefix = null; @@ -27,6 +26,7 @@ public async static Task Run(Minio.MinioRestClient minio) item => Console.WriteLine("OnNext: {0}", item.Key), ex => Console.WriteLine("OnError: {0}", ex.Message), () => Console.WriteLine("OnComplete: {0}")); + */ // subscription.Dispose(); } diff --git a/Minio.Examples/Cases/MakeBucket.cs b/Minio.Examples/Cases/MakeBucket.cs index 8bf09680d..ce0924e1b 100644 --- a/Minio.Examples/Cases/MakeBucket.cs +++ b/Minio.Examples/Cases/MakeBucket.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Minio.Examples.Cases @@ -9,13 +6,13 @@ namespace Minio.Examples.Cases public class MakeBucket { //Make a bucket - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string bucketName="my-bucket-name") { try { - await minio.Api.MakeBucketAsync("mybucket"); - Console.Out.WriteLine("mybucket created successfully"); - + await minio.Api.MakeBucketAsync(bucketName); + Console.Out.WriteLine("bucket-name created successfully"); } catch (Exception e) { diff --git a/Minio.Examples/Cases/PutObject.cs b/Minio.Examples/Cases/PutObject.cs index 0fa28339b..50592a564 100644 --- a/Minio.Examples/Cases/PutObject.cs +++ b/Minio.Examples/Cases/PutObject.cs @@ -1,39 +1,28 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Minio.Examples.Cases { class PutObject { - //get object in a bucket - public async static Task Run(Minio.MinioRestClient minio) + //Put an object from a local stream into bucket + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectName = "my-object-name", + string fileName="location-of-file") { try { - //TODO uncomment later - //test1- simple upload - // byte[] data = System.Text.Encoding.UTF8.GetBytes("hello world"); - //await minio.Objects.PutObjectAsync("bucket-name", "object-name", data, data.Length, "application/octet-stream"); - - //await minio.Objects.PutObjectAsync("asiatrip", "hellotext", new MemoryStream(data), 11, "application/octet-stream"); - //test2 - multipart upload - //String fileName = "path-to-a-file-larger-than-5mb-less-than-5gb"; - //byte[] bs = File.ReadAllBytes(fileName); - //System.IO.MemoryStream filestream = new System.IO.MemoryStream(bs); - //await minio.Objects.PutObjectAsync("bucket-name", "object-name", filestream, filestream.Length, "application/octet-stream"); - //TODO end uncomment - - //TODO comment out for release - // String fileName = "C:\\Users\\vagrant\\Downloads\\go1.7.4.windows-amd64.msi"; - String fileName = "C:\\Users\\vagrant\\Downloads\\multipart-2parts"; byte[] bs = File.ReadAllBytes(fileName); System.IO.MemoryStream filestream = new System.IO.MemoryStream(bs); - await minio.Api.PutObjectAsync("mountshasta", "full-upload-multi", filestream, filestream.Length, "application/octet-stream"); - //TODO end comment out for release + + await minio.Api.PutObjectAsync(bucketName, + objectName, + filestream, + filestream.Length, + "application/octet-stream"); + Console.Out.WriteLine("done uploading"); } catch (Exception e) diff --git a/Minio.Examples/Cases/RemoveBucket.cs b/Minio.Examples/Cases/RemoveBucket.cs index 2cf47d5a6..6376e4f7a 100644 --- a/Minio.Examples/Cases/RemoveBucket.cs +++ b/Minio.Examples/Cases/RemoveBucket.cs @@ -1,15 +1,17 @@ using System; using System.Threading.Tasks; + namespace Minio.Examples.Cases { class RemoveBucket { //Remove a bucket - public async static Task Run(MinioRestClient minio) + public async static Task Run(MinioRestClient minio, + string bucketName = "my-bucket-name") { try { - await minio.Api.RemoveBucketAsync("dminio"); + await minio.Api.RemoveBucketAsync(bucketName); Console.Out.WriteLine("bucket-name removed successfully"); } catch (Exception e) diff --git a/Minio.Examples/Cases/RemoveIncompleteUpload.cs b/Minio.Examples/Cases/RemoveIncompleteUpload.cs index 3e5160730..684495fec 100644 --- a/Minio.Examples/Cases/RemoveIncompleteUpload.cs +++ b/Minio.Examples/Cases/RemoveIncompleteUpload.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Minio.Examples.Cases @@ -10,16 +7,13 @@ class RemoveIncompleteUpload { //Remove incomplete upload object from a bucket - public async static Task Run(MinioRestClient minio) + public async static Task Run(MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectName = "my-object-name") { try { - var bucketName = "bucket-name"; - var bucketObject = "bucket-object"; - - bucketName = "mountshasta"; - bucketObject = "newmulti-225"; - await minio.Api.RemoveIncompleteUploadAsync(bucketName, bucketObject); + await minio.Api.RemoveIncompleteUploadAsync(bucketName, objectName); Console.Out.WriteLine("object-name removed from bucket-name successfully"); } catch (Exception e) diff --git a/Minio.Examples/Cases/RemoveObject.cs b/Minio.Examples/Cases/RemoveObject.cs index 17d832682..65af96836 100644 --- a/Minio.Examples/Cases/RemoveObject.cs +++ b/Minio.Examples/Cases/RemoveObject.cs @@ -1,19 +1,18 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using Minio; + namespace Minio.Examples.Cases { class RemoveObject { //Remove an object from a bucket - public async static Task Run(MinioRestClient minio) + public async static Task Run(MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectName = "my-object-name") { try { - await minio.Api.RemoveObjectAsync("bucket-name","object-name"); + await minio.Api.RemoveObjectAsync(bucketName,objectName); Console.Out.WriteLine("object-name removed from bucket-name successfully"); } catch (Exception e) diff --git a/Minio.Examples/Cases/SetBucketPolicy.cs b/Minio.Examples/Cases/SetBucketPolicy.cs index bdbd0df7f..da9fe0add 100644 --- a/Minio.Examples/Cases/SetBucketPolicy.cs +++ b/Minio.Examples/Cases/SetBucketPolicy.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using Minio.DataModel.Policy; using Minio.DataModel; namespace Minio.Examples.Cases @@ -11,11 +7,16 @@ namespace Minio.Examples.Cases class SetBucketPolicy { //set bucket policy - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string objectPrefix="") { try { - await minio.Api.SetPolicyAsync("mountshasta2", "bobcat",PolicyType.READ_ONLY); + //Change policy type parameter + await minio.Api.SetPolicyAsync(bucketName, + objectPrefix, + PolicyType.READ_ONLY); } catch (Exception e) diff --git a/Minio.Examples/Cases/StatObject.cs b/Minio.Examples/Cases/StatObject.cs index b568ec93f..013078784 100644 --- a/Minio.Examples/Cases/StatObject.cs +++ b/Minio.Examples/Cases/StatObject.cs @@ -1,21 +1,16 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Minio.DataModel; + namespace Minio.Examples.Cases { class StatObject { //get stats on a object - public async static Task Run(Minio.MinioRestClient minio) + public async static Task Run(Minio.MinioRestClient minio, + string bucketName = "my-bucket-name", + string bucketObject="my-object-name") { - var bucketName = "bucket-name"; - var bucketObject = "bucket-object"; - - // bucketName = "asiatrip"; - // bucketObject = "asiaphotos.jpg"; try { ObjectStat statObject = await minio.Api.StatObjectAsync(bucketName, bucketObject); diff --git a/Minio.Examples/Program.cs b/Minio.Examples/Program.cs index 450a62dce..360abc445 100644 --- a/Minio.Examples/Program.cs +++ b/Minio.Examples/Program.cs @@ -6,66 +6,66 @@ using Minio; using System.Net; using Minio.Exceptions; +using System.Text.RegularExpressions; + namespace Minio.Examples { class Program { public static void Main(string[] args) { - /* - var minioClient = new Minio.MinioRestClient("play.minio.io:9000", + + var minioClient2 = new Minio.MinioRestClient("play.minio.io:9000", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" ).WithSSL(); - */ - //ServicePointManager.Expect100Continue = true; + + ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; var endPoint = Environment.GetEnvironmentVariable("AWS_ENDPOINT"); - var accessKey = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY"); - var secretKey = Environment.GetEnvironmentVariable("AWS_SECRET_KEY"); + var accessKey = Environment.GetEnvironmentVariable("MY_AWS_ACCESS_KEY"); + var secretKey = Environment.GetEnvironmentVariable("MY_AWS_SECRET_KEY"); - endPoint = "s3-us-west-1.amazonaws.com"; var minioClient = new MinioRestClient(endPoint, accessKey: accessKey, secretKey: secretKey).WithSSL(); try { + + string bucketName = "testminiopolicyzzz"; + string objectName ="testobject"; + string prefix = "mult"; + string smallFilePath = "C:\\Users\\vagrant\\Downloads\\hellotext"; + string uploadFilePath = "C:\\Users\\vagrant\\Downloads\\go1.7.4.windows-amd64.msi"; + string downloadFilePath = "C:\\Users\\vagrant\\Downloads\\downloaded-object"; + string destBucketName = "mtky2"; + string destObjectName = "copyrighted_copy.txt"; + string removeObject = "newmulti-406"; //Set app Info minioClient.SetAppInfo("app-name", "app-version"); - // Cases.MakeBucket.Run(minioClient).Wait(); - - // Cases.RemoveBucket.Run(minioClient).Wait(); - - Cases.BucketExists.Run(minioClient).Wait(); - // Cases.ListObjects.Run(minioClient).Wait(); - // Cases.GetBucketPolicy.Run(minioClient).Wait(); - // Cases.SetBucketPolicy.Run(minioClient).Wait(); - - //Cases.ListBuckets.Run(minioClient).Wait(); - - // Cases.MakeBucket.Run(minioClient).Wait(); - // Cases.FPutObject.Run(minioClient).Wait(); - // Cases.GetObject.Run(minioClient).Wait(); - - Cases.MakeBucket.Run(minioClient).Wait(); + + Cases.MakeBucket.Run(minioClient, bucketName).Wait(); + Cases.BucketExists.Run(minioClient, bucketName).Wait(); Cases.ListBuckets.Run(minioClient).Wait(); - - Cases.FPutObject.Run(minioClient).Wait(); - - // Cases.GetObject.Run(minioClient).Wait(); - - Cases.GetObject.Run(minioClient).Wait(); - Cases.StatObject.Run(minioClient).Wait(); - Cases.PutObject.Run(minioClient).Wait(); - Cases.ListIncompleteUploads.Run(minioClient); - Cases.RemoveIncompleteUpload.Run(minioClient).Wait(); - Cases.CopyObject.Run(minioClient).Wait(); - Cases.ListObjects.Run(minioClient).Wait(); - Cases.FGetObject.Run(minioClient).Wait(); - + Cases.ListObjects.Run(minioClient, bucketName); + Cases.PutObject.Run(minioClient, bucketName, objectName, smallFilePath).Wait(); + Cases.GetObject.Run(minioClient, bucketName, objectName).Wait(); + Cases.FPutObject.Run(minioClient, bucketName, objectName,uploadFilePath).Wait(); + + Cases.FGetObject.Run(minioClient, bucketName, objectName,downloadFilePath).Wait(); + + Cases.RemoveBucket.Run(minioClient, bucketName).Wait(); + Cases.ListIncompleteUploads.Run(minioClient, bucketName, prefix:prefix); + Cases.RemoveIncompleteUpload.Run(minioClient, bucketName, removeObject).Wait(); + + Cases.GetBucketPolicy.Run(minioClient, bucketName).Wait(); + + Cases.SetBucketPolicy.Run(minioClient, bucketName).Wait(); + Cases.StatObject.Run(minioClient, bucketName, objectName).Wait(); + Cases.CopyObject.Run(minioClient, bucketName, objectName, destBucketName, destObjectName).Wait(); Console.ReadLine(); } catch(ClientException ex) diff --git a/SimpleTest/Program.cs b/SimpleTest/Program.cs index 5e9fc8589..270910833 100644 --- a/SimpleTest/Program.cs +++ b/SimpleTest/Program.cs @@ -2,15 +2,10 @@ using System; using Minio; using Minio.DataModel; -<<<<<<< HEAD - -======= + using System.Configuration; ->>>>>>> 5391fusing System.Net; using System.Threading.Tasks; -c1... add presigned operations -using System.Threading.Tasks; using System.Net; namespace SimpleTest @@ -45,10 +40,11 @@ static void Main(string[] args) { Console.Out.WriteLine(bucket.Name + " " + bucket.CreationDateDateTime); } + + //Supply a new bucket name + Task.WaitAll(minio.Api.MakeBucketAsync("MyNewBucket")); - - - var bucketExistTask = minio.Api.BucketExistsAsync("bucky"); + var bucketExistTask = minio.Api.BucketExistsAsync("MyNewBucket"); Task.WaitAll(bucketExistTask); var found = bucketExistTask.Result; Console.Out.WriteLine("bucket was " + found); diff --git a/d5ozndk4.2pt.txt b/d5ozndk4.2pt.txt new file mode 100644 index 000000000..91aa30995 --- /dev/null +++ b/d5ozndk4.2pt.txt @@ -0,0 +1,31 @@ +modified target url for aws requests + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# interactive rebase in progress; onto 7c53c60 +# Last commands done (32 commands done): +# pick cab4327 added presigned operations +# pick 3978416 modified target url for aws requests +# Next commands to do (3 remaining commands): +# pick 7637d41 support virtual style calls +# pick 6f28883 added examples for presigned operations +# You are currently rebasing branch 'master' on '7c53c60'. +# +# Changes to be committed: +# modified: Minio.Api/AWSS3Endpoints.cs +# modified: Minio.Api/ApiEndpoints/BucketOperations.cs +# modified: Minio.Api/BucketRegionCache.cs +# modified: Minio.Api/Exceptions/InvalidTransferAccelerationBucketException.cs +# modified: Minio.Api/MinioRestClient.cs +# modified: Minio.Examples/Cases/BucketExists.cs +# modified: Minio.Examples/Cases/GetBucketPolicy.cs +# modified: Minio.Examples/Cases/GetObject.cs +# modified: Minio.Examples/Cases/MakeBucket.cs +# modified: Minio.Examples/Cases/SetBucketPolicy.cs +# modified: Minio.Examples/Program.cs +# new file: Minio.Tests/App.config +# new file: Minio.Tests/Minio.Tests.csproj +# new file: Minio.Tests/Properties/AssemblyInfo.cs +# new file: Minio.Tests/UnitTest1.cs +# + diff --git a/i2c2nxk1.mwo.txt b/i2c2nxk1.mwo.txt new file mode 100644 index 000000000..6ceda48a8 --- /dev/null +++ b/i2c2nxk1.mwo.txt @@ -0,0 +1,34 @@ +modified target url for aws requests + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# interactive rebase in progress; onto 7c53c60 +# Last commands done (32 commands done): +# pick cab4327 added presigned operations +# pick 3978416 modified target url for aws requests +# Next commands to do (3 remaining commands): +# pick 7637d41 support virtual style calls +# pick 6f28883 added examples for presigned operations +# You are currently rebasing branch 'master' on '7c53c60'. +# +# Changes to be committed: +# modified: Minio.Api/AWSS3Endpoints.cs +# modified: Minio.Api/ApiEndpoints/BucketOperations.cs +# modified: Minio.Api/BucketRegionCache.cs +# modified: Minio.Api/Exceptions/InvalidTransferAccelerationBucketException.cs +# modified: Minio.Api/MinioRestClient.cs +# modified: Minio.Examples/Cases/BucketExists.cs +# modified: Minio.Examples/Cases/GetBucketPolicy.cs +# modified: Minio.Examples/Cases/GetObject.cs +# modified: Minio.Examples/Cases/MakeBucket.cs +# modified: Minio.Examples/Cases/SetBucketPolicy.cs +# modified: Minio.Examples/Program.cs +# new file: Minio.Tests/App.config +# new file: Minio.Tests/Minio.Tests.csproj +# new file: Minio.Tests/Properties/AssemblyInfo.cs +# new file: Minio.Tests/UnitTest1.cs +# +# Untracked files: +# d5ozndk4.2pt.txt +# +