Want to integrate AWS Lambda to an API endpoint? This project will walk you through the exact steps needed to attach Lambda with API Gateway to returning the caller’s public IP using a simple Python Lambda.
What We’ll Build
In this article, we have a lightweight Python function running inside AWS Lambda. The function gets triggered when a user hits an API Gateway (HTTP API) URL. Once called, it grabs the user’s public IP and current timestamp and sends that back in the response.
Example of URL provided by API Gateway:
curl https://<your-api>.execute-api.<region>.amazonaws.com/<stage>/
Output on browser upon hitting URL:
{
"timestamp": "2025-06-20T17:45:12.841111",
"ip_address": "103.xx.x.xx"
}
What’s happening behind the scenes ( Overview of request)
As a USER, you will be hitting a URL( that is provided by API Gateway ). Upon hitting the URL, the request will flow from API Gateway to AWS Lambda, which will invoke the python application.
You (the user) hit the URL provided by API Gateway.
API Gateway forwards the request to Lambda.
Lambda runs the Python code and sends back a response with your IP and the current timestamp.
The python application will take “event” metadata from the API Gateway and use that to return the sourceIP. The timestamp is returned using the datetime() function.
Python Application
Here’s the Python function we’re using
import json
import datetime
def lambda_handler(event, context):
# Fetch the IP from the API Gateway event
ip_address = event['requestContext']['http']['sourceIp']
# Get the current timestamp
timestamp = datetime.datetime.utcnow().isoformat()
response = {
'timestamp': timestamp,
'ip_address': ip_address
}
return {
'statusCode': 200,
'headers': { 'Content-Type': 'application/json' },
'body': json.dumps(response)
}
“event” Metadata from API Gateway
I believe the only component worth exploring here is:
ip_address = event['requestContext']['http']['sourceIp']
“event” is returned by API Gateway and contain some metadata that can be consumed by Lambda. This include the sourceIP field as well, that we will be using to display output on hitting URL.
Metadata in the event context of API Gateway
{
"requestContext": {
"accountId": "123456789012",
"apiId": "a1b2c3d4",
"http": {
"method": "GET",
"path": "/",
"protocol": "HTTP/1.1",
"sourceIp": "203.0.113.42",
"userAgent": "curl/7.64.1"
},
"requestId": "abc123",
"routeKey": "GET /",
"stage": "$default",
"time": "20/Jun/2025:10:45:00 +0000",
"timeEpoch": 1718877900000
}
}
Why we don’t need any layer for this Python Lambda?
The packages that we are using ( json , datetime ), are part of Python’s standard library, and AWS Lambda already includes the entire standard library for whatever runtime we’re using (like python3.12, python3.11, etc.).
Tech Stack
- Python 3.12
- AWS Lambda
- API Gateway (HTTP API)
- Terraform
- CloudWatch (for logging/debugging)
Project Structure
.
├── terraform/
│ ├── modules/
│ │ ├── iam/
│ │ │ ├── main.tf
│ │ │ └── outputs.tf
│ │ ├── lambda/
│ │ │ ├── main.tf
│ │ │ ├── variables.tf
│ │ │ └── outputs.tf
│ │ └── apigw/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── main.tf
│ ├── outputs.tf
│ └── provider.tf
├── app.py
├── .gitignore
└── README.md
CODE REPOSITORY ( follow the URL for Github Repository)
Follow the below github repository for the terraform code
https://github.com/ifaakash/whats-my-ip-lambda
Terraform Code Highlight
From terraform POV, we will need to create the components listed below:
`aws_lambda_function` → Lambda function configuration
`aws_apigatewayv2_api` → API for the end user
`aws_lambda_permission` → Ensure API GW have permission to invoke Lambda
`aws_apigatewayv2_integration` → Attach API GW with Lambda function
`aws_api_gatewayv2_route` → Define route for API GW to invoke Lambda
`aws_api_gatewayv2_stage` → Used to handle API GW in multi env( dev, stg, prod )
`aws_iam_role` and policy for Lambda execution
Why create the IAM Role?
Without IAM role, the lambda function will not be able to perform operation like writing logs to cloudwatch, read from S3 bucket etc. So, we need IAM role to allot permission to AWS Lambda.
# IAM Role for AWS Lambda to assume
resource "aws_iam_role" "lambda_exec_role" {
name = "lambda_exec_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
# Required permission for AWS lambda to perform action on other resources
resource "aws_iam_policy" "permissions" {
name = "lambda_permissions"
description = "Required IAM permission for AWS Lambda Execution"
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource" : "*"
}
]
}
)
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_exec_role.name
policy_arn = aws_iam_policy.permissions.arn
}
Permission for AWS Lambda
This will allow the API Gateway to invoke the lambda function, when the user hit the API URL.
resource "aws_lambda_permission" "allow_apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
principal = "apigateway.amazonaws.com"
function_name = var.lambda_name
}
Lambda function Configuration
This block defines the python application that need to be used by AWS Lambda and the HASH code for the application to detect changes to the ZIP file.
resource "aws_lambda_function" "lambda" {
function_name = var.function_name
role = var.lambda_exec_role_arn
description = var.description
filename = var.filename # <zip_file_name>
runtime = var.runtime_env
package_type = var.package_type
handler = var.handler # <python_file_name.lambda_function_name>
source_code_hash = filebase64sha256(var.filename)
}
Deploying It
→ Initialize using terraform init
→ Plan the changes using terraform plan
→ Apply the changes using terraform apply
→ Grab the endpoint from API Gateway
output "api_url" {
value = "${aws_apigatewayv2_api.http_api.api_endpoint}/${aws_apigatewayv2_stage.dev.name}/"
}
Test the API
curl https://<api-id>.execute-api.us-west-1.amazonaws.com/dev/
Make sure the route is GET /, not /dev or /ping unless explicitly defined.
Cleaning Up
To destroy all resources
terraform destroy
Follow for More
If this helped or sparked an idea, drop a comment, a clap, or reach out!
[Github Repo](https://github.com/ifaakash)
[My Portfolio](https://hey-its-aakash.lovable.app/)
[LinkedIn](https://www.linkedin.com/in/aakashch2/)
Top comments (1)
hey! that was very interesting! I wonder why you need AWS for this? it's to host your py code, or for another performance aspect? could you have used Azure or another random app hosting?