Uso de HttpModule en NestJS para comunicación de microservicios

Uso de HttpModule en NestJS para comunicación de microservicios

La comunicación entre microservicios es una de los principales desafíos de esta arquitectura y al trabajar con NestJS, este ofrece un módulo llamado HttpModule que se utiliza para realizar solicitudes HTTP. En este artículo, explicaré cómo integrar y utilizar este módulo en tu aplicación NestJS.

¿Qué es NestJS?

NestJS es un framework de back-end construido sobre Node.js. Utiliza TypeScript por defecto y ofrece un conjunto de herramientas para construir aplicaciones de servidor eficientes y escalables. Su arquitectura modular y sistema de inyección de dependencias permiten una fácil integración de diferentes módulos, incluido el HttpModule.

NestJS combina elementos de la programación orientada a objetos, funcional y reactiva, proporcionando una base sólida para la construcción de microservicios que pueden operar y escalar de manera independiente.

¿Qué es HttpModule?

HttpModule es una utilidad en NestJS que facilita la realización de solicitudes HTTP. Está basado en la biblioteca Axios y se integra perfectamente con los servicios de NestJS. Lo especial de HttpModule es que, en lugar de trabajar con promesas, trabaja con observables. Estos observables provienen de la biblioteca RxJS y permiten una mayor flexibilidad y control sobre las operaciones asíncronas, como las solicitudes HTTP.

Instalación y Configuración

Para comenzar a utilizar NestJS y HttpModule, primero deberás instalar el CLI de NestJS. Luego, podrás importar el HttpModule en el módulo de tu aplicación, yo estoy suponiendo que si has llegado a este artículo, es porque ya tienes tu aplicación montada y solo buscas entender como funciona el módulo de http.

// Instalación de NestJS CLI
npm i -g @nestjs/cli

// Crear una nueva aplicación
nest new my-nest-app

// Importar HttpModule en app.module.ts
import { HttpModule } from '@nestjs/common';
import { MiServicio } from './MiServicio';

@Module({
  imports: [HttpModule],
  providers: [MiServicio]
})
export class AppModule {}

Utilizando HttpModule

Este es un ejemplo de cómo realizar una solicitud vía POST hacia un endpoint que me he inventado, utiliza el método pipe y el operador catchError para el manejo de errores.

import { HttpService } from  '@nestjs/axios';
import { Inject, Injectable, Logger } from  '@nestjs/common';
import { AxiosError, AxiosRequestConfig, AxiosResponse } from  'axios';
import { catchError, firstValueFrom, map } from  'rxjs';

@Injectable()
export class MiServicio {
  private  readonly  logger  =  new  Logger(MiServicio.name);
  private  requestConfig: (type:  'JSON'  |  'FORM') =>  AxiosRequestConfig;
  /**
   * Constructor
   **/
  constructor(private httpService: HttpService) {
    // Configuración de la petición HTTP
    this.requestConfig = (type: 'JSON' | 'FORM'): AxiosRequestConfig => {
      const baseHeaders = {
         'Accept': 'application/json',
         'Content-Type': type === 'JSON' ? 'application/json' : 'application/x-www-form-urlencoded',
         'User-Agent': 'nombre_de_tu_aplicacion'
      };

      return {
        baseURL: 'http://ejemplo.com',
        headers: baseHeaders,
      };
    };
  }

  /**
   * ejemploPost
   **/
  async ejemploPost(uuid: string, data: Record<string, string | number >): Promise<boolean> {
    return firstValueFrom(
      this.httpService
        .post<boolean>(`/api/data/${uuid}`, data, this.requestConfig('JSON'))
        .pipe(
          map((res: AxiosResponse<boolean>) => res.data),
          catchError((error: AxiosError) => {
            throw error;
          }),
        )
    ).catch((error: AxiosError) => {
      this.logger.error(error);
      throw error;
    });
  }
}

El HttpModule retorna observables cuando se hacen solicitudes. Un observable es una secuencia de datos que pueden llegar con el tiempo. Con los observables, puedes usar operadores como pipe para transformar o manipular esos datos, o incluso manejar errores. El operador pipe permite encadenar múltiples operadores para actuar sobre los valores emitidos por el observable. En el ejemplo anterior, estamos utilizando pipe para transformar la respuesta y manejar errores.

Comentarios adicionales sobre los operadores y funciones de RxJS

firstValueFrom

Cuando trabajamos con observables, a menudo necesitamos extraer el primer valor emitido y luego completar automáticamente el observable. Esto es especialmente útil cuando trabajamos con llamadas HTTP, donde generalmente sólo nos interesa la respuesta inicial. La función firstValueFrom de RxJS nos permite hacer precisamente eso.

import { firstValueFrom } from 'rxjs';

const observableData = this.httpService.get('/api/data');
const data = await firstValueFrom(observableData);

En el código anterior, firstValueFrom toma el observable observableData y devuelve una promesa que resuelve con el primer valor emitido por el observable.

map

El operador map es similar a la función map de JavaScript para arrays, pero se aplica a observables. Nos permite transformar los datos emitidos por un observable antes de que lleguen al suscriptor.

import { map } from 'rxjs/operators';

this.httpService.get('/api/data').pipe(
  map(response => response.data)
);

En el ejemplo anterior, estamos usando map para extraer la propiedad data de la respuesta HTTP.

catchError

Las operaciones asincrónicas, como las solicitudes HTTP, pueden fallar por diversas razones. El operador catchError nos permite manejar errores en nuestro flujo de observables. Nos proporciona el error que ocurrió y nos permite devolver un nuevo observable o arrojar un error.

import { catchError } from 'rxjs/operators';

this.httpService.get('/api/data').pipe(
  catchError(error => {
    console.error('Error fetching data:', error);
    throw new Error('Failed to fetch data');
  })
);

En este ejemplo, estamos capturando cualquier error que ocurra durante la llamada HTTP y luego mostrando un mensaje de error en la consola y arrojando un nuevo error.

NestJS y su HttpModule representan una combinación poderosa para la construcción de microservicios robustos y eficientes. El uso de observables y el sistema modular de NestJS permiten una comunicación fluida entre servicios, optimizando el rendimiento y la escalabilidad de tus aplicaciones.

Debo dejar claro que no he sugerido que utilices HTTP para resolver la comunicación entre tus microservicios, esta es una de tantas posibles soluciones y obviamente el uso de HTTP agregará un poco de latencia en tus aplicaciones.

Happy coding! :D


Photo by Matt Duncan on Unsplash

Jack Fiallos

Jack Fiallos

Te gustó este artículo?