public static ApiGatewayEmulatorProcess Startup()

in Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs [43:165]


    public static ApiGatewayEmulatorProcess Startup(RunCommandSettings settings, CancellationToken cancellationToken = default)
    {
        if (settings.ApiGatewayEmulatorMode is null)
        {
            throw new InvalidApiGatewayModeException("The API Gateway emulator mode was not provided.");
        }

        var builder = WebApplication.CreateBuilder();

        Utils.ConfigureWebApplicationBuilder(builder);

        builder.Services.AddApiGatewayEmulatorServices();
        builder.Services.AddSingleton<ILambdaClient, LambdaClient>();

        var serviceUrl = $"http://{settings.LambdaEmulatorHost}:{settings.ApiGatewayEmulatorPort}";
        builder.WebHost.UseUrls(serviceUrl);
        builder.WebHost.SuppressStatusMessages(true);

        builder.Services.AddHealthChecks();

        var app = builder.Build();

        app.MapHealthChecks("/__lambda_test_tool_apigateway_health__");

        app.Lifetime.ApplicationStarted.Register(() =>
        {
            app.Logger.LogInformation("The API Gateway Emulator is available at: {ServiceUrl}", serviceUrl);
        });

        app.Map("/{**catchAll}", async (HttpContext context, IApiGatewayRouteConfigService routeConfigService, ILambdaClient lambdaClient) =>
        {
            var routeConfig = routeConfigService.GetRouteConfig(context.Request.Method, context.Request.Path);
            if (routeConfig == null)
            {
                app.Logger.LogInformation("Unable to find a configured Lambda route for the specified method and path: {Method} {Path}",
                    context.Request.Method, context.Request.Path);
                await ApiGatewayResults.RouteNotFoundAsync(context, (ApiGatewayEmulatorMode)settings.ApiGatewayEmulatorMode);
                return;
            }

            // Convert ASP.NET Core request to API Gateway event object
            var lambdaRequestStream = new MemoryStream();
            if (settings.ApiGatewayEmulatorMode.Equals(ApiGatewayEmulatorMode.HttpV2))
            {
                var lambdaRequest = await context.ToApiGatewayHttpV2Request(routeConfig);
                JsonSerializer.Serialize<APIGatewayHttpApiV2ProxyRequest>(lambdaRequestStream, lambdaRequest, _jsonSerializationOptions);
            }
            else
            {
                var lambdaRequest = await context.ToApiGatewayRequest(routeConfig, settings.ApiGatewayEmulatorMode.Value);
                JsonSerializer.Serialize<APIGatewayProxyRequest>(lambdaRequestStream, lambdaRequest, _jsonSerializationOptions);
            }
            lambdaRequestStream.Position = 0;

            // Invoke Lamdba function via the test tool's Lambda Runtime API.
            var invokeRequest = new InvokeRequest
            {
                FunctionName = routeConfig.LambdaResourceName,
                InvocationType = InvocationType.RequestResponse,
                PayloadStream = lambdaRequestStream
            };

            try
            {
                var endpoint = routeConfig.Endpoint ?? $"http://{settings.LambdaEmulatorHost}:{settings.LambdaEmulatorPort}";
                var response = await lambdaClient.InvokeAsync(invokeRequest, endpoint);

                if (response.FunctionError == null) // response is successful
                {
                    if (settings.ApiGatewayEmulatorMode.Equals(ApiGatewayEmulatorMode.HttpV2))
                    {
                        var lambdaResponse = response.ToApiGatewayHttpApiV2ProxyResponse();
                        await lambdaResponse.ToHttpResponseAsync(context);
                    }
                    else
                    {
                        var lambdaResponse = response.ToApiGatewayProxyResponse(settings.ApiGatewayEmulatorMode.Value);
                        await lambdaResponse.ToHttpResponseAsync(context, settings.ApiGatewayEmulatorMode.Value);
                    }
                }
                else
                {
                    // For errors that happen within the function they still come back as 200 status code (they dont throw exception) but have FunctionError populated.
                    // Api gateway just displays them as an internal server error, so we convert them to the correct error response here.
                    if (settings.ApiGatewayEmulatorMode.Equals(ApiGatewayEmulatorMode.HttpV2))
                    {
                        var lambdaResponse = InvokeResponseExtensions.ToHttpApiV2ErrorResponse();
                        await lambdaResponse.ToHttpResponseAsync(context);
                    }
                    else
                    {
                        var lambdaResponse = InvokeResponseExtensions.ToApiGatewayErrorResponse(settings.ApiGatewayEmulatorMode.Value);
                        await lambdaResponse.ToHttpResponseAsync(context, settings.ApiGatewayEmulatorMode.Value);
                    }
                }
            }
            catch (AmazonLambdaException e)
            {
                if (e.ErrorCode == Exceptions.RequestEntityTooLargeException)
                {
                    if (settings.ApiGatewayEmulatorMode.Equals(ApiGatewayEmulatorMode.HttpV2))
                    {
                        var lambdaResponse = InvokeResponseExtensions.ToHttpApiV2RequestTooLargeResponse();
                        await lambdaResponse.ToHttpResponseAsync(context);
                    }
                    else
                    {
                        var lambdaResponse = InvokeResponseExtensions.ToHttpApiRequestTooLargeResponse(settings.ApiGatewayEmulatorMode.Value);
                        await lambdaResponse.ToHttpResponseAsync(context, settings.ApiGatewayEmulatorMode.Value);
                    }
                }
            }
        });

        var runTask = app.RunAsync(cancellationToken);

        return new ApiGatewayEmulatorProcess
        {
            Services = app.Services,
            RunningTask = runTask,
            ServiceUrl = serviceUrl
        };
    }