Here is small terraform example how you can create serverless React app that will use AWS API Gateway which will call AWS Lambda.
API Gateway is proxying GET request to lambda. Lambda will simply return "Hello World".
Actual terraform infrastructure definition. This terraform definition include CORS configuration.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
locals { | |
function_name = "hello_world" | |
handler = "index.handler" | |
runtime = "nodejs14.x" | |
zip_file = "hello_world.zip" | |
} | |
data "archive_file" "zip" { | |
source_dir = "${path.module}/lambdas/hello-world" | |
type = "zip" | |
output_path = local.zip_file | |
} | |
resource "aws_lambda_function" "this" { | |
description = "${var.config.team}-lambda-stream-es" | |
// Function parameters we defined at the beginning | |
function_name = local.function_name | |
handler = local.handler | |
runtime = local.runtime | |
timeout = 15 | |
// Upload the .zip file Terraform created to AWS | |
filename = local.zip_file | |
source_code_hash = data.archive_file.zip.output_base64sha256 | |
// Connect our IAM resource to our lambda function in AWS | |
role = var.config.es_lambda_role_arn | |
} | |
resource "aws_apigatewayv2_api" "this" { | |
name = "${var.config.team}-${var.config.env}-lambda-gw" | |
protocol_type = "HTTP" | |
cors_configuration { | |
allow_origins = ["https://www.first.com", "https://www.second.com"] | |
allow_methods = ["GET"] | |
allow_headers = ["content-type"] | |
max_age = 300 | |
} | |
} | |
resource "aws_apigatewayv2_stage" "this" { | |
api_id = aws_apigatewayv2_api.this.id | |
name = "${var.config.team}-${var.config.env}-lambda-gw-stage" | |
auto_deploy = true | |
access_log_settings { | |
destination_arn = aws_cloudwatch_log_group.this.arn | |
format = jsonencode({ | |
requestId = "$context.requestId" | |
sourceIp = "$context.identity.sourceIp" | |
requestTime = "$context.requestTime" | |
protocol = "$context.protocol" | |
httpMethod = "$context.httpMethod" | |
resourcePath = "$context.resourcePath" | |
routeKey = "$context.routeKey" | |
status = "$context.status" | |
responseLength = "$context.responseLength" | |
integrationErrorMessage = "$context.integrationErrorMessage" | |
} | |
) | |
} | |
} | |
resource "aws_apigatewayv2_integration" "hello_world_integration" { | |
api_id = aws_apigatewayv2_api.this.id | |
integration_uri = aws_lambda_function.this.invoke_arn | |
integration_type = "AWS_PROXY" | |
integration_method = "POST" | |
} | |
resource "aws_apigatewayv2_route" "hello_world_route" { | |
api_id = aws_apigatewayv2_api.this.id | |
route_key = "GET /hello-world" | |
target = "integrations/${aws_apigatewayv2_integration.hello_world_integration.id}" | |
} | |
resource "aws_cloudwatch_log_group" "this" { | |
name = "/aws/api_gw/${aws_apigatewayv2_api.this.name}" | |
retention_in_days = 30 | |
} | |
resource "aws_lambda_permission" "api_gw" { | |
statement_id = "AllowExecutionFromAPIGateway" | |
action = "lambda:InvokeFunction" | |
function_name = aws_lambda_function.this.function_name | |
principal = "apigateway.amazonaws.com" | |
source_arn = "${aws_apigatewayv2_api.this.execution_arn}/*/*" | |
} |
Lambda which that will return "Hello World".
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// AWS lambda that call ECS service to get similar products | |
module.exports.handler = async (event) => { | |
console.log('Event: ', event); | |
let responseMessage = 'Hello, World!'; | |
return { | |
statusCode: 200, | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
message: responseMessage, | |
}), | |
} | |
} | |