/// <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); }
/// <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); }
/// <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); }
/// <summary> /// This method initializes a new RESTClient. 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."); } 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); this.uri = RequestUtil.GetEndpointURL(this.BaseUrl, this.Secure); RequestUtil.ValidateEndpoint(this.uri, this.Endpoint); // Initialize a new REST client. This uri will be modified if region specific endpoint/virtual style request // is decided upon while constructing a request for Amazon. restClient = new RestSharp.RestClient(this.uri); restClient.UserAgent = this.FullUserAgent; authenticator = new V4Authenticator(this.Secure, this.AccessKey, this.SecretKey); restClient.Authenticator = authenticator; }
/// <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); }
/// <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); }
/// <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); }
/// <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); }