NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. One of its powerful features is the microservices architecture, which allows developers to build distributed systems.
NestJS provides built-in transporters like TCP, Redis, and NATS, but sometimes you might need to create a custom transporter to meet specific requirements. This article explores how to create and use custom transporters in NestJS.
What are Transporters in NestJS?Transporters in NestJS are responsible for communication between microservices. They abstract the underlying communication protocol, allowing developers to focus on business logic. NestJS provides several built-in transporters, but custom transporters can be created to use different protocols or integrate with specific services.
The built-in transporters are:
- TCP: Default transport layer, suitable for direct service-to-service communication.
- Redis: Used for Pub/Sub messaging patterns.
- NATS: Lightweight, high-performance messaging system.
- MQTT: Protocol for IoT and M2M communication.
- gRPC: Google’s RPC framework for microservices.
While these built-in transporters cover a wide range of use cases, there are situations where a custom transporter is necessary. For example, integrating with a legacy system or a third-party service with a unique protocol might require a custom solution.
When to Use a Custom TransporterCreating a custom transporter might be necessary when:
- You need to integrate with a third-party service that uses a proprietary protocol.
- You want to optimize performance with a specialized communication protocol.
- The built-in transporters do not meet specific application requirements.
Steps to Create Nest ApplicationStep 1: Install NestJS globally in your systemTo create a new NestJS project, you can use the NestJS CLI (@nestjs/cli). Install it globally using npm:
npm install -g @nestjs/cli Step 2: Initialize NestJS ProjectCreating a New NestJS Project using the below command
nest new nest-gfg
cd nest-gfg You will be prompted to choose a package manager. Select either npm or yarn according to your preference.
Step 3: Install Required Packages
Install the @nestjs/microservices package if it’s not already included:
npm install @nestjs/microservices npm install @nestjs/platform-socket.io npm install @nestjs/websockets Step 4: Create the Custom Transporter
Create a new file custom.transporter.ts and app.gateway.ts in the src directory.
Folder Structure Nestjs folder structure Dependencies"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/microservices": "^10.3.10",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-socket.io": "^10.3.10", "@nestjs/websockets": "^10.3.10",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
} Example: Creating Custom Transporter
JavaScript
//src/custom.transporter.ts
import {
ClientProxy,
ReadPacket,
WritePacket,
CustomTransportStrategy,
} from '@nestjs/microservices';
import { Logger } from '@nestjs/common';
export class CustomTransporter
extends ClientProxy
implements CustomTransportStrategy {
private readonly logger = new Logger(CustomTransporter.name);
constructor(private readonly options: any) {
super();
}
async connect(): Promise<void> {
this.logger.log('Custom Transporter connected...');
// Implement your connection logic here
}
async close(): Promise<void> {
this.logger.log('Custom Transporter closed...');
// Implement your close logic here
}
listen(callback: () => void): void {
this.logger.log('Custom Transporter is listening...');
// Implement your custom transport logic here
callback();
}
protected dispatchEvent(packet: ReadPacket<any>): Promise<any> {
this.logger.log(`Dispatch event: ${JSON.stringify(packet)}`);
// Implement your dispatch event logic here
return Promise.resolve();
}
protected publish(
packet: ReadPacket<any>,
callback: (packet: WritePacket<any>) => void,
): () => void {
this.logger.log(`Publish event: ${JSON.stringify(packet)}`);
// Simulate an immediate response for testing purposes
callback({ response: 'response' });
return () => { };
}
}
JavaScript
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CustomTransporter } from './custom.transporter';
import { MicroserviceOptions } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.connectMicroservice<MicroserviceOptions>({
strategy: new CustomTransporter({
/* Custom options */
}),
});
await app.startAllMicroservices();
await app.listen(3000);
}
bootstrap();
JavaScript
//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppGateway } from './app.gateway';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService, AppGateway],
})
export class AppModule { }
JavaScript
//app.controller.ts
import { Controller, Get } from '@nestjs/common';
import {
ClientProxy,
ClientProxyFactory,
CustomClientOptions,
} from '@nestjs/microservices';
import { CustomTransporter } from './custom.transporter';
@Controller()
export class AppController {
private client: ClientProxy;
constructor() {
const customClientOptions: CustomClientOptions = {
customClass: CustomTransporter,
options: {
/* Custom options */
},
};
this.client = ClientProxyFactory.create(customClientOptions);
}
@Get()
async sendMessage() {
const pattern = { cmd: 'custom_message' };
const data = { text: 'Hello from custom transporter' };
const response = await this.client.send(pattern, data).toPromise();
return response;
}
@Get('custom-message')
async getCustomMessage() {
const pattern = { cmd: 'custom_message' };
const data = { text: 'Hello from custom transporter' };
const response = await this.client.send(pattern, data).toPromise();
return response;
}
}
JavaScript
//app.gateway.ts
import {
SubscribeMessage,
WebSocketGateway,
MessageBody,
} from '@nestjs/websockets';
@WebSocketGateway()
export class AppGateway {
@SubscribeMessage('message')
handleMessage(@MessageBody() message: string): string {
return message;
}
}
JavaScript
//app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
To start the application run the following command.
npm run start Output Custom Transporters in NestJS
|