HTTP Handlers
Learn how to create and work with HTTP handlers in Serverless Monolith.
Basic Handler
A handler is an async function that receives an API Gateway event and returns a response:
import { APIGatewayProxyHandler, APIGatewayProxyResult } from 'aws-lambda';
export const handler: APIGatewayProxyHandler = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello World' }),
};
};
Event Object
The event object contains information about the HTTP request:
export const handler: APIGatewayProxyHandler = async (event) => {
// HTTP method
const method = event.httpMethod; // GET, POST, PUT, DELETE, etc.
// Path parameters
const { id } = event.pathParameters || {};
// Query string parameters
const { page, limit } = event.queryStringParameters || {};
// Request headers
const authHeader = event.headers['Authorization'];
// Request body (for POST, PUT, PATCH)
const body = JSON.parse(event.body || '{}');
// ...
};
Defining Routes
Define routes in your functions.yml:
# GET /users
listUsers:
handler: handlers/list/index.handler
events:
- http:
path: users
method: GET
# POST /users
createUser:
handler: handlers/create/index.handler
events:
- http:
path: users
method: POST
cors: true
# GET /users/{id}
getUserById:
handler: handlers/get/index.handler
events:
- http:
path: users/{id}
method: GET
# PUT /users/{id}
updateUser:
handler: handlers/update/index.handler
events:
- http:
path: users/{id}
method: PUT
# DELETE /users/{id}
deleteUser:
handler: handlers/delete/index.handler
events:
- http:
path: users/{id}
method: DELETE
Response Format
Always return a properly formatted response:
// Success response
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
};
// Error response
return {
statusCode: 400,
body: JSON.stringify({
error: 'Validation failed',
details: errors,
}),
};
// No content
return {
statusCode: 204,
body: '',
};
CORS Configuration
Enable CORS in your function definition:
createUser:
handler: handlers/create/index.handler
events:
- http:
path: users
method: POST
cors: true
Or with custom configuration:
createUser:
handler: handlers/create/index.handler
events:
- http:
path: users
method: POST
cors:
origin: 'https://example.com'
headers:
- Content-Type
- Authorization
allowCredentials: true
Request Validation
Validate incoming requests in your handler:
import { APIGatewayProxyHandler } from 'aws-lambda';
interface CreateUserBody {
name: string;
email: string;
}
export const handler: APIGatewayProxyHandler = async (event) => {
// Parse body
let body: CreateUserBody;
try {
body = JSON.parse(event.body || '{}');
} catch {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Invalid JSON body' }),
};
}
// Validate required fields
if (!body.name || !body.email) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Name and email are required' }),
};
}
// Process request...
};
Error Handling
Implement proper error handling:
export const handler: APIGatewayProxyHandler = async (event) => {
try {
const result = await someOperation();
return {
statusCode: 200,
body: JSON.stringify(result),
};
} catch (error) {
console.error('Handler error:', error);
if (error instanceof ValidationError) {
return {
statusCode: 400,
body: JSON.stringify({ error: error.message }),
};
}
if (error instanceof NotFoundError) {
return {
statusCode: 404,
body: JSON.stringify({ error: 'Resource not found' }),
};
}
return {
statusCode: 500,
body: JSON.stringify({ error: 'Internal server error' }),
};
}
};
Accessing Execution ID
Each request has a unique execution ID for tracing:
export const handler: APIGatewayProxyHandler = async (event, context) => {
const executionId = context.awsRequestId;
console.log(`[${executionId}] Processing request...`);
return {
statusCode: 200,
headers: {
'X-Execution-Id': executionId,
},
body: JSON.stringify({ success: true }),
};
};
Testing Handlers
Test handlers using the local server:
# GET request
curl http://localhost:4005/api/http/user/users
# POST request
curl -X POST http://localhost:4005/api/http/user/users \
-H "Content-Type: application/json" \
-d '{"name": "John", "email": "john@example.com"}'
# GET with path parameter
curl http://localhost:4005/api/http/user/users/123
# GET with query parameters
curl "http://localhost:4005/api/http/user/users?page=1&limit=10"
Next Steps
- SQS Handlers - Working with queues
- Logging - Execution logging and debugging