We use cookies to enhance your experience on the site
CodeWorlds

Routing and HTTP Methods in NestJS

Ave, young legionary! Consul Caesar.js is reaching out to you again. Now that you've learned the basics of our NestJS forum, it's time to learn how to navigate the digital provinces of the empire - that is, routing and handling various HTTP methods.

In a Roman legion, every soldier has their task and position. Similarly in NestJS, every endpoint has its role and path. Routing is our map of Roman roads - it tells us exactly where to find what we're looking for.

What is routing in NestJS?

Routing in NestJS is a system that determines how the application responds to different client requests to specific endpoints. Each endpoint is defined by a URL path and a specific HTTP method (GET, POST, PUT, DELETE).

Just as in the Roman Empire we have different sections - the forum, the senate, the tribute warehouses - so in an application we have different paths leading to different functionalities.

Basic HTTP methods

1import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
2
3@Controller('tributes')
4export class TributesController {
5 // GET - retrieving data (like checking the treasury contents)
6 @Get()
7 getAllTributes() {
8 return {
9 message: 'Here are all the tributes in the empire treasury!',
10 tributes: ['Gold coins', 'Gemstones', 'Sapphires']
11 };
12 }
13
14 // GET with parameter - retrieving a specific tribute
15 @Get(':id')
16 getTributeById(@Param('id') id: string) {
17 return {
18 message: `Found tribute with ID: ${id}`,
19 tribute: 'Golden medallion'
20 };
21 }
22
23 // POST - creating new data (adding tributes)
24 @Post()
25 addTribute(@Body() tributeData: any) {
26 return {
27 message: 'New tribute added to the treasury!',
28 tribute: tributeData
29 };
30 }
31
32 // PUT - updating data (replacing a tribute)
33 @Put(':id')
34 updateTribute(@Param('id') id: string, @Body() tributeData: any) {
35 return {
36 message: `Tribute ${id} has been updated`,
37 tribute: tributeData
38 };
39 }
40
41 // DELETE - removing data (transferring a tribute to another province)
42 @Delete(':id')
43 removeTribute(@Param('id') id: string) {
44 return {
45 message: `Tribute ${id} has been removed from the treasury`
46 };
47 }
48}

Routing decorators in NestJS

NestJS uses decorators to define routes. Each HTTP decorator corresponds to a specific method:

@Get() - Retrieving data

Used when we want to fetch information, like checking the legion status:

1@Get('legion')
2getLegionStatus() {
3 return {
4 consul: 'Caesar.js',
5 centurion: 'Marcus Aurelius',
6 legionaries: 120,
7 status: 'Ready to march!'
8 };
9}

@Post() - Creating new resources

Used when adding new legionaries:

1@Post('legion')
2addLegionary(@Body() newLegionary: any) {
3 return {
4 message: 'A new legionary has joined the legion!',
5 legionary: newLegionary
6 };
7}

@Put() - Updating an entire resource

Used when completely changing information about a legionary:

1@Put('legion/:id')
2updateLegionary(@Param('id') id: string, @Body() legionaryData: any) {
3 return {
4 message: `Legionary ${id} has received new duties`,
5 updatedLegionary: legionaryData
6 };
7}

@Patch() - Partial update

Used when changing only part of the information:

1@Patch('legion/:id')
2updateLegionaryPartially(@Param('id') id: string, @Body() partialData: any) {
3 return {
4 message: `Partially updated legionary ${id} data`,
5 changes: partialData
6 };
7}

@Delete() - Removing resources

Used when a legionary leaves the legion:

1@Delete('legion/:id')
2removeLegionary(@Param('id') id: string) {
3 return {
4 message: `Legionary ${id} has left the legion. Ave atque vale!`
5 };
6}

Route parameters

In the Roman forum, every resource has its unique identifier. In NestJS, we use URL parameters to identify specific resources:

