/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Globalization; using Amazon.Util; namespace Amazon.Runtime.Internal { /// /// This handler marshalls the request before calling invoking the next handler. /// public class Marshaller : PipelineHandler { /// /// Calls pre invoke logic before calling the next handler /// in the pipeline. /// /// The execution context which contains both the /// requests and response context. public override void InvokeSync(IExecutionContext executionContext) { PreInvoke(executionContext); base.InvokeSync(executionContext); } #if AWS_ASYNC_API /// /// Calls pre invoke logic before calling the next handler /// in the pipeline. /// /// The response type for the current request. /// The execution context, it contains the /// request and response context. /// A task that represents the asynchronous operation. public override System.Threading.Tasks.Task InvokeAsync(IExecutionContext executionContext) { PreInvoke(executionContext); return base.InvokeAsync(executionContext); } #elif AWS_APM_API /// /// Calls pre invoke logic before calling the next handler /// in the pipeline. /// /// The execution context which contains both the /// requests and response context. /// IAsyncResult which represent an async operation. public override IAsyncResult InvokeAsync(IAsyncExecutionContext executionContext) { PreInvoke(ExecutionContext.CreateFromAsyncContext(executionContext)); return base.InvokeAsync(executionContext); } #endif /// /// Marshalls the request before calling invoking the next handler. /// /// The execution context, it contains the /// request and response context. protected static void PreInvoke(IExecutionContext executionContext) { var requestContext = executionContext.RequestContext; requestContext.Request = requestContext.Marshaller.Marshall(requestContext.OriginalRequest); requestContext.Request.AuthenticationRegion = requestContext.ClientConfig.AuthenticationRegion; var userAgent = $"{requestContext.ClientConfig.UserAgent} " + $"{(executionContext.RequestContext.IsAsync ? "ClientAsync" : "ClientSync")}{requestContext.OriginalRequest.UserAgentAddition}"; if(requestContext.ClientConfig.UseAlternateUserAgentHeader) { requestContext.Request.Headers[HeaderKeys.XAmzUserAgentHeader] = userAgent; } else { requestContext.Request.Headers[HeaderKeys.UserAgentHeader] = userAgent; } #if NETSTANDARD var method = requestContext.Request.HttpMethod.ToUpperInvariant(); #else var method = requestContext.Request.HttpMethod.ToUpper(CultureInfo.InvariantCulture); #endif if (method != "GET" && method != "DELETE" && method != "HEAD") { if (!requestContext.Request.Headers.ContainsKey(HeaderKeys.ContentTypeHeader)) { if (requestContext.Request.UseQueryString) requestContext.Request.Headers[HeaderKeys.ContentTypeHeader] = "application/x-amz-json-1.0"; else requestContext.Request.Headers[HeaderKeys.ContentTypeHeader] = AWSSDKUtils.UrlEncodedContent; } } SetRecursionDetectionHeader(requestContext.Request.Headers); } /// /// Sets the X-Amzn-Trace-Id header for recursion detection within Lambda workloads. /// /// Current request headers before marshalling. private static void SetRecursionDetectionHeader(IDictionary headers) { if (!headers.ContainsKey(HeaderKeys.XAmznTraceIdHeader)) { var lambdaFunctionName = Environment.GetEnvironmentVariable(EnvironmentVariables.AWS_LAMBDA_FUNCTION_NAME); var amznTraceId = Environment.GetEnvironmentVariable(EnvironmentVariables._X_AMZN_TRACE_ID); if (!string.IsNullOrEmpty(lambdaFunctionName) && !string.IsNullOrEmpty(amznTraceId)) { headers[HeaderKeys.XAmznTraceIdHeader] = AWSSDKUtils.EncodeTraceIdHeaderValue(amznTraceId); } } } } }