02. Routing & Controllers
1. The Vanilla Mechanics
Routing is the mapping of an incoming HTTP request to a specific function based on the URL and Method. In raw Node.js or basic Express, this is often a chain of if/else statements or a simple router object.
Concept: Path Parsing
- Pathname: Extracting
/usersfrom/users?id=1. - Regex Matching: Handling dynamic routes like
/users/:id.
The “Raw” Implementation (Example)
const url = require('url');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
if (req.method === 'GET' && path === '/users') {
res.end('List of users');
} else if (req.method === 'POST' && path === '/users') {
res.end('Create user');
} else if (req.method === 'GET' && path.startsWith('/users/')) {
const id = path.split('/')[2];
res.end(`User with ID ${id}`);
}
});Challenges:
- Dynamic Routes: Extracting parameters from strings requires custom splitting logic.
- Tightly Coupled Logic: Routing and business logic are mixed in the same function.
- Parameter Extraction: It’s difficult to extract query params and body payloads cleanly.
2. The NestJS Abstraction
NestJS uses Decorators to handle routing declaratively.
Key Advantages:
@Controller(): Scopes a set of routes to a base path.- Request Decorators:
@Get(),@Post(),@Param(),@Query(),@Body()simplify data extraction. - Metadata-driven: NestJS registers these routes automatically at bootstrap time.
The NestJS Implementation:
import { Controller, Get, Post, Param, Body } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get() // GET /users
findAll() {
return 'List of users';
}
@Get(':id') // GET /users/123
findOne(@Param('id') id: string) {
return `User with ID ${id}`;
}
@Post() // POST /users
create(@Body() dto: any) {
return 'User created';
}
}3. Engineering Labs
- Lab 2.1: Implement a manual router in a raw Node.js script that handles at least three nested routes with path parameters.
- Lab 2.2: Re-implement the same in NestJS and use
@Param()to extract values directly into your method arguments.