NestJS — Guard ou Middleware?

Giovani Cassiano
3 min readJan 5, 2024

--

Nesse artigo, vamos aprender sobre a diferença entre guards e middlewares em aplicações NestJS.

Recentemente, precisei implementar um módulo de autorização de usuário em um projeto NestJS, e como também sou um programador PHP e amo utilizar o framework Laravel, a primeira coisa que veio na minha cabeça foi criar uma middleware. Mas eu também tenho conhecimento que o NestJS possui guards e foi onde que surgiu a minha dúvida.

Quais são as diferenças entre Guards e Middlewares?

Guards e Middlewares tem propósitos bem parecidos, podem até serem utilizadas para as mesmas finalidades, porém, devemos ter em mente que elas possuem papéis específicos

Guards

O guard é um componente que determina se uma requisição deve ser processada ou não. Ele é uma camada de segurança que tem como objetivo controlar os acessos a determinados recursos de uma aplicação. Os guards no NestJS implementam a interface CanActivate e são usados para lógicas de autorização.

Exemplo: Você pode ter um guard onde verifica se um determinado usuário possui permissões para cadastrar novos usuários.

@Injectable()
export class CanRegisterUser implements CanActivate {
canActivate(context: ExecutionContext): boolean | Promise<boolean> {
// Lógica da verificação da permissão do usuário
return true; // ou false
}
}

E depois inserir dentro do seu controller.

import { Controller, Post, UseGuards, Body } from '@nestjs/common';
import { CanRegisterUser } from './can-register-user.guard';

@Controller('user')
export class CreateUserController {

@Post()
@UseGuards(CanRegisterUser)
async createUser(@Body() userDTO) {
// Lógica para cadastrar novo usuário
}
}

Middlewares

Podemos dizer que as middlewares são camadas por interceptar as requisições e respostas de cada recurso que ela foi inserida. Seu principal objetivo é intermediar tanto a chegada quanto a saída, para realizar tarefas como de autorização, autenticação, logging e entre outras.

Um detalhe muito legal é que uma middleware pode ser executada em forma de cascata, criando assim camadas de regras.

Em NestJS, as middlewares utilizam a interface NestMiddleware e possuem acesso ao objeto Request, Response e NextFunction. Elas podem ser aplicadas em nível global, de rota ou controlador.

Exemplo: Você pode ter uma middleware que valida imprime um log no console da requisição que chegou e qual usuário está tentando acessar a rota.

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

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
private readonly logger = new Logger(LoggerMiddleware.name);

use(req: Request, res: Response, next: NextFunction) {
const method = req.method;
const path = req.path;
const userId = req.user ? req.user.id : 'N/A';

// Utiliza o LoggerService para imprimir logs
this.logger.log(`[${new Date().toISOString()}] ${method} ${path} - User ID: ${userId}`);

// Permite que a requisição prossiga para os próximos middlewares ou controladores
next();
}
}

E depois, só essa middleware globalmente na aplicação. Desta forma, todas as requisições da sua aplicação vão imprimir logs das requisições recebidas.

Caso tivesse outra middleware ela seria chamada após a execução da LoggerMiddleware .

// app.module.ts

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';

@Module({
// ... outras configurações do módulo
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
// Aplica o middleware a todas as rotas
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}

Resumo

O guard determina se uma requisição deve ser processada ou não, implementa a interface CanActivate e é usado geralmente para proteger rotas.

O middleware é executado durante um processamento de uma requisição HTTP como intermediador, utiliza a interface NestMiddleware e é usado geralmente para tarefas como autenticação, logging, manipulação de cabeçalhos, etc

Ambos são conceitos importantes para criar aplicações web robustas, permitindo controle de acesso e manipulação de requisições em diferentes pontos do ciclo de vida da aplicação.

Pessoal, é basicamente isso, espero que tenham gostado do meu artigo.

Me sigam no instagram e linkedin!

--

--