Example #1
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);
        }
Example #2
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);
        }
Example #3
0
 internal virtual HttpRequestMessageBuilder BuildRequest(HttpRequestMessageBuilder requestMessageBuilder)
 {
     return(requestMessageBuilder);
 }
 internal override HttpRequestMessageBuilder BuildRequest(HttpRequestMessageBuilder requestMessageBuilder)
 {
     requestMessageBuilder.AddQueryParameter("lifecycle", "");
     return(requestMessageBuilder);
 }
 internal override HttpRequestMessageBuilder BuildRequest(HttpRequestMessageBuilder requestMessageBuilder)
 {
     requestMessageBuilder.AddQueryParameter("replication", "");
     return(requestMessageBuilder);
 }
 internal override HttpRequestMessageBuilder BuildRequest(HttpRequestMessageBuilder requestMessageBuilder)
 {
     requestMessageBuilder.AddQueryParameter("object-lock", "");
     return(requestMessageBuilder);
 }
Example #7
0
 /// <summary>
 /// Set 'Host' http header.
 /// </summary>
 /// <param name="requestBuilder">Instantiated requestBuilder object</param>
 /// <param name="hostUrl">Host url</param>
 private void SetHostHeader(HttpRequestMessageBuilder requestBuilder, string hostUrl)
 {
     requestBuilder.AddHeaderParameter("Host", hostUrl);
 }
Example #8
0
 /// <summary>
 /// Sets 'x-amz-date' http header.
 /// </summary>
 /// <param name="requestBuilder">Instantiated requestBuilder object</param>
 /// <param name="signingDate">Date for signature to be signed</param>
 private void SetDateHeader(HttpRequestMessageBuilder requestBuilder, DateTime signingDate)
 {
     requestBuilder.AddHeaderParameter("x-amz-date", signingDate.ToString("yyyyMMddTHHmmssZ"));
 }
Example #9
0
        /// <summary>
        /// Presigns any input client object with a requested expiry.
        /// </summary>
        /// <param name="requestBuilder">Instantiated requestBuilder</param>
        /// <param name="expires">Expiration in seconds</param>
        /// <param name="region">Region of storage</param>
        /// <param name="sessionToken">Value for session token</param>
        /// <param name="reqDate"> Optional requestBuilder date and time in UTC</param>
        /// <returns>Presigned url</returns>
        internal string PresignURL(HttpRequestMessageBuilder requestBuilder, int expires, string region = "", string sessionToken = "", DateTime?reqDate = null)
        {
            var signingDate = reqDate ?? DateTime.UtcNow;

            if (string.IsNullOrWhiteSpace(region))
            {
                region = this.GetRegion(requestBuilder.RequestUri.Host);
            }

            Uri    requestUri   = requestBuilder.RequestUri;
            string requestQuery = requestUri.Query;

            SortedDictionary <string, string> headersToSign = this.GetHeadersToSign(requestBuilder);

            if (!string.IsNullOrEmpty(sessionToken))
            {
                headersToSign["X-Amz-Security-Token"] = sessionToken;
            }

            if (requestQuery.Length > 0)
            {
                requestQuery += "&";
            }
            requestQuery += "X-Amz-Algorithm=AWS4-HMAC-SHA256&";
            requestQuery += "X-Amz-Credential="
                            + Uri.EscapeDataString(this.accessKey + "/" + this.GetScope(region, signingDate))
                            + "&";
            requestQuery += "X-Amz-Date="
                            + signingDate.ToString("yyyyMMddTHHmmssZ")
                            + "&";
            requestQuery += "X-Amz-Expires="
                            + expires
                            + "&";
            requestQuery += "X-Amz-SignedHeaders=host";

            var presignUri = new UriBuilder(requestUri)
            {
                Query = requestQuery
            }.Uri;
            string canonicalRequest = this.GetPresignCanonicalRequest(requestBuilder.Method, presignUri, headersToSign);
            string headers          = string.Concat(headersToSign.Select(p => $"&{p.Key}={utils.UrlEncode(p.Value)}"));

            byte[] canonicalRequestBytes = System.Text.Encoding.UTF8.GetBytes(canonicalRequest);
            string canonicalRequestHash  = this.BytesToHex(ComputeSha256(canonicalRequestBytes));
            string stringToSign          = this.GetStringToSign(region, signingDate, canonicalRequestHash);

            byte[] signingKey        = this.GenerateSigningKey(region, signingDate);
            byte[] stringToSignBytes = System.Text.Encoding.UTF8.GetBytes(stringToSign);
            byte[] signatureBytes    = this.SignHmac(signingKey, stringToSignBytes);
            string signature         = this.BytesToHex(signatureBytes);

            // Return presigned url.
            var signedUri = new UriBuilder(presignUri)
            {
                Query = $"{requestQuery}{headers}&X-Amz-Signature={signature}"
            };

            if (signedUri.Uri.IsDefaultPort)
            {
                signedUri.Port = -1;
            }
            return(signedUri.ToString());
        }
Example #10
0
        /// <summary>
        /// private helper method to remove list of objects from bucket
        /// </summary>
        /// <param name="args">GetObjectArgs Arguments Object encapsulates information like - bucket name, object name etc </param>
        /// <param name="objectStat"> ObjectStat object encapsulates information like - object name, size, etag etc, represents Object Information </param>
        /// <param name="cb"> Action object of type Stream, callback to send Object contents, if assigned </param>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        private async Task getObjectStreamAsync(GetObjectArgs args, ObjectStat objectStat, Action <Stream> cb, CancellationToken cancellationToken = default(CancellationToken))
        {
            HttpRequestMessageBuilder requestMessageBuilder = await CreateRequest(args).ConfigureAwait(false);

            await ExecuteTaskAsync(this.NoErrorHandlers, requestMessageBuilder, cancellationToken).ConfigureAwait(false);
        }