AWS Lambda Adapter¶
AwsApiGatewayAdapter ¶
AwsApiGatewayAdapter(app: RestApplication, metrics_publisher: Union[MetricsPublisher, None, _DefaultPublisher] = _DEFAULT_PUBLISHER, enable_metrics: Optional[bool] = None, namespace: Optional[str] = None, service_name: Optional[str] = None, metrics_resolution: int = 60)
Bases: Adapter
Adapter for AWS API Gateway Lambda proxy integration events.
This adapter handles events from: - API Gateway REST APIs (v1) - payload format 1.0 - API Gateway HTTP APIs (v2) - payload format 2.0 - Application Load Balancer (ALB) - Lambda Function URLs (v2 format)
Version detection is automatic based on event structure:
- v1 events use httpMethod
at top level
- v2 events have version: "2.0"
field
- ALB events have requestContext.elb
field
Follows ASGI patterns for header and parameter handling: - Headers are normalized to lowercase for case-insensitive matching - Query parameters are parsed consistently - Body encoding is handled transparently
Initialize the adapter with a RestApplication instance.
Automatically executes startup handlers during cold start and configures CloudWatch EMF metrics unless disabled.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
app
|
RestApplication
|
The RestApplication instance to execute requests against |
required |
metrics_publisher
|
Union[MetricsPublisher, None, _DefaultPublisher]
|
Metrics publisher. Defaults to CloudWatchEMFPublisher. Pass None to explicitly disable metrics. |
_DEFAULT_PUBLISHER
|
enable_metrics
|
Optional[bool]
|
Explicitly enable/disable metrics. |
None
|
namespace
|
Optional[str]
|
CloudWatch namespace (overrides env var) |
None
|
service_name
|
Optional[str]
|
Service name for dimension (overrides env var) |
None
|
metrics_resolution
|
int
|
Default resolution, 1 or 60 seconds (default: 60) |
60
|
Examples:
Auto EMF with custom namespace¶
adapter = AwsApiGatewayAdapter( app, namespace="MyApp/API", service_name="user-service" )
High-resolution metrics¶
adapter = AwsApiGatewayAdapter( app, namespace="MyApp/API", metrics_resolution=1 )
Disable metrics¶
adapter = AwsApiGatewayAdapter(app, enable_metrics=False)
Source code in packages/restmachine-aws/src/restmachine_aws/adapter.py
Functions¶
handle_event ¶
Handle an AWS API Gateway event with metrics support.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
event
|
Dict[str, Any]
|
AWS API Gateway event dictionary |
required |
context
|
Optional[Any]
|
AWS Lambda context (optional) |
None
|
Returns:
Type | Description |
---|---|
Dict[str, Any]
|
AWS API Gateway response dictionary |
Source code in packages/restmachine-aws/src/restmachine_aws/adapter.py
convert_to_request ¶
Convert AWS event to Request object.
Automatically detects and handles: - API Gateway (v1, v2) events - Application Load Balancer (ALB) events - Lambda Function URL events
Parameters:
Name | Type | Description | Default |
---|---|---|---|
event
|
Dict[str, Any]
|
AWS event dictionary |
required |
context
|
Optional[Any]
|
AWS Lambda context (optional) |
None
|
Returns:
Type | Description |
---|---|
Request
|
Request object |
Source code in packages/restmachine-aws/src/restmachine_aws/adapter.py
convert_from_response ¶
convert_from_response(response: Response, event: Dict[str, Any], context: Optional[Any] = None) -> Dict[str, Any]
Convert Response object to AWS API Gateway response format.
Handles proper JSON serialization, header encoding, streaming bodies, and file paths. For streaming bodies and Path objects, reads the entire content since Lambda requires complete responses.
Range Request Support: - Detects 206 Partial Content responses (response.is_range_response()) - Extracts only the requested byte range from Path, stream, or bytes body - Base64 encodes the range content for transmission
Parameters:
Name | Type | Description | Default |
---|---|---|---|
response
|
Response
|
Response from the app |
required |
event
|
Dict[str, Any]
|
Original AWS API Gateway event |
required |
context
|
Optional[Any]
|
AWS Lambda context (optional) |
None
|
Returns:
Type | Description |
---|---|
Dict[str, Any]
|
AWS API Gateway response dictionary |
Source code in packages/restmachine-aws/src/restmachine_aws/adapter.py
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
|
Overview¶
The AwsApiGatewayAdapter
converts AWS Lambda events into RestMachine requests and responses back into Lambda-compatible formats. It automatically detects and handles multiple event sources.
Supported Event Sources¶
The adapter automatically detects and handles:
- API Gateway REST API (v1) - Payload format 1.0
- API Gateway HTTP API (v2) - Payload format 2.0
- Application Load Balancer (ALB) - ALB target integration
- Lambda Function URLs - Direct HTTPS endpoints (uses v2 format)
Version detection is automatic based on the event structure.
Basic Usage¶
from restmachine import RestApplication
from restmachine_aws import AwsApiGatewayAdapter
app = RestApplication()
@app.get("/hello/{name}")
def hello(request):
name = request.path_params['name']
return {"message": f"Hello, {name}!"}
# Create adapter
adapter = AwsApiGatewayAdapter(app)
def lambda_handler(event, context):
"""AWS Lambda handler function."""
return adapter.handle_event(event, context)
Automatic Startup¶
The adapter automatically runs startup handlers during Lambda cold start:
@app.on_startup
def database():
"""Runs once per Lambda container."""
print("Opening database connection...")
return create_db_connection()
@app.get("/users/{user_id}")
def get_user(database, request):
# Database connection is already initialized
user_id = request.path_params['user_id']
return database.get_user(user_id)
Startup handlers execute when the Lambda container initializes, not on every request. This ensures expensive operations (like opening database connections) only happen during cold starts.
Event Format Detection¶
API Gateway v1 (REST API)¶
{
"httpMethod": "GET",
"path": "/users/123",
"headers": {"Accept": "application/json"},
"pathParameters": {"user_id": "123"},
"queryStringParameters": {"page": "1"},
"body": null,
"requestContext": {
"requestId": "abc123",
"authorizer": {...}
}
}
API Gateway v2 (HTTP API)¶
{
"version": "2.0",
"routeKey": "GET /users/{user_id}",
"rawPath": "/users/123",
"headers": {"accept": "application/json"},
"pathParameters": {"user_id": "123"},
"queryStringParameters": {"page": "1"},
"body": null,
"requestContext": {
"http": {
"method": "GET",
"path": "/users/123"
}
}
}
Application Load Balancer (ALB)¶
{
"httpMethod": "GET",
"path": "/users/123",
"headers": {"accept": "application/json"},
"queryStringParameters": {"page": "1"},
"body": null,
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:..."
}
}
}
The adapter automatically detects the format and extracts the correct fields.
Header Handling¶
Headers are normalized to lowercase for case-insensitive matching, following ASGI conventions:
# API Gateway event
{
"headers": {
"Content-Type": "application/json",
"X-Custom-Header": "value"
}
}
# Converted to
request.headers = {
"content-type": "application/json",
"x-custom-header": "value"
}
Access headers in your handlers:
@app.get("/api/data")
def get_data(request):
content_type = request.headers.get("content-type")
custom = request.headers.get("x-custom-header")
return {"content_type": content_type, "custom": custom}
Multi-Value Headers¶
The adapter properly handles multi-value headers (cookies, set-cookie, etc.):
# API Gateway v1 with multiValueHeaders
{
"multiValueHeaders": {
"cookie": ["session=abc123", "tracking=xyz789"]
}
}
# Converted to RestMachine request
request.headers = MultiValueHeaders({
"cookie": ["session=abc123", "tracking=xyz789"]
})
Query Parameters¶
Query parameters are parsed and available as dictionaries:
# Event
{
"queryStringParameters": {
"page": "2",
"limit": "10"
}
}
# Access in handler
@app.get("/users")
def list_users(request):
page = int(request.query_params.get("page", 1))
limit = int(request.query_params.get("limit", 20))
return {"page": page, "limit": limit}
Request Body¶
The adapter handles both plain text and base64-encoded bodies:
# Plain text body
{
"body": '{"name": "Alice", "email": "alice@example.com"}',
"isBase64Encoded": false
}
# Base64-encoded body (binary data)
{
"body": "iVBORw0KGgoAAAANSUhEUgAA...",
"isBase64Encoded": true
}
# Access in handler
@app.post("/users")
def create_user(request):
import json
data = json.loads(request.body)
return {"created": data}, 201
Response Conversion¶
RestMachine responses are automatically converted to Lambda-compatible formats:
# RestMachine response
Response(
status_code=200,
body='{"message": "Success"}',
headers={"Content-Type": "application/json"}
)
# Converted to API Gateway v1 format
{
"statusCode": 200,
"body": '{"message": "Success"}',
"headers": {"Content-Type": "application/json"},
"multiValueHeaders": {},
"isBase64Encoded": false
}
# Converted to API Gateway v2 format
{
"statusCode": 200,
"body": '{"message": "Success"}',
"headers": {"content-type": "application/json"},
"cookies": [],
"isBase64Encoded": false
}
Error Handling¶
The adapter handles errors gracefully:
@app.get("/users/{user_id}")
def get_user(request):
user_id = request.path_params['user_id']
if not user_exists(user_id):
return {"error": "User not found"}, 404
return {"id": user_id, "name": "Alice"}
# Returns proper Lambda error response
{
"statusCode": 404,
"body": '{"error": "User not found"}',
"headers": {"Content-Type": "application/json"}
}
Method Reference¶
handle_event(event, context)
¶
Main entry point for Lambda handler.
Parameters:
- event
(dict): AWS Lambda event dictionary
- context
(optional): AWS Lambda context object
Returns: - dict: Lambda-compatible response dictionary
Example:
convert_to_request(event, context)
¶
Convert AWS event to RestMachine Request object.
Parameters:
- event
(dict): AWS Lambda event
- context
(optional): Lambda context
Returns: - Request: RestMachine Request object
convert_from_response(response, event, context)
¶
Convert RestMachine Response to Lambda response format.
Parameters:
- response
(Response): RestMachine response
- event
(dict): Original AWS event (for format detection)
- context
(optional): Lambda context
Returns: - dict: Lambda-compatible response
See Also¶
- Lambda Deployment Guide - Complete deployment guide
- Lambda Extensions - Shutdown handler support
- Lifecycle Handlers - Startup and shutdown patterns