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
};
}