Пример #1
0
        /// <summary>
        /// Connects to Cloud Storage with HTTPS if this method is invoked on client object
        /// </summary>
        /// <returns></returns>
        public MinioClient WithSSL()
        {
            this.Secure = true;
            Uri secureUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure);

            SetTargetURL(secureUrl);
            return(this);
        }
Пример #2
0
        /// <summary>
        /// Connects to Cloud Storage with HTTPS if this method is invoked on client object
        /// </summary>
        /// <returns></returns>
        public MinioClient WithSSL()
        {
            this.Secure = true;
            if (string.IsNullOrEmpty(this.BaseUrl))
            {
                return(this);
            }
            Uri secureUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure);

            return(this);
        }
Пример #3
0
        /// <summary>
        /// Updates Region cache for given bucket.
        /// </summary>
        /// <param name="bucketName"></param>
        internal async Task <string> Update(MinioClient client, string bucketName)
        {
            string region = null;

            if (bucketName != null && client.AccessKey != null &&
                client.SecretKey != null && !Instance.Exists(bucketName))
            {
                string location = null;
                var    path     = utils.UrlEncode(bucketName) + "?location";
                // Initialize client
                Uri requestUrl = RequestUtil.MakeTargetURL(client.BaseUrl, client.Secure);
                client.SetTargetURL(requestUrl);

                var request = new RestRequest(path, Method.GET);

                var response = await client.ExecuteTaskAsync(client.NoErrorHandlers, request).ConfigureAwait(false);

                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.
                Instance.Add(bucketName, region);
            }
            return(region);
        }
Пример #4
0
        /// <summary>
        ///  Presigned post policy
        /// </summary>
        public async Task <Tuple <string, Dictionary <string, string> > > PresignedPostPolicyAsync(PostPolicy policy)
        {
            string region = null;

            if (!policy.IsBucketSet())
            {
                throw new ArgumentException("bucket should be set");
            }

            if (!policy.IsKeySet())
            {
                throw new ArgumentException("key should be set");
            }

            if (!policy.IsExpirationSet())
            {
                throw new ArgumentException("expiration should be set");
            }

            // Initialize a new client.
            if (!BucketRegionCache.Instance.Exists(policy.Bucket))
            {
                region = await BucketRegionCache.Instance.Update(this, policy.Bucket);
            }
            else
            {
                region = BucketRegionCache.Instance.Region(policy.Bucket);
            }
            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, bucketName: policy.Bucket, region: region, usePathStyle: false);

            SetTargetURL(requestUrl);
            DateTime signingDate = DateTime.UtcNow;

            policy.SetAlgorithm("AWS4-HMAC-SHA256");
            policy.SetCredential(this.authenticator.GetCredentialString(signingDate, region));
            policy.SetDate(signingDate);

            string policyBase64 = policy.Base64();
            string signature    = this.authenticator.PresignPostSignature(region, signingDate, policyBase64);

            policy.SetPolicy(policyBase64);
            policy.SetSignature(signature);

            return(new Tuple <string, Dictionary <string, string> >(this.restClient.BaseUrl.AbsoluteUri, policy.GetFormData()));
        }
Пример #5
0
        /// <summary>
        /// Updates Region cache for given bucket.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="bucketName"></param>
        internal async Task <string> Update(MinioClient client, string bucketName)
        {
            string region = null;

            if (bucketName != null && client.AccessKey != null &&
                client.SecretKey != null && !Instance.Exists(bucketName))
            {
                string location = null;
                var    path     = utils.UrlEncode(bucketName);
                // Initialize client
                Uri requestUrl = RequestUtil.MakeTargetURL(client.BaseUrl, client.Secure);

                var requestBuilder = new HttpRequestMessageBuilder(HttpMethod.Get, requestUrl, path);
                requestBuilder.AddQueryParameter("location", "");
                ResponseResult response = null;
                response = await client.ExecuteTaskAsync(client.NoErrorHandlers, requestBuilder).ConfigureAwait(false);

                if (response != null && HttpStatusCode.OK.Equals(response.StatusCode))
                {
                    XDocument root = XDocument.Parse(response.Content);
                    location = root.Root.Value;
                }

                if (string.IsNullOrEmpty(location))
                {
                    region = "us-east-1";
                }
                else
                {
                    // eu-west-1 can be sometimes 'EU'.
                    if (location == "EU")
                    {
                        region = "eu-west-1";
                    }
                    else
                    {
                        region = location;
                    }
                }

                // Add the new location.
                Instance.Add(bucketName, region);
            }
            return(region);
        }
Пример #6
0
        /// <summary>
        /// The Init method used with MinioClient constructor with multiple arguments. The host URI for Amazon is set to virtual hosted style
        /// if usePathStyle is false. Otherwise path style URL is constructed.
        /// </summary>
        internal void InitClient()
        {
            if (string.IsNullOrEmpty(this.BaseUrl))
            {
                throw new InvalidEndpointException("Endpoint cannot be empty.");
            }
            else if (this.Secure && this.restClient != null && this.restClient.BaseUrl == null)
            {
                Uri secureUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure);
                this.SetTargetURL(secureUrl);
            }
            string host = this.BaseUrl;

            var scheme = this.Secure ? utils.UrlEncode("https") : utils.UrlEncode("http");

            // This is the actual url pointed to for all HTTP requests
            this.Endpoint = string.Format("{0}://{1}", scheme, host);
            Init();
        }
Пример #7
0
        /// <summary>
        /// Create a private bucket with the given name.
        /// </summary>
        /// <param name="bucketName">Name of the new bucket</param>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        /// <returns> Task </returns>
        public async Task MakeBucketAsync(string bucketName, string location = "us-east-1", CancellationToken cancellationToken = default(CancellationToken))
        {
            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure);

            SetTargetURL(requestUrl);

            var request = new RestRequest("/" + bucketName, Method.PUT);

            request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer();
            request.RequestFormat = DataFormat.Xml;
            // ``us-east-1`` is not a valid location constraint according to amazon, so we skip it.
            if (location != "us-east-1")
            {
                CreateBucketConfiguration config = new CreateBucketConfiguration(location);
                request.AddBody(config);
            }

            var response = await this.ExecuteTaskAsync(this.NoErrorHandlers, request, cancellationToken).ConfigureAwait(false);
        }
Пример #8
0
        /// <summary>
        /// Create a bucket with the given name.
        /// </summary>
        /// <param name="args">MakeBucketArgs Arguments Object that has bucket info like name, location. etc</param>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        /// <returns> Task </returns>
        /// <exception cref="InvalidBucketNameException">When bucketName is invalid</exception>
        public async Task MakeBucketAsync(MakeBucketArgs args, CancellationToken cancellationToken = default(CancellationToken))
        {
            args.Validate();
            RestRequest request = new RestRequest("/" + args.BucketName, Method.PUT);

            if (string.IsNullOrEmpty(args.Location))
            {
                args.Location = this.Region;
            }
            // Set Target URL for MakeBucket
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, args.Location);

            SetTargetURL(requestUrl);
            // Set Authenticator, if necessary.
            if (string.IsNullOrEmpty(this.Region) && !s3utils.IsAmazonEndPoint(this.BaseUrl) && args.Location != "us-east-1" && this.restClient != null)
            {
                this.restClient.Authenticator = new V4Authenticator(this.Secure, this.AccessKey, this.SecretKey, region: args.Location, sessionToken: this.SessionToken);
            }
            await this.ExecuteTaskAsync(this.NoErrorHandlers, args.BuildRequest(request), cancellationToken);
        }
Пример #9
0
        /// <summary>
        /// List all objects in a bucket
        /// </summary>
        /// <param name="bucketName">Bucket to list objects from</param>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        /// <returns>Task with an iterator lazily populated with objects</returns>
        public async Task <ListAllMyBucketsResult> ListBucketsAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure);

            SetTargetURL(requestUrl);
            // Initialize a new client
            //PrepareClient();

            var request  = new RestRequest("/", Method.GET);
            var response = await this.ExecuteTaskAsync(this.NoErrorHandlers, request, cancellationToken).ConfigureAwait(false);

            ListAllMyBucketsResult bucketList = new ListAllMyBucketsResult();

            if (HttpStatusCode.OK.Equals(response.StatusCode))
            {
                var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content);
                using (var stream = new MemoryStream(contentBytes))
                    bucketList = (ListAllMyBucketsResult)(new XmlSerializer(typeof(ListAllMyBucketsResult)).Deserialize(stream));
                return(bucketList);
            }
            return(bucketList);
        }
Пример #10
0
        /// <summary>
        /// Constructs a RestRequest. For AWS, this function has the side-effect of overriding the baseUrl
        /// in the RestClient with region specific host path or virtual style path.
        /// </summary>
        /// <param name="method">HTTP method</param>
        /// <param name="bucketName">Bucket Name</param>
        /// <param name="objectName">Object Name</param>
        /// <param name="headerMap">headerMap</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="body">request body</param>
        /// <param name="resourcePath">query string</param>
        /// <returns>A RestRequest</returns>
        /// <exception cref="BucketNotFoundException">When bucketName is invalid</exception>
        internal async Task <RestRequest> CreateRequest(Method method, string bucketName      = null, string objectName = null,
                                                        Dictionary <string, string> headerMap = null,
                                                        string contentType = "application/octet-stream",
                                                        object body        = null, string resourcePath = null)
        {
            string region = string.Empty;

            if (bucketName != null)
            {
                utils.ValidateBucketName(bucketName);
                region = await GetRegion(bucketName).ConfigureAwait(false);
            }

            if (objectName != null)
            {
                utils.ValidateObjectName(objectName);
            }

            // Start with user specified endpoint
            string host = this.BaseUrl;

            this.restClient.Authenticator = new V4Authenticator(this.Secure, this.AccessKey, this.SecretKey, region: string.IsNullOrEmpty(this.Region)?region:this.Region, sessionToken: this.SessionToken);

            // This section reconstructs the url with scheme followed by location specific endpoint (s3.region.amazonaws.com)
            // or Virtual Host styled endpoint (bucketname.s3.region.amazonaws.com) for Amazon requests.
            string resource     = string.Empty;
            bool   usePathStyle = false;

            if (bucketName != null)
            {
                if (s3utils.IsAmazonEndPoint(this.BaseUrl))
                {
                    usePathStyle = false;

                    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 != null && bucketName.Contains(".") && this.Secure)
                    {
                        // use path style where '.' in bucketName causes SSL certificate validation error
                        usePathStyle = true;
                    }

                    if (usePathStyle)
                    {
                        resource += utils.UrlEncode(bucketName) + "/";
                    }
                }
                else
                {
                    resource += utils.UrlEncode(bucketName) + "/";
                }
            }

            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, bucketName, region, usePathStyle);

            SetTargetURL(requestUrl);

            if (objectName != null)
            {
                resource += utils.EncodePath(objectName);
            }

            // Append query string passed in
            if (resourcePath != null)
            {
                resource += resourcePath;
            }

            RestRequest request = new RestRequest(resource, method);

            if (body != null)
            {
                request.AddParameter(contentType, body, RestSharp.ParameterType.RequestBody);
            }

            if (headerMap != null)
            {
                foreach (var entry in headerMap)
                {
                    request.AddHeader(entry.Key, entry.Value);
                }
            }

            return(request);
        }
Пример #11
0
        /// <summary>
        /// Constructs a RestRequest. For AWS, this function has the side-effect of overriding the baseUrl
        /// in the RestClient with region specific host path or virtual style path.
        /// </summary>
        /// <param name="method">HTTP method</param>
        /// <param name="bucketName">Bucket Name</param>
        /// <param name="objectName">Object Name</param>
        /// <param name="headerMap">headerMap</param>
        /// <param name="queryParamMap">unused queryParamMap</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="body">request body</param>
        /// <param name="resourcePath">query string</param>
        /// <returns>A RestRequest</returns>
        internal async Task <RestRequest> CreateRequest(Method method, string bucketName, string objectName = null,
                                                        Dictionary <string, string> headerMap = null,
                                                        string contentType = "application/octet-stream",
                                                        Object body        = null, string resourcePath = null, string region = null)
        {
            // Validate bucket name and object name
            if (bucketName == null && objectName == null)
            {
                throw new InvalidBucketNameException(bucketName, "null bucket name for object '" + objectName + "'");
            }
            utils.validateBucketName(bucketName);
            if (objectName != null)
            {
                utils.validateObjectName(objectName);
            }

            // Start with user specified endpoint
            string host = this.BaseUrl;

            // Fetch correct region for bucket
            if (region == null)
            {
                if (!BucketRegionCache.Instance.Exists(bucketName))
                {
                    region = await BucketRegionCache.Instance.Update(this, bucketName);
                }
                else
                {
                    region = BucketRegionCache.Instance.Region(bucketName);
                }
            }


            // This section reconstructs the url with scheme followed by location specific endpoint( s3.region.amazonaws.com)
            // or Virtual Host styled endpoint (bucketname.s3.region.amazonaws.com) for Amazon requests.
            string resource     = "";
            bool   usePathStyle = false;

            if (s3utils.IsAmazonEndPoint(this.BaseUrl))
            {
                usePathStyle = false;

                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;
                }

                if (usePathStyle)
                {
                    resource += utils.UrlEncode(bucketName) + "/";
                }
            }
            else
            {
                resource += utils.UrlEncode(bucketName) + "/";
            }

            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, bucketName, region, usePathStyle);

            SetTargetURL(requestUrl);

            if (objectName != null)
            {
                resource += utils.EncodePath(objectName);
            }

            // Append query string passed in
            if (resourcePath != null)
            {
                resource += resourcePath;
            }

            RestRequest request = new RestRequest(resource, method);

            if (body != null)
            {
                request.AddParameter(contentType, body, RestSharp.ParameterType.RequestBody);
            }

            if (headerMap != null)
            {
                foreach (var entry in headerMap)
                {
                    request.AddHeader(entry.Key, entry.Value);
                }
            }

            return(request);
        }
Пример #12
0
        /// <summary>
        /// Constructs a HttpRequestMessage builder. For AWS, this function has the side-effect of overriding the baseUrl
        /// in the HttpClient with region specific host path or virtual style path.
        /// </summary>
        /// <param name="method">HTTP method</param>
        /// <param name="bucketName">Bucket Name</param>
        /// <param name="objectName">Object Name</param>
        /// <param name="headerMap">headerMap</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="body">request body</param>
        /// <param name="resourcePath">query string</param>
        /// <returns>A HttpRequestMessage builder</returns>
        internal async Task <HttpRequestMessageBuilder> CreateRequest(
            HttpMethod method,
            string bucketName = null,
            string objectName = null,
            Dictionary <string, string> headerMap = null,
            string contentType = "application/octet-stream",
            byte[] body        = null, string resourcePath = null)
        {
            string region = string.Empty;

            if (bucketName != null)
            {
                utils.ValidateBucketName(bucketName);
                // Fetch correct region for bucket
                region = await GetRegion(bucketName).ConfigureAwait(false);
            }

            if (objectName != null)
            {
                utils.ValidateObjectName(objectName);
            }

            // This section reconstructs the url with scheme followed by location specific endpoint (s3.region.amazonaws.com)
            // or Virtual Host styled endpoint (bucketname.s3.region.amazonaws.com) for Amazon requests.
            string resource     = string.Empty;
            bool   usePathStyle = false;

            if (bucketName != null)
            {
                if (s3utils.IsAmazonEndPoint(this.BaseUrl))
                {
                    usePathStyle = false;

                    if (method == HttpMethod.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 != null && bucketName.Contains(".") && this.Secure)
                    {
                        // use path style where '.' in bucketName causes SSL certificate validation error
                        usePathStyle = true;
                    }

                    if (usePathStyle)
                    {
                        resource += utils.UrlEncode(bucketName) + "/";
                    }
                }
                else
                {
                    resource += utils.UrlEncode(bucketName) + "/";
                }
            }

            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, bucketName, region, usePathStyle);

            if (objectName != null)
            {
                resource += utils.EncodePath(objectName);
            }

            // Append query string passed in
            if (resourcePath != null)
            {
                resource += resourcePath;
            }

            var messageBuilder = new HttpRequestMessageBuilder(method, requestUrl, resource);

            if (body != null)
            {
                messageBuilder.SetBody(body);
            }

            if (headerMap != null)
            {
                foreach (var entry in headerMap)
                {
                    messageBuilder.AddHeaderParameter(entry.Key, entry.Value);
                }
            }

            return(messageBuilder);
        }
Пример #13
0
        /// <summary>
        /// Constructs an HttpRequestMessage builder. For AWS, this function has the side-effect of overriding the baseUrl
        /// in the HttpClient with region specific host path or virtual style path.
        /// </summary>
        /// <param name="method">HTTP method</param>
        /// <param name="bucketName">Bucket Name</param>
        /// <param name="objectName">Object Name</param>
        /// <param name="headerMap">headerMap</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="body">request body</param>
        /// <param name="resourcePath">query string</param>
        /// <returns>A HttpRequestMessage builder</returns>
        /// <exception cref="BucketNotFoundException">When bucketName is invalid</exception>
        internal async Task <HttpRequestMessageBuilder> CreateRequest(
            HttpMethod method,
            string bucketName = null,
            string objectName = null,
            Dictionary <string, string> headerMap = null,
            string contentType  = "application/octet-stream",
            byte[] body         = null,
            string resourcePath = null)
        {
            string region = string.Empty;

            if (bucketName != null)
            {
                utils.ValidateBucketName(bucketName);
                // Fetch correct region for bucket if this is not a bucket creation
                if (!string.IsNullOrEmpty(objectName) && method != HttpMethod.Put)
                {
                    region = await GetRegion(bucketName).ConfigureAwait(false);
                }
            }

            if (objectName != null)
            {
                utils.ValidateObjectName(objectName);
            }

            if (this.Provider != null)
            {
                bool isAWSEnvProvider = (this.Provider is AWSEnvironmentProvider) ||
                                        (this.Provider is ChainedProvider ch &&
                                         ch.CurrentProvider is AWSEnvironmentProvider);

                bool isIAMAWSProvider = (this.Provider is IAMAWSProvider) ||
                                        (this.Provider is ChainedProvider chained && chained.CurrentProvider is AWSEnvironmentProvider);

                AccessCredentials creds = null;

                if (isAWSEnvProvider)
                {
                    var aWSEnvProvider = (AWSEnvironmentProvider)this.Provider;
                    creds = await aWSEnvProvider.GetCredentialsAsync();
                }
                else if (isIAMAWSProvider)
                {
                    var iamAWSProvider = (IAMAWSProvider)this.Provider;
                    creds = iamAWSProvider.Credentials;
                }
                else
                {
                    creds = await this.Provider.GetCredentialsAsync();
                }
                if (creds != null)
                {
                    this.AccessKey = creds.AccessKey;
                    this.SecretKey = creds.SecretKey;
                }
            }

            // This section reconstructs the url with scheme followed by location specific endpoint (s3.region.amazonaws.com)
            // or Virtual Host styled endpoint (bucketname.s3.region.amazonaws.com) for Amazon requests.
            string resource     = string.Empty;
            bool   usePathStyle = false;

            if (bucketName != null)
            {
                if (s3utils.IsAmazonEndPoint(this.BaseUrl))
                {
                    if (method == HttpMethod.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 != null && bucketName.Contains(".") && this.Secure)
                    {
                        // use path style where '.' in bucketName causes SSL certificate validation error
                        usePathStyle = true;
                    }

                    if (usePathStyle)
                    {
                        resource += utils.UrlEncode(bucketName) + "/";
                    }
                }
            }

            // Set Target URL
            Uri requestUrl = RequestUtil.MakeTargetURL(this.BaseUrl, this.Secure, bucketName, region, usePathStyle);

            if (objectName != null)
            {
                resource += utils.EncodePath(objectName);
            }

            // Append query string passed in
            if (resourcePath != null)
            {
                resource += resourcePath;
            }


            HttpRequestMessageBuilder messageBuilder;

            if (!string.IsNullOrEmpty(resource))
            {
                messageBuilder = new HttpRequestMessageBuilder(method, requestUrl, resource);
            }
            else
            {
                messageBuilder = new HttpRequestMessageBuilder(method, requestUrl);
            }
            if (body != null)
            {
                messageBuilder.SetBody(body);
                messageBuilder.AddOrUpdateHeaderParameter("Content-Type", contentType);
            }

            if (headerMap != null)
            {
                if (headerMap.ContainsKey(messageBuilder.ContentTypeKey) &&
                    (!string.IsNullOrEmpty(headerMap[messageBuilder.ContentTypeKey])))
                {
                    headerMap[messageBuilder.ContentTypeKey] = contentType;
                }
                foreach (var entry in headerMap)
                {
                    messageBuilder.AddOrUpdateHeaderParameter(entry.Key, entry.Value);
                }
            }

            return(messageBuilder);
        }