Setting Up Backend Routes in NestJS

Learn how to create, structure, and secure backend routes in your MatureStack NestJS application.

Prerequisites

  • Node.js and npm installed
  • A NestJS project initialized
  • Basic understanding of TypeScript

Basic Route Setup

To set up a route in NestJS, you need to create a controller and define a route handler.

// src/app.controller.ts
import { Controller, Get } from '@nestjs/common';

@Controller('example') // Base route: /example
export class AppController {
  @Get()
  getExample(): string {
    return 'This is an example route!';
  }
}

The route above will be accessible at /example. The @Controller() decorator defines the base route, and the @Get() decorator specifies the HTTP GET method.

Dynamic Routes

NestJS allows dynamic routes using route parameters:

// src/app.controller.ts
import { Controller, Get, Param } from '@nestjs/common';

@Controller('users')
export class UserController {
  @Get(':id') // Dynamic route: /users/:id
  getUser(@Param('id') id: string): string {
    return `User ID: ${id}`;
  }
}

The route /users/123 will return User ID: 123. The @Param() decorator extracts the route parameter.

Creating POST Routes

Use the @Post() decorator to handle POST requests:

// src/app.controller.ts
import { Controller, Post, Body } from '@nestjs/common';

@Controller('tasks')
export class TaskController {
  @Post() // POST route: /tasks
  createTask(@Body() taskData: { title: string; description: string }): string {
    return `Task Created: ${taskData.title}`;
  }
}

The @Body() decorator extracts data from the request body.

Using Middleware for Routes

Middleware can be used for logging, authentication, or other pre-processing tasks:

// src/logger.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log(`Request... ${req.method} ${req.originalUrl}`);
    next();
  }
}

Register the middleware in the module:

// src/app.module.ts
import { Module, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';
import { AppController } from './app.controller';

@Module({
  controllers: [AppController],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('*');
  }
}

Guards and Public Decorators

@UseGuards(JwtAuthGuard, CompanyAccessGuard)

The @UseGuards decorator combines multiple guards for security. Using JwtAuthGuard and CompanyAccessGuard ensures:

  • The user is authenticated with a valid JWT token.
  • The company mentioned in the route belongs to the logged-in user.
@UseGuards(JwtAuthGuard, CompanyAccessGuard)
@Controller('companies/:companyId/resources')
export class ResourcesController {
@Get()
getResources(@Param('companyId') companyId: string) {
  return this.resourcesService.getResourcesForCompany(companyId);
}
}

@Public()

The @Public() decorator marks an endpoint as publicly accessible, bypassing any guards applied globally or at the controller level.

@Public()
@Post('auth/login')
async login(@Body() loginDto: LoginDto) {
return this.authService.login(loginDto);
}

Best Practices

  • Group related routes into modules for better organization.
  • Use DTOs (Data Transfer Objects) for data validation.
  • Implement guards to secure sensitive routes.
  • Use the @Public() decorator only for endpoints meant for unauthenticated access.
MatureStack LogoBuilt with MatureStack