Skip to main content

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