API Extractor can be deployed as an AWS Lambda function with Function URL for HTTP access. This serverless deployment pattern is ideal for on-demand API extraction without managing servers.
The Lambda deployment uses three key AWS services:
- Lambda Function - Runs the API extraction code in a serverless environment
- Function URL - Provides an HTTPS endpoint with IAM authentication
- S3 Files - Mounts an S3 bucket as a filesystem at
/mnt/s3for reading source code
graph TB
client["Client"] -->|"HTTP POST with IAM signature"| funcurl["Function URL<br/>https://xyz.lambda-url.region.on.aws"]
subgraph lambda["AWS Lambda Function (ARM64 Graviton)"]
handler["Lambda Handler (handler.py)<br/>- Receives HTTP request<br/>- Reads from S3 Files mount<br/>- Runs api_extractor service<br/>- Returns OpenAPI spec"]
subgraph s3files["S3 Files Filesystem Mount: /mnt/s3/lambda/"]
fastapi["my-fastapi-app/<br/>(source code)"]
flask["my-flask-app/<br/>(source code)"]
spring["my-spring-app/<br/>(source code)"]
end
handler --> s3files
end
funcurl --> handler
subgraph s3["S3 Bucket: my-code-repositories"]
s3bucket["s3://bucket/lambda/<br/>├── my-fastapi-app/<br/>├── my-flask-app/<br/>└── my-spring-app/"]
end
s3files -.->|"Backed by"| s3bucket
handler -->|"Returns OpenAPI JSON"| funcurl
funcurl -->|"200 OK"| client
style lambda fill:#fff3e0,stroke:#e65100,stroke-width:2px
style s3files fill:#e1f5ff,stroke:#01579b
style s3 fill:#e8f5e9,stroke:#1b5e20
style handler fill:#fff9c4,stroke:#f57f17
- Client sends HTTP POST to Function URL with AWS IAM signatures
- Lambda receives request via Function URL (API Gateway is not used)
- Handler reads
folderparameter from request body - Handler accesses
/mnt/s3/lambda/{folder}via S3 Files mount - Extraction service analyzes code and generates OpenAPI spec
- Lambda returns OpenAPI spec in HTTP response
AWS Lambda Function URLs provide built-in HTTPS endpoints without needing API Gateway:
- Direct HTTP Access: Each Lambda function gets a unique HTTPS URL
- IAM Authentication: Secured with AWS signature v4 (AWS_IAM auth type)
- Low Latency: Direct invocation without API Gateway overhead
- No Additional Cost: Included with Lambda pricing, no API Gateway charges
- CORS Support: Configurable cross-origin access for web clients
URL Format:
https://{url-id}.lambda-url.{region}.on.aws/
Authentication:
- All requests must be signed with AWS credentials (AWS Signature Version 4)
- Use AWS SDKs, AWS CLI, or
awscurlto sign requests automatically - IAM policies control which users/roles can invoke the function
S3 Files is an AWS service that mounts S3 buckets as POSIX filesystems in Lambda:
- Standard File APIs: Access S3 objects using
open(),Path(), and other filesystem operations - No Downloads: No need to download code from S3 before processing - read directly from mount
- Automatic Caching: S3 Files caches frequently accessed files for better performance
- Cost Efficient: Only pay for data transfer and API calls, no storage duplication
- Large Files: Supports files up to 5 TB in S3
- VPC Required: S3 Files requires Lambda to run in a VPC with private subnets
How it works:
- S3 bucket
my-code-repositoriescontains project folders inlambda/prefix - S3 Files mounts the bucket at
/mnt/s3inside the Lambda execution environment - Lambda reads code using standard filesystem operations:
/mnt/s3/lambda/my-project/ - No explicit S3 API calls needed in the Lambda handler code
Benefits over direct S3 access:
- Simpler code - use
Path()instead ofboto3.client('s3') - Better performance - automatic caching and prefetching
- Works with existing file-based tools without modification
Lambda runs in a VPC with private subnets to access S3 Files:
- Private Subnets: Lambda runs in subnets without internet access
- NAT Gateway: Not required for S3 Files access (uses VPC endpoints)
- Security Groups: Control network access to/from Lambda
- S3 VPC Endpoint: Direct S3 access without internet gateway
Lambda files are organized into two directories:
Python Lambda Code (api_extractor/lambda/):
api_extractor/lambda/
├── handler.py # Lambda entry point
└── requirements.txt # Lambda dependencies
Deployment Scripts (deployment/lambda/):
deployment/lambda/
├── config.sh # AWS configuration
├── build_lambda.sh # Build ARM64 package
├── deploy_lambda.sh # Deploy to AWS
├── setup_vpc.sh # Create VPC
├── setup_s3_files.sh # Create S3 Files filesystem
├── setup_s3_files.py # S3 Files setup helper
├── attach_s3_files.sh # Attach filesystem to Lambda
├── create_function_url.sh # Create Function URL
├── cleanup.sh # Delete Lambda function
├── cleanup_vpc.sh # Delete VPC resources
├── test_lambda_local.py # Local testing
├── test_lambda_remote.sh # Remote testing
└── QUICK_START.md # Quick reference guide
-
AWS CLI configured with credentials:
aws configure
-
Docker for building ARM64 package:
docker --version
-
IAM Permissions to create:
- Lambda functions
- IAM roles
- VPC resources
- S3 buckets
- S3 Files filesystems
Edit deployment/lambda/config.sh:
# Lambda Configuration
export FUNCTION_NAME=api-extractor
export AWS_REGION=eu-north-1
# S3 Configuration
export S3_BUCKET_NAME=my-code-repositories
# Lambda Settings
export LAMBDA_TIMEOUT=300 # seconds (5 minutes)
export LAMBDA_MEMORY=1024 # MBSet up VPC with private subnets for S3 Files:
cd deployment/lambda
./setup_vpc.shThis creates:
- VPC with CIDR 10.0.0.0/16
- 2 private subnets in different availability zones
- Security group allowing outbound HTTPS
- VPC endpoint for S3 access
The script updates config.sh with VPC IDs automatically.
# Create S3 bucket (if needed)
aws s3 mb s3://my-code-repositories
# Upload project code to S3 under lambda/ prefix
aws s3 cp --recursive ./my-fastapi-app s3://my-code-repositories/lambda/my-fastapi-app/
aws s3 cp --recursive ./my-flask-app s3://my-code-repositories/lambda/my-flask-app/
# Verify upload
aws s3 ls s3://my-code-repositories/lambda/Important: All projects must be uploaded under the lambda/ prefix in S3. The Lambda handler expects paths like /mnt/s3/lambda/{folder}/.
Create S3 Files filesystem and mount configuration:
./setup_s3_files.shThis creates:
- S3 Files filesystem
- IAM role with S3 and S3 Files permissions
- Access point linked to S3 bucket
The script updates config.sh with filesystem IDs automatically.
# Build ARM64 package with Docker
./build_lambda.sh
# Deploy to AWS
./deploy_lambda.shThe build process:
- Uses Docker with
public.ecr.aws/lambda/python:3.11-arm64image - Installs dependencies for ARM64 architecture (Graviton processors)
- Packages
api_extractormodule andhandler.py - Creates
lambda-function.zip(typically 15-20 MB)
The deploy process:
- Creates IAM role with Lambda, VPC, S3, and S3 Files permissions
- Creates or updates Lambda function
- Configures VPC networking
- Sets environment variables
Mount the S3 Files filesystem at /mnt/s3:
./attach_s3_files.shThis:
- Creates EFS File System Configuration linking S3 Files access point
- Mounts filesystem at
/mnt/s3in Lambda environment - Updates Lambda function configuration
Important: Lambda must be deployed before attaching S3 Files.
Enable HTTP access with IAM authentication:
./create_function_url.shThis creates a Function URL with:
- Auth Type:
AWS_IAM(requires signed requests) - CORS: Enabled for cross-origin access
The script outputs the Function URL:
Function URL: https://abc123xyz.lambda-url.eu-north-1.on.aws/
Save this URL - you'll need it to invoke the Lambda function.
Send a POST request with JSON body:
{
"folder": "my-fastapi-app",
"title": "My FastAPI Application",
"version": "2.0.0",
"description": "Production API for FastAPI app"
}Request Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
folder |
string | Yes | - | Folder name under /mnt/s3/lambda/ to analyze |
title |
string | No | "Extracted API" |
OpenAPI spec title |
version |
string | No | "1.0.0" |
API version |
description |
string | No | null |
API description |
Important: The folder parameter should match the folder name in S3:
- S3 path:
s3://my-code-repositories/lambda/my-fastapi-app/ - Request:
{"folder": "my-fastapi-app"} - Lambda reads:
/mnt/s3/lambda/my-fastapi-app/
Install awscurl for automatic AWS signature signing:
pip install awscurlMake a request:
# Get Function URL
FUNCTION_URL=$(aws lambda get-function-url-config \
--function-name api-extractor \
--query 'FunctionUrl' \
--output text)
# Extract API from folder
awscurl --service lambda --region eu-north-1 -X POST \
-H "Content-Type: application/json" \
-d '{"folder": "my-fastapi-app"}' \
"$FUNCTION_URL"Full example:
awscurl --service lambda --region eu-north-1 -X POST \
-H "Content-Type: application/json" \
-d '{
"folder": "my-spring-boot-app",
"title": "Spring Boot RealWorld API",
"version": "1.0.0",
"description": "RealWorld backend implementation"
}' \
"$FUNCTION_URL"Invoke Lambda directly (response is Base64-encoded):
aws lambda invoke \
--function-name api-extractor \
--payload '{"folder": "my-fastapi-app"}' \
response.json
# View response
cat response.jsonimport boto3
import json
client = boto3.client('lambda', region_name='eu-north-1')
response = client.invoke(
FunctionName='api-extractor',
InvocationType='RequestResponse',
Payload=json.dumps({
'folder': 'my-fastapi-app',
'title': 'My API',
'version': '1.0.0'
})
)
result = json.loads(response['Payload'].read())
print(json.dumps(result, indent=2))import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth
import json
# Get credentials from environment or ~/.aws/credentials
auth = AWSRequestsAuth(
aws_access_key='YOUR_ACCESS_KEY',
aws_secret_access_key='YOUR_SECRET_KEY',
aws_host='abc123xyz.lambda-url.eu-north-1.on.aws',
aws_region='eu-north-1',
aws_service='lambda'
)
response = requests.post(
'https://abc123xyz.lambda-url.eu-north-1.on.aws/',
auth=auth,
json={'folder': 'my-fastapi-app'}
)
openapi_spec = response.json()
print(json.dumps(openapi_spec, indent=2)){
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"X-Endpoints-Count": "15",
"X-Frameworks": "fastapi"
},
"body": "{\"openapi\":\"3.1.0\",\"info\":{\"title\":\"My API\",\"version\":\"1.0.0\"},...}"
}The body field contains a JSON-serialized OpenAPI 3.1.0 specification.
404 - Folder Not Found:
{
"statusCode": 404,
"headers": {"Content-Type": "application/json"},
"body": "{\"error\": \"Folder not found: my-project\"}"
}400 - Invalid Request:
{
"statusCode": 400,
"headers": {"Content-Type": "application/json"},
"body": "{\"error\": \"Missing required field: 'folder'\"}"
}500 - S3 Files Not Mounted:
{
"statusCode": 500,
"headers": {"Content-Type": "application/json"},
"body": "{\"error\": \"S3 filesystem not mounted at /mnt/s3\"}"
}422 - Extraction Failed:
{
"statusCode": 422,
"headers": {"Content-Type": "application/json"},
"body": "{\"error\": \"Extraction failed\", \"errors\": [...], \"warnings\": [...]}"
}Real-time logs:
aws logs tail /aws/lambda/api-extractor --followRecent logs:
# Last 10 minutes
aws logs tail /aws/lambda/api-extractor --since 10m
# Last hour
aws logs tail /aws/lambda/api-extractor --since 1hFilter logs:
# Show errors only
aws logs tail /aws/lambda/api-extractor --filter-pattern "ERROR"
# Show specific folder extractions
aws logs tail /aws/lambda/api-extractor --filter-pattern "my-fastapi-app"View Lambda metrics in CloudWatch console:
- Invocations
- Duration
- Errors
- Throttles
- Concurrent executions
Set in Lambda function configuration:
| Variable | Default | Description |
|---|---|---|
S3_MOUNT_PATH |
/mnt/s3 |
S3 Files mount point |
Update environment variables:
aws lambda update-function-configuration \
--function-name api-extractor \
--environment Variables="{S3_MOUNT_PATH=/mnt/s3}"Update timeout (default 300 seconds):
aws lambda update-function-configuration \
--function-name api-extractor \
--timeout 600Update memory (default 1024 MB):
aws lambda update-function-configuration \
--function-name api-extractor \
--memory-size 2048The Lambda function needs permissions for:
-
Lambda Execution:
AWSLambdaBasicExecutionRole- CloudWatch LogsAWSLambdaVPCAccessExecutionRole- VPC networking
-
S3 Access:
s3:GetObject- Read objects from S3 buckets3:ListBucket- List bucket contents
-
S3 Files Access:
s3files:DescribeFileSystem- Access filesystem metadatas3files:DescribeAccessPoint- Access mount point
The deploy_lambda.sh script creates these permissions automatically.
# Rebuild and redeploy
cd deployment/lambda
./build_lambda.sh
./deploy_lambda.sh# Upload updated project code
aws s3 sync ./my-fastapi-app s3://my-code-repositories/lambda/my-fastapi-app/
# S3 Files will automatically reflect changes
# No Lambda restart needed# Edit config
nano config.sh
# Redeploy
./deploy_lambda.shRun Lambda handler locally (requires uploaded code in S3):
cd deployment/lambda
python test_lambda_local.py# Test with default folder
./test_lambda_remote.sh
# Test specific folder
./test_lambda_remote.sh my-spring-boot-appcd deployment/lambda
./cleanup.shThis removes:
- Lambda function
- Lambda IAM role
- Function URL
Keeps:
- VPC and subnets
- S3 bucket and contents
- S3 Files filesystem
# Delete Lambda
./cleanup.sh
# Delete S3 Files
aws s3files delete-file-system --file-system-id $FILE_SYSTEM_ID
aws iam delete-role --role-name api-extractor-s3files-role
# Delete VPC
./cleanup_vpc.sh
# Delete S3 bucket (WARNING: deletes all code)
aws s3 rb s3://my-code-repositories --forceError:
{"error": "S3 filesystem not mounted at /mnt/s3"}Solution:
cd deployment/lambda
./attach_s3_files.shVerify mount:
aws lambda get-function-configuration \
--function-name api-extractor \
--query 'FileSystemConfigs'Error:
{"error": "Folder not found: my-project"}Solution:
Check S3 bucket structure:
aws s3 ls s3://my-code-repositories/lambda/Ensure folder exists under lambda/ prefix:
aws s3 cp --recursive ./my-project s3://my-code-repositories/lambda/my-project/Error:
Task timed out after 300.00 seconds
Solution:
Increase timeout:
# Edit config.sh
export LAMBDA_TIMEOUT=600
# Redeploy
./deploy_lambda.shOr update directly:
aws lambda update-function-configuration \
--function-name api-extractor \
--timeout 600Error:
Access Denied (Service: S3Files)
Solution:
Check IAM role permissions:
aws iam list-attached-role-policies \
--role-name api-extractor-roleRe-run setup:
./setup_s3_files.sh
./deploy_lambda.shError:
Task timed out (no logs)
Solution:
Verify VPC configuration:
aws lambda get-function-configuration \
--function-name api-extractor \
--query 'VpcConfig'Check security group allows outbound HTTPS:
aws ec2 describe-security-groups \
--group-ids $SECURITY_GROUP_IDAWS Lambda pricing (as of 2024):
| Component | Cost | Notes |
|---|---|---|
| Lambda Requests | $0.20 per 1M requests | First 1M free per month |
| Lambda Compute | $0.0000133334 per GB-second (ARM64) | First 400,000 GB-seconds free per month |
| S3 Storage | $0.023 per GB/month | Standard storage |
| S3 Files | $0.08 per GB transferred | Data transfer from S3 to Lambda |
| VPC | Free | No NAT Gateway needed |
Example calculation (1024 MB, 30-second execution):
- 1000 requests/month: $0.20
- Compute (1024 MB × 30s × 1000): $0.41
- S3 storage (10 GB): $0.23
- S3 Files transfer (100 MB per request × 1000): $8.00
Total: ~$8.84/month for 1000 requests
Free Tier:
- First 1M requests free
- First 400,000 GB-seconds free (~13,000 requests at 1024 MB × 30s)
- Serverless - No server management, automatic scaling
- Cost-Efficient - Pay only for actual execution time
- Low Latency - Function URL provides direct HTTP access
- S3 Integration - S3 Files mounts buckets as filesystem
- Secure - IAM authentication, VPC isolation
- ARM64 - Graviton processors for better price/performance
- Cold Starts - First request after idle period is slower (3-5 seconds)
- Timeout - Maximum 15 minutes execution time
- Memory - Maximum 10 GB memory
- VPC Required - S3 Files requires VPC configuration
- Large Projects - Very large codebases may exceed timeout
For production workloads with consistent traffic, consider the HTTP Server Mode with Docker/Kubernetes instead.
- HTTP Server Guide - HTTP API for on-demand analysis
- Docker Deployment - Containerized deployment
- Kubernetes Deployment - Production orchestration