1@Controller('forum')
2export class ForumController {
3 // Path parameter
4 @Get('level/:floor')
5 getFloorInfo(@Param('floor') floor: string) {
6 return {
7 floor: floor,
8 description: this.getFloorDescription(floor)
9 };
10 }
11
12 // Multiple parameters
13 @Get('chamber/:floor/:number')
14 getChamberInfo(
15 @Param('floor') floor: string,
16 @Param('number') number: string
17 ) {
18 return {
19 location: `Level ${floor}, chamber ${number}`,
20 occupant: 'Available'
21 };
22 }
23
24 // Query parameters
25 @Get('search')
26 searchItems(@Query('type') type: string, @Query('value') value: string) {
27 return {
28 message: `Searching for ${type} worth ${value} aureus`,
29 results: []
30 };
31 }
32
33 private getFloorDescription(floor: string): string {
34 const descriptions = {
35 'upper': 'Upper level - the consul rules here',
36 'main': 'Main level - the center of forum life',
37 'lower': 'Lower level - warehouses and treasury'
38 };
39 return descriptions[floor] || 'Unknown level';
40 }
41}

Request Body and Data Transfer Objects (DTO)

When provinces deliver new tributes to the empire, we need to check their quality and value. In NestJS, we use DTOs to validate data:

1// dto/tribute.dto.ts
2export class CreateTributeDto {
3 readonly name: string;
4 readonly type: string;
5 readonly value: number;
6 readonly description?: string;
7}
8
9@Controller('inventory')
10export class InventoryController {
11 @Post('add')
12 addToInventory(@Body() tributeDto: CreateTributeDto) {
13 // Validation was performed automatically
14 return {
15 message: 'Tribute added to the inventory!',
16 tribute: tributeDto,
17 addedAt: new Date().toISOString()
18 };
19 }
20}

Headers and Custom Headers

Sometimes legions send secret messages in dispatch headers. In NestJS, we can read and set HTTP headers:

1import { Headers, Res } from '@nestjs/common';
2import { Response } from 'express';
3
4@Controller('messages')
5export class MessageController {
6 @Get('secret')
7 getSecretMessage(@Headers('legion-token') token: string) {
8 if (token !== 'ave-caesar') {
9 return { error: 'Invalid legionary token!' };
10 }
11
12 return {
13 message: 'The tribute is hidden under the great oak in the province!'
14 };
15 }
16
17 @Post('send')
18 sendMessage(@Body() messageData: any, @Res() res: Response) {
19 // Setting custom header
20 res.setHeader('X-Legion-Response', 'message-sent');
21 res.setHeader('X-Legion-Name', 'Legio X Equestris');
22
23 return res.json({
24 message: 'Message sent!',
25 timestamp: new Date().toISOString()
26 });
27 }
28}

Status Codes

Every HTTP response has its status code, like flag signals in the Roman Empire:

1import { HttpStatus, HttpCode } from '@nestjs/common';
2
3@Controller('operations')
4export class OperationController {
5 @Post('campaign')
6 @HttpCode(HttpStatus.ACCEPTED) // 202
7 launchCampaign(@Body() target: any) {
8 return {
9 message: 'Campaign launched!',
10 target: target.name,
11 status: 'in-progress'
12 };
13 }
14
15 @Get('tribute/:id')
16 findTribute(@Param('id') id: string) {
17 if (id === '404') {
18 throw new NotFoundException('Tribute was not found!');
19 }
20
21 return {
22 tribute: `Tribute ${id}`,
23 location: 'Forum treasury'
24 };
25 }
26}

Wildcards and Advanced Routing

Sometimes we need flexible routes, like roads through various provinces:

1@Controller('navigation')
2export class NavigationController {
3 // Wildcard route - matches everything
4 @Get('province/*')
5 exploreProvince(@Param('0') path: string) {
6 return {
7 message: `Exploring province: ${path}`,
8 challenges: ['Local tribes', 'Difficult terrain', 'Unstable weather']
9 };
10 }
11
12 // Route patterns
13 @Get('coordinates/:lat-:lng')
14 getLocationInfo(@Param('lat') lat: string, @Param('lng') lng: string) {
15 return {
16 coordinates: { latitude: lat, longitude: lng },
17 description: 'Position on the empire map'
18 };
19 }
20}

Route grouping

In the great forum, we organize everything into sections. In NestJS, we can group routes using prefixes:

1@Controller('api/v1/legion')
2export class LegionManagementController {
3 @Get('status')
4 getLegionStatus() {
5 return {
6 name: 'Legio X Equestris',
7 legionaries: 5000,
8 ballistae: 20,
9 speed: '25 km/day'
10 };
11 }
12
13 @Get('supplies')
14 getSupplies() {
15 return {
16 food: '30 days',
17 water: '25 days',
18 weapons: '5000 units',
19 wine: '1000 amphorae' // Important for morale!
20 };
21 }
22}
Go to CodeWorlds