public static async Task ToApiGatewayHttpV2Request()

in Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/HttpContextExtensions.cs [23:120]


    public static async Task<APIGatewayHttpApiV2ProxyRequest> ToApiGatewayHttpV2Request(
        this HttpContext context,
        ApiGatewayRouteConfig apiGatewayRouteConfig)
    {
        var request = context.Request;
        var currentTime = DateTimeOffset.UtcNow;
        var body = await HttpRequestUtility.ReadRequestBody(request);
        var contentLength = HttpRequestUtility.CalculateContentLength(request, body);

        var pathParameters = RouteTemplateUtility.ExtractPathParameters(apiGatewayRouteConfig.Path, request.Path);

        // Format 2.0 doesn't have multiValueHeaders or multiValueQueryStringParameters fields. Duplicate headers are combined with commas and included in the headers field.
        // 2.0 also lowercases all header keys
        var (_, allHeaders) = HttpRequestUtility.ExtractHeaders(request.Headers, true);
        var headers = allHeaders.ToDictionary(
            kvp => kvp.Key,
            kvp => string.Join(", ", kvp.Value)
        );

        // Duplicate query strings are combined with commas and included in the queryStringParameters field.
        var (_, allQueryParams) = HttpRequestUtility.ExtractQueryStringParameters(request.Query);
        var queryStringParameters = allQueryParams.ToDictionary(
            kvp => kvp.Key,
            kvp => string.Join(",", kvp.Value)
        );

        string userAgent = request.Headers.UserAgent.ToString();

        if (!headers.ContainsKey("content-length"))
        {
            headers["content-length"] = contentLength.ToString();
        }

        if (!headers.ContainsKey("content-type"))
        {
            headers["content-type"] = "text/plain; charset=utf-8";
        }

        var httpApiV2ProxyRequest = new APIGatewayHttpApiV2ProxyRequest
        {
            RouteKey = $"{request.Method} {apiGatewayRouteConfig.Path}",
            RawPath = request.Path.Value, // this should be decoded value
            Body = body,
            IsBase64Encoded = false,
            RequestContext = new ProxyRequestContext
            {
                Http = new HttpDescription
                {
                    Method = request.Method,
                    Path = request.Path.Value, // this should be decoded value
                    Protocol = !string.IsNullOrEmpty(request.Protocol) ? request.Protocol : "HTTP/1.1", // defaults to http 1.1 if not provided
                    UserAgent = userAgent
                },
                Time = currentTime.ToString("dd/MMM/yyyy:HH:mm:ss") + " +0000",
                TimeEpoch = currentTime.ToUnixTimeMilliseconds(),
                RequestId = HttpRequestUtility.GenerateRequestId(),
                RouteKey = $"{request.Method} {apiGatewayRouteConfig.Path}",
            },
            Version = "2.0"
        };

        if (request.Cookies.Any())
        {
            httpApiV2ProxyRequest.Cookies = request.Cookies.Select(c => $"{c.Key}={c.Value}").ToArray();
        }

        if (headers.Any())
        {
            httpApiV2ProxyRequest.Headers = headers;
        }

        httpApiV2ProxyRequest.RawQueryString = string.Empty; // default is empty string

        if (queryStringParameters.Any())
        {
            // this should be decoded value
            httpApiV2ProxyRequest.QueryStringParameters = queryStringParameters;

            // this should be the url encoded value and not include the "?"
            // e.g. key=%2b%2b%2b
            httpApiV2ProxyRequest.RawQueryString = HttpUtility.UrlPathEncode(request.QueryString.Value?.Substring(1));

        }

        if (pathParameters.Any())
        {
            // this should be decoded value
            httpApiV2ProxyRequest.PathParameters = pathParameters;
        }

        if (HttpRequestUtility.IsBinaryContent(request.ContentType))
        {
            // we already converted it when we read the body so we dont need to re-convert it
            httpApiV2ProxyRequest.IsBase64Encoded = true;
        }

        return httpApiV2ProxyRequest;
    }