protected override void MarshallRequest()

in Libraries/src/Amazon.Lambda.AspNetCoreServer/ApplicationLoadBalancerFunction.cs [57:144]


        protected override void MarshallRequest(InvokeFeatures features, ApplicationLoadBalancerRequest lambdaRequest, ILambdaContext lambdaContext)
        {
            // Call consumers customize method in case they want to change how API Gateway's request
            // was marshalled into ASP.NET Core request.
            PostMarshallHttpAuthenticationFeature(features, lambdaRequest, lambdaContext);

            // Request coming from Application Load Balancer will always send the headers X-Amzn-Trace-Id, X-Forwarded-For, X-Forwarded-Port, and X-Forwarded-Proto.
            // So this will only happen when writing tests with incomplete sample requests.
            if (lambdaRequest.Headers == null && lambdaRequest.MultiValueHeaders == null)
            {
                throw new Exception("Unable to determine header mode, single or multi value, because both Headers and MultiValueHeaders are null.");
            }

            if (lambdaRequest.RequestContext?.Elb?.TargetGroupArn == null)
            {
                _logger.LogWarning($"Request does not contain ELB information but is derived from {nameof(ApplicationLoadBalancerFunction)}.");
            }

            // Look to see if the request is using mutli value headers or not. This is important when
            // marshalling the response to know whether to fill in the the Headers or MultiValueHeaders collection.
            // Since a Lambda function compute environment is only one processing one event at a time it is safe to store
            // this as a member variable.
            this._multiHeaderValuesEnabled = lambdaRequest.MultiValueHeaders != null;

            {
                var requestFeatures = (IHttpRequestFeature)features;
                requestFeatures.Scheme = GetSingleHeaderValue(lambdaRequest, "x-forwarded-proto");
                requestFeatures.Method = lambdaRequest.HttpMethod;

                var rawPath = lambdaRequest.Path;
                var rawQueryString = Utilities.CreateQueryStringParameters(
                    lambdaRequest.QueryStringParameters, lambdaRequest.MultiValueQueryStringParameters, false);

                requestFeatures.RawTarget = rawPath + rawQueryString;
                requestFeatures.QueryString = rawQueryString;
                requestFeatures.Path = Utilities.DecodeResourcePath(rawPath);

                Utilities.SetHeadersCollection(requestFeatures.Headers, lambdaRequest.Headers, lambdaRequest.MultiValueHeaders);

                if (!string.IsNullOrEmpty(lambdaRequest.Body))
                {
                    requestFeatures.Body = Utilities.ConvertLambdaRequestBodyToAspNetCoreBody(lambdaRequest.Body, lambdaRequest.IsBase64Encoded);
                }

                // Make sure the content-length header is set if header was not present.
                const string contentLengthHeaderName = "Content-Length";
                if (!requestFeatures.Headers.ContainsKey(contentLengthHeaderName))
                {
                    requestFeatures.Headers[contentLengthHeaderName] = requestFeatures.Body == null ? "0" : requestFeatures.Body.Length.ToString(CultureInfo.InvariantCulture);
                }

                var userAgent = GetSingleHeaderValue(lambdaRequest, "user-agent");
                if (userAgent != null && userAgent.StartsWith("ELB-HealthChecker/", StringComparison.OrdinalIgnoreCase))
                {
                    requestFeatures.Scheme = "https";
                    requestFeatures.Headers["host"] = "localhost";
                    requestFeatures.Headers["x-forwarded-port"] = "443";
                    requestFeatures.Headers["x-forwarded-for"] = "127.0.0.1";
                }

                // Call consumers customize method in case they want to change how API Gateway's request
                // was marshalled into ASP.NET Core request.
                PostMarshallRequestFeature(requestFeatures, lambdaRequest, lambdaContext);
            }


            {
                // set up connection features
                var connectionFeatures = (IHttpConnectionFeature)features;

                var remoteIpAddressStr = GetSingleHeaderValue(lambdaRequest, "x-forwarded-for");
                if (!string.IsNullOrEmpty(remoteIpAddressStr) &&
                    IPAddress.TryParse(remoteIpAddressStr, out var remoteIpAddress))
                {
                    connectionFeatures.RemoteIpAddress = remoteIpAddress;
                }

                var remotePort = GetSingleHeaderValue(lambdaRequest, "x-forwarded-port");
                if (!string.IsNullOrEmpty(remotePort))
                {
                    connectionFeatures.RemotePort = int.Parse(remotePort, CultureInfo.InvariantCulture);
                }

                // Call consumers customize method in case they want to change how API Gateway's request
                // was marshalled into ASP.NET Core request.
                PostMarshallConnectionFeature(connectionFeatures, lambdaRequest, lambdaContext);
            }
        }