Controllers
Controllers are functions that handle HTTP questions and send responses. This guide covers everything you need to know about building controllers in StratusTS.
What is a Controller?
Section titled “What is a Controller?”A controller is a function that:
- Receives an HTTP question
- Processes the data (business logic)
- Sends back an HTTP response
Think of controllers as the bridge between your routes and your application logic.
Basic Controller Structure
Section titled “Basic Controller Structure”Every controller follows this pattern:
import { type ControllerType, ok } from 'stratus-ts';
const myController: ControllerType = (question, reply) => { // 1. Get data from question // 2. Process/validate data // 3. Send response
reply.status(ok()).json({ success: true, message: 'Hello World!', });};
export { myController };Controller Anatomy
Section titled “Controller Anatomy”ControllerType - TypeScript type for type safety
question - The incoming HTTP question object containing:
question.body()- POST/PUT dataquestion.headers()- HTTP headersquestion.method()- HTTP method (GET, POST, etc.)
reply - The response object for sending data back:
reply.status()- Set HTTP status codereply.json()- Send JSON responsereply.send()- Send plain text/HTMLreply.header()- Set response headers
Creating Your First Controller
Section titled “Creating Your First Controller”Step 1: Create the Controller File
Section titled “Step 1: Create the Controller File”Open src/users/controllers.ts:
import { type ControllerType, ok } from 'stratus-ts';
const users = [{ id: 1, name: 'Alice', email: 'alice@example.com' },{ id: 2, name: 'Bob', email: 'bob@example.com' },];
const listUsers: ControllerType = (question, reply) => { reply.status(ok()).json({ success: true, data: users, });};
export { listUsers };Step 2: Link to Route
Section titled “Step 2: Link to Route”Open src/users/routes.ts:
import { Router } from 'stratus-ts';import { listUsers } from './controllers';
const { routes, route } = Router();
route.get('/', listUsers);
export default routes;Step 3: Test It
Section titled “Step 3: Test It”Visit http://localhost:2000/users to see your data!
Getting Request Data
Section titled “Getting Request Data”Reading the Request Body
Section titled “Reading the Request Body”For POST/PUT requests, data comes in question.body:
const createUser: ControllerType = (question, reply) => { const { body: { name, email, password } } = await question.body();
// Validate data if (!name || !email || !password) { return reply.status(400).json({ success: false, error: 'Missing required fields', }); }
// Create user (mock example) const newUser = { id: Date.now(), name, email, };
reply.status(201).json({ success: true, data: newUser, });};Test with curl:
curl -X POST http://localhost:2000/users/create -H "Content-Type: application/json" -d '{"name":"Charlie","email":"charlie@example.com","password":"secret"}'URL Parameters
Section titled “URL Parameters”Access dynamic URL segments:
// Route: route.get('/users/<id:str>', getUser)
const getUser: ControllerType = (question, reply) => { const { id } = question.params(); // Get <id:str> from URL
// Mock data const users = [ { id: '1', name: 'Alice', email: 'alice@example.com' }, { id: '2', name: 'Bob', email: 'bob@example.com' }, ];
const user = users.find(u => u.id === id);
if (!user) { return reply.status(404).json({ success: false, error:{ message:'User not found', name:'not found' } }); }
reply.status(200).json({ success: true, data: user, });};Test: http://localhost:2000/users/1
Query Parameters
Section titled “Query Parameters”Access query strings (?page=1&limit=10):
Upcomming
Section titled “Upcomming”Request Headers
Section titled “Request Headers”Access HTTP headers:
const protectedController: ControllerType = (question, reply) => { const authHeader = question.get('authorization'); // question.header('authorization') const contentType = question.get('content-type');
if (!authHeader) { throw new Error('Authorization header required') }
// Extract token const token = authHeader.replace('Bearer ', '');
// Verify token (mock) if (token !== 'valid-token') { throw new Error('Invalid token') }
reply.status(200).json({ success: true, data:{} });};Test with curl:
curl http://localhost:2000/users/protected -H "Authorization: Bearer valid-token"Sending Responses
Section titled “Sending Responses”HTTP Status Codes
Section titled “HTTP Status Codes”StratusTS provides helpers for common status codes:
import { ok, // 200 created, // 201 badRequest, // 400 unauthorized, // 401 forbidden, // 403 notFound, // 404 serverError, // 500} from 'stratus-ts';Status Code Examples
Section titled “Status Code Examples”200 OK - Success
reply.status(ok()).json({ success: true, data: users,});201 Created - Resource Created
reply.status(created()).json({ success: true, data: newUser,});400 Bad Request - Invalid Input
reply.status(badRequest()).json({ success: false, error: { message: 'Invalid email format', name: 'invalid' }});401 Unauthorized - Authentication Required
reply.status(unauthorized()).json({ success: false, error: { message: 'Please log in to continue', name: 'invalid' }});403 Forbidden - No Permission
reply.status(forbidden()).json({ success: false, error: { message:'You do not have permission to perform this action', name: 'invalid' }});404 Not Found - Resource Missing
reply.status(notFound()).json({ success: false, error: { message: 'User not found', name: 'not found', }});500 Internal Server Error - Something Broke
reply.status(serverError()).json({ success: false, error: { message: 'An unexpected error occurred', name: 'server error', }});Sending JSON Responses
Section titled “Sending JSON Responses”The most common response format:
const controller: ControllerType = (question, reply) => { reply.status(ok()).json({ success: true, data: { id: 1, name: 'Alice', email: 'alice@example.com', } });};Next Steps
Section titled “Next Steps”Now that you understand controllers: