Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🟢
Intermediaire 30 min NestJS

API REST avec NestJS

Pourquoi API REST avec NestJS ?

API REST est un modèle d'architecture pour les applications web qui utilise l'HTTP pour communiquer entre clients et serveurs. Avec NestJS, vous pouvez créer des API REST de manière plus rapide et efficace en utilisant TypeScript. Un dev a besoin de ce type d'API pour interagir avec des données sur le backend et mettre à jour ces données dans une base de données.

Un cas concret est l'application de gestionnaire de tâches où vous avez besoin d'un système qui permet aux utilisateurs de créer, lire, mettre à jour et supprimer des tâches.

Prerequis

  • Connaissances en JavaScript/TypeScript
  • Compréhension de base de la programmation orientée objet
  • Node.js installé sur votre machine (version recommandée : 14.x)
  • npm ou yarn pour la gestion des dépendances

Concepts fondamentaux

Controller

Un controller gère les requêtes HTTP et retourne une réponse. Il définit les routes de l'API.

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

@Controller('tasks')
export class TasksController {
  @Get()
  findAll() {
    return 'This action returns all tasks';
  }

  @Post()
  create() {
    return 'This action adds a new task';
  }
}

Service

Un service contient la logique métier de l'application. Il est utilisé par les controllers.

// tasks.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class TasksService {
  findAll() {
    return 'This action returns all tasks';
  }

  create(task: any) {
    return 'This action adds a new task';
  }
}

Module

Un module regroupe les contrôleurs, les services et autres éléments logiques liés.

// app.module.ts
import { Module } from '@nestjs/common';
import { TasksController } from './app.controller';
import { TasksService } from './tasks.service';

@Module({
  imports: [],
  controllers: [TasksController],
  providers: [TasksService],
})
export class AppModule {}

DTO (Data Transfer Object)

Un DTO est utilisé pour définir la structure des données d'entrée et de sortie.

// create-task.dto.ts
import { IsNotEmpty } from 'class-validator';

export class CreateTaskDto {
  @IsNotEmpty()
  title: string;

  description?: string;
}

Validation

NestJS utilise le validateur class-validator pour la validation des données.

// tasks.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { CreateTaskDto } from './create-task.dto';

@Controller('tasks')
export class TasksController {
  constructor(private readonly tasksService: TasksService) {}

  @Post()
  async create(@Body() createTaskDto: CreateTaskDto) {
    return this.tasksService.create(createTaskDto);
  }
}

Middleware

Un middleware est une fonction qui est appelée avant que le controller ne traite la requête.

// logger.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request...`);
    next();
  }
}

Exception Filter

Un exception filter permet de gérer les exceptions et de renvoyer une réponse personnalisée.

// http.exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}

Mise en pratique : projet fil rouge

Nous allons créer un gestionnaire de tâches simple avec NestJS.

Étape 1 : Initialisation du projet

npm install -g @nestjs/cli
nest new task-manager
cd task-manager

Étape 2 : Création d'un service et d'un controller

## tasks.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class TasksService {
  private tasks: any[] = [];

  findAll() {
    return this.tasks;
  }

  create(task: any) {
    this.tasks.push(task);
    return task;
  }
}
typescript
## app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';

@Controller('tasks')
export class TasksController {
  constructor(private readonly tasksService: TasksService) {}

  @Get()
  findAll() {
    return this.tasksService.findAll();
  }

  @Post()
  create(@Body() taskDto: any) {
    return this.tasksService.create(taskDto);
  }
}

Étape 3 : Ajout de la validation avec DTO

## create-task.dto.ts
import { IsNotEmpty, IsOptional } from 'class-validator';

export class CreateTaskDto {
  @IsNotEmpty()
  title: string;

  @IsOptional()
  description?: string;
}

Mise à jour du controller :

## app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { CreateTaskDto } from './create-task.dto';

@Controller('tasks')
export class TasksController {
  constructor(private readonly tasksService: TasksService) {}

  @Get()
  findAll() {
    return this.tasksService.findAll();
  }

  @Post()
  create(@Body() taskDto: CreateTaskDto) {
    return this.tasksService.create(taskDto);
  }
}

Étape 4 : Ajout de middleware et filter

Création du middleware :

## logger.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request...`);
    next();
  }
}

Ajout du middleware au module principal :

## app.module.ts
import { Module } from '@nestjs/common';
import { TasksController } from './app.controller';
import { TasksService } from './tasks.service';
import { LoggerMiddleware } from './logger.middleware';

@Module({
  imports: [],
  controllers: [TasksController],
  providers: [TasksService, LoggerMiddleware],
})
export class AppModule {}

Création du filter :

## http.exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}

Ajout du filter au module principal :

## app.module.ts
import { Module } from '@nestjs/common';
import { TasksController } from './app.controller';
import { TasksService } from './tasks.service';
import { LoggerMiddleware } from './logger.middleware';
import { HttpExceptionFilter } from './http.exception.filter';

@Module({
  imports: [],
  controllers: [TasksController],
  providers: [TasksService, LoggerMiddleware, HttpExceptionFilter],
})
export class AppModule {}

Étape 5 : Exécution et test de l'API

npm run start

Test avec Postman ou curl :

curl -X POST http://localhost:3000/tasks -H "Content-Type: application/json" -d '{"title": "Task 1", "description": "Description 1"}'
curl http://localhost:3000/tasks

Erreurs frequentes et debugging

Erreur 1 : Cannot find module 'class-validator'

## ❌ Mauvais
import { IsNotEmpty } from 'class-validator';

## ✅ Correct
npm install class-validator --save
import { IsNotEmpty } from 'class-validator';

Erreur 2 : TypeError: Cannot read property 'apply' of undefined

## ❌ Mauvais
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req, res, next) {
    console.log(`Request...`);
    next();
  }
}

## ✅ Correct
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request...`);
    next();
  }
}

Erreur 3 : Unhandled exception

## ❌ Mauvais
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}

## ✅ Correct
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}

Pour aller plus loin

Piste 1 : Ajout d'une base de données

Utilisez TypeORM pour connecter votre application à une base de données.

  • Installez TypeORM et les dépendances requises.
  • Configurez la connexion à la base de données.
  • Mettez à jour le service pour utiliser des entités et des repositories.

Piste 2 : Création d'une API sécurisée

Ajoutez l'authentification JWT pour sécuriser votre API.

  • Installez les dépendances nécessaires (jsonwebtoken).
  • Créez un middleware d'authentification.
  • Appliquez le middleware aux routes sensibles.

Piste 3 : Création d'une API de blog

Créez une API simple pour gérer des articles.

  • Ajoutez une ressource 'articles'.
  • Implémentez les opérations CRUD (Create, Read, Update, Delete).
  • Testez l'API avec Postman ou curl.

Défi pratique : Création d'un CLI tool

Créez un CLI tool utilisant NestJS pour gérer des tâches en ligne de commande.

  • Installez le package @nestjs/cli global.
  • Créez un projet CLI.
  • Implémentez les commandes (create, read, update, delete).
  • Testez le CLI avec npm scripts ou directement dans la console.

Besoin d'aide sur NestJS ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelle est la différence entre NestJS et Express?
NestJS est un framework d'application basé sur le design pattern des microservices, tandis qu'Express est un cadre minimaliste pour créer des applications web en Node.js.
Comment définir une route dans NestJS?
Pour définir une route dans NestJS, on utilise les décorateurs @Controller et @Get, @Post, @Put, etc. sur une méthode du contrôleur correspondant à la fonctionnalité souhaitée.
Comment gérer les erreurs en utilisant NestJS?
NestJS utilise un système de gestion des exceptions basé sur le décorateur @Catch et le service ExceptionFilter pour traiter et renvoyer des erreurs au client de manière cohérente.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.