Routing
Routes connect URLs to your controllers. This guide covers everything you need to know about routing in StratusTS.
What is Routing?
Section titled “What is Routing?”Routing maps HTTP requests to specific controllers based on:
- URL path:
/users,/blog/posts - HTTP method: GET, POST, PATCH, DELETE, etc.
When someone visits your URL, routing decides which code runs.
Basic Route Setup
Section titled “Basic Route Setup”Each app has its own routes.ts file that defines its routes.
Minimal Example
Section titled “Minimal Example”import { Router } from 'stratus-ts';import { listUsers } from './controllers';
const { routes, route } = Router();
route.get('/', listUsers);
export default routes;What’s happening:
- Import
Routerfrom StratusTS - Create a router with
Router() - Define routes using
route.get(),route.post(), etc. - Export
routesas default
HTTP Methods
Section titled “HTTP Methods”StratusTS supports all standard HTTP methods.
GET - Retrieve Data
Section titled “GET - Retrieve Data”route.get('/', listUsers);route.get('/<id:int>', getUser);When to use: Fetching data, displaying pages, reading resources
POST - Create Data
Section titled “POST - Create Data”route.post('/create', createUser);route.post('/login', loginUser);When to use: Creating new resources, submitting forms, uploading data
PUT - Update Data (Complete)
Section titled “PUT - Update Data (Complete)”route.put('/<id:int>', updateUser);When to use: Replacing entire resources
PATCH - Update Data (Partial)
Section titled “PATCH - Update Data (Partial)”route.patch('/<id:int>', patchUser);When to use: Updating specific fields
DELETE - Remove Data
Section titled “DELETE - Remove Data”route.delete('/<id:int>', deleteUser);When to use: Removing resources
ALL - Any Method
Section titled “ALL - Any Method”route.all('/webhook', handleWebhook); // doesn't support yet trying hardWhen to use: Endpoints that accept any HTTP method
Route Paths
Section titled “Route Paths”Root Path
Section titled “Root Path”route.get('/', controller);Named Paths
Section titled “Named Paths”route.get('/profile', getProfile);route.get('/settings', getSettings);Full URLs:
/profile/settings
Nested Paths
Section titled “Nested Paths”route.get('/posts/recent', getRecentPosts);route.get('/admin/dashboard', getDashboard);Dynamic Parameters
Section titled “Dynamic Parameters”Basic Parameters
Section titled “Basic Parameters”route.get('/<id:int>', getUser);Access in controller:
const getUserController: ControllerType = (question, reply) => { const { id } = question.params(); console.log(`User ID: ${id}`);};Multiple Parameters
Section titled “Multiple Parameters”route.get('/<userId:int>/posts/<postId:int>', getPost);Access in controller:
const { userId, postId } = question.params();Query Parameters
Section titled “Query Parameters”Query parameters appear after ? in URLs: /users?page=2&limit=10
Upcomming
Section titled “Upcomming”Base URL / Prefix
Section titled “Base URL / Prefix”You can customize the base URL:
const { routes, route } = Router('/api/v1');
route.get('/users', handler); // → /api/v1/usersMultiple Routes Example
Section titled “Multiple Routes Example”Here’s a complete CRUD (Create, Read, Update, Delete) setup:
import { Router } from 'stratus-ts';import { listUsers, getUser, createUser, updateUser, deleteUser,} from './controllers';
const { routes, route } = Router();
// List all usersroute.get('/', listUsers);
// Get single userroute.get('/<id:int>', getUser);
// Create new userroute.post('/create', createUser);
// Update userroute.put('/<id:int>', updateUser);
// Delete userroute.delete('/<id:int>', deleteUser);
export default routes;Resulting Routes
Section titled “Resulting Routes”GET / → listUsersGET /:id → getUserPOST /create → createUserPUT /:id → updateUserDELETE /:id → deleteUserRESTful Routing
Section titled “RESTful Routing”Follow REST conventions for clean, predictable APIs.
Standard REST Routes
Section titled “Standard REST Routes”// Collection routesroute.get('/', listResources); // GET /usersroute.post('/', createResource); // POST /users
// Member routesroute.get('/<id:int>', getResource); // GET /users/:idroute.put('/<id:int>', updateResource); // PUT /users/:idroute.patch('/<id:int>', patchResource); // PATCH /users/:idroute.delete('/<id:int>', deleteResource); // DELETE /users/:idNested Resources
Section titled “Nested Resources”// Posts belong to usersroute.get('/<userId:int>/posts', getUserPosts);route.post('/<userId:int>/posts', createUserPost);route.get('/<userId:int>/posts/<postId:int>', getUserPost);URLs become:
/1/posts- Get all posts by user 1/1/posts/5- Get post 5 by user 1
Route Organization
Section titled “Route Organization”Keep Routes Logical
Section titled “Keep Routes Logical”Group related functionality:
// User routesroute.get('/', listUsers);route.get('/<id:int>', getUser);route.post('/create', createUser);
// Authentication routesroute.post('/login', loginUser);route.post('/logout', logoutUser);route.post('/register', registerUser);
// Profile routesroute.get('/profile', getProfile);route.patch('/profile', updateProfile);Route Order Matters
Section titled “Route Order Matters”Routes are matched in the order they’re defined.
Specific Before Generic
Section titled “Specific Before Generic”// ✅ Correct orderroute.get('/profile', getMyProfile); // Matches /profileroute.get('/<id:int>', getUser); // Matches /123
// ❌ Wrong orderroute.get('/<id:int>', getUser); // Matches /profile too!route.get('/profile', getMyProfile); // Never reachedRule: Define specific routes before dynamic routes.
Static Before Dynamic
Section titled “Static Before Dynamic”// Goodroute.get('/search', searchUsers);route.get('/new', newUserForm);route.get('/<id:str>', getUser);
// Badroute.get('/<id:str>', getUser); // Catches '/search' and '/new'route.get('/search', searchUsers); // Never reachedroute.get('/new', newUserForm); // Never reachedTesting Routes
Section titled “Testing Routes”Using curl
Section titled “Using curl”# GET requestcurl http://localhost:2000/users
# POST request with JSON datacurl -X POST http://localhost:2000/users/create \-H 'Content-Type: application/json' \-d '{"name":"Alice","email":"alice@example.com"}'
# GET with parameterscurl http://localhost:2000/users/1
# DELETE requestcurl -X DELETE http://localhost:2000/users/1Using Browser
Section titled “Using Browser”Visit in your browser for GET requests:
http://localhost:2000/usershttp://localhost:2000/users/1http://localhost:2000/users?page=2Using Postman/Insomnia
Section titled “Using Postman/Insomnia”- Set HTTP method (GET, POST, etc.)
- Enter URL:
http://localhost:2000/users - Add body for POST/PUT requests
- Click Send
Common Patterns
Section titled “Common Patterns”Pattern 1: API Endpoints
Section titled “Pattern 1: API Endpoints”const { routes, route } = Router('/api');
route.get('/users', listUsers);route.get('/posts', listPosts);route.get('/comments', listComments);
// URLs: /api/users, /api/posts, /api/commentsPattern 2: Versioned API
Section titled “Pattern 2: Versioned API”// api/routes.tsconst { routes, route } = Router('/api/v1');route.get('/users', listUsers);
// api-v2/routes.tsconst { routes, route } = Router('/api/v2');route.get('/users', listUsers);Pattern 3: Admin Routes
Section titled “Pattern 3: Admin Routes”Although planed for default admin panel
Section titled “Although planed for default admin panel”// In admin appconst { routes, route } = Router('/admin');
route.get('/dashboard', adminDashboard);route.get('/users', adminListUsers);route.delete('/users/<id:int>', adminDeleteUser);
// URLs: /admin/dashboard, /admin/users, etc.Debugging Routes
Section titled “Debugging Routes”List All Routes
Section titled “List All Routes”Add a debug route to see all registered routes:
// In admin appconst { routes, route } = Router();
route.get('/dashboard', dashboard);route.get('/users', users);route.delete('/users/<id:int>', user);
console.log(routes);Console Logging
Section titled “Console Logging”Add logging to understand route matching:
Upcomming
Section titled “Upcomming”Best Practices
Section titled “Best Practices”1. Use RESTful Conventions
Section titled “1. Use RESTful Conventions”Follow standard REST patterns for predictable APIs:
// ✅ Good - RESTfulroute.get('/', listUsers);route.post('/', createUser);route.get('/<id:int>', getUser);route.put('/<id:int>', updateUser);route.delete('/<id:int>', deleteUser);
// ❌ Bad - non-standardroute.get('/getAllUsers', listUsers);route.get('/createNewUser', createUser);2. Keep URLs Simple
Section titled “2. Keep URLs Simple”// ✅ Goodroute.get('/posts', listPosts);route.get('/posts/<id:int>', getPost);
// ❌ Badroute.get('/get-all-posts-from-database', listPosts);route.get('/retrieve-single-post-by-id/<id:int>', getPost);3. Use Nouns, Not Verbs
Section titled “3. Use Nouns, Not Verbs”// ✅ Good - nounsroute.get('/users', listUsers);route.post('/users', createUser);
// ❌ Bad - verbsroute.get('/getUsers', listUsers);route.post('/createUser', createUser);4. Be Consistent
Section titled “4. Be Consistent”// ✅ Good - consistentroute.get('/users', listUsers);route.get('/posts', listPosts);route.get('/comments', listComments);
// ❌ Bad - inconsistentroute.get('/users', listUsers);route.get('/all-posts', listPosts);route.get('/comment-list', listComments);5. Version Your API
Section titled “5. Version Your API”For public APIs, use versioning:
const { routes, route } = Router('/api/v1');This allows changes without breaking existing clients.
Troubleshooting
Section titled “Troubleshooting”Route Returns 404
Section titled “Route Returns 404”Check:
- App is in
APPSarray in settings - Route is defined in
routes.ts - Server was restarted after changes
- URL matches exactly (check spelling, case)
Wrong Controller Executes
Section titled “Wrong Controller Executes”Check:
- Route order (specific routes before generic)
- Multiple apps don’t define same route
- App order in
APPSarray
Parameters Not Working
Section titled “Parameters Not Working”Check:
- Using
:prefix:/<id:int>not/id - Accessing with
question.params().id - Dynamic routing is enabled (see Dynamic Routes)
Next Steps
Section titled “Next Steps”Now that you understand routing:
- Models - Connect routes to databases
- Dynamic Routes - Let’s see Dynamic Routes