private static async Task <HttpResponseMessage> GetHttpRequestResponseAsync(
            HttpClient httpClient, string method, string url,
            HttpContent content, IDictionary <string, string> headers,
            Options options, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Only POST, PUT, PATCH and DELETE can have content, otherwise the HttpClient will fail
            var isContentAllowed = Enum.TryParse(method, ignoreCase: true, result: out SendMethod _);

            using (var request = new HttpRequestMessage(new HttpMethod(method), new Uri(url))
            {
                Content = isContentAllowed ? content : null,
            })
            {
                //Clear default headers
                content.Headers.Clear();
                foreach (var header in headers)
                {
                    var requestHeaderAddedSuccessfully = request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                    if (!requestHeaderAddedSuccessfully && request.Content != null)
                    {
                        //Could not add to request headers try to add to content headers
                        // this check is probably not needed anymore as the new HttpClient does not seem fail on malformed headers
                        var contentHeaderAddedSuccessfully = content.Headers.TryAddWithoutValidation(header.Key, header.Value);
                        if (!contentHeaderAddedSuccessfully)
                        {
                            Trace.TraceWarning($"Could not add header {header.Key}:{header.Value}");
                        }
                    }
                }

                var credentials = new ImmutableCredentials(options.AWSConnectionInfo.AccessKey, options.AWSConnectionInfo.SecretKey, null);

                string regionName  = options.AWSConnectionInfo.Region.ToCodeString();
                string serviceName = options.AWSConnectionInfo.ServiceName;

                HttpResponseMessage response;
                try
                {
                    response = await httpClient.SendAsync(request, cancellationToken, regionName, serviceName, credentials).ConfigureAwait(false);
                }
                catch (TaskCanceledException canceledException)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        // Cancellation is from outside -> Just throw
                        throw;
                    }

                    // Cancellation is from inside of the request, mostly likely a timeout
                    throw new Exception("HttpRequest was canceled, most likely due to a timeout.", canceledException);
                }

                // this check is probably not needed anymore as the new HttpClient does not fail on invalid charsets
                if (options.AllowInvalidResponseContentTypeCharSet && response.Content.Headers?.ContentType != null)
                {
                    response.Content.Headers.ContentType.CharSet = null;
                }

                return(response);
            }
        }
        /// <summary>
        /// Generic http request task that signs the request using AWS Signature Version 4. Uses 3rd party library AwsSignatureVersion4 to perform the signing.
        /// Documentation: https://github.com/CommunityHiQ/Frends.Community.AWS.Http
        /// </summary>
        /// <param name="input">Input parameters</param>
        /// <param name="options">AWS authentication and optional parameters</param>
        /// <param name="cancellationToken"></param>
        /// <returns>Object with the following properties: string Body, Dictionary(string,string) Headers. int StatusCode</returns>
        public static async Task <object> HttpRequestWithAWSSigV4([PropertyTab] Input input, [PropertyTab] Options options, CancellationToken cancellationToken)
        {
            var httpClient = GetHttpClientForOptions(options);
            var headers    = GetHeaderDictionary(input.Headers);

            using (var content = GetContent(input, headers))
            {
                using (var responseMessage = await GetHttpRequestResponseAsync(
                           httpClient,
                           input.Method.ToString(),
                           input.Url,
                           content,
                           headers,
                           options,
                           cancellationToken)
                                             .ConfigureAwait(false))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var response = new HttpResponse()
                    {
                        Body       = responseMessage.Content != null ? await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false) : null,
                        StatusCode = (int)responseMessage.StatusCode,
                        Headers    = GetResponseHeaderDictionary(responseMessage.Headers, responseMessage.Content?.Headers)
                    };

                    if (!responseMessage.IsSuccessStatusCode && options.ThrowExceptionOnErrorResponse)
                    {
                        throw new WebException(
                                  $"Request to '{input.Url}' failed with status code {(int)responseMessage.StatusCode}. Response body: {response.Body}");
                    }

                    return(response);
                }
            }
        }