NestJS is a progressive framework for building scalable server-side applications. To enhance security, optimize performance, and streamline functionality, various middleware and libraries are integrated into NestJS projects. This guide explores essential tools and features such as CORS, Swagger, Mongoose, Rate Limiting, CSP, Helmet, Custom Logging, PM2 Logging, and Environment Variables Handling with .env
, complete with examples.
1. Cross-Origin Resource Sharing (CORS)
CORS ensures that your API can handle requests from specific origins, improving security while allowing legitimate cross-origin requests.
Implementation:
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: "https://example.com", // Specify allowed origins
methods: "GET,POST,PUT,DELETE",
credentials: true,
});
await app.listen(3000);
}
bootstrap();
Use Case: CORS is vital for APIs that serve frontend applications hosted on different domains.
2. Swagger for API Documentation
Swagger simplifies API documentation and testing. With NestJS, it's effortless to integrate Swagger.
Installation:
npm install --save @nestjs/swagger swagger-ui-express
Implementation:
import { NestFactory } from "@nestjs/core";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle("API Documentation")
.setDescription("API documentation for our application")
.setVersion("1.0")
.addBearerAuth() // Add Authorization Header
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api-docs", app, document); // Accessible at /api-docs
await app.listen(3000);
}
bootstrap();
Use Case: Automatically generate and maintain documentation for RESTful APIs.
3. Mongoose for MongoDB
Mongoose integrates MongoDB with NestJS, providing schema-based solutions to model your application data.
Installation:
npm install --save @nestjs/mongoose mongoose
Example:
// user.schema.ts
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Document } from "mongoose";
@Schema()
export class User extends Document {
@Prop({ required: true })
name: string;
@Prop({ required: true, unique: true })
email: string;
@Prop({ required: true })
password: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
// app.module.ts
import { Module } from "@nestjs/common";
import { MongooseModule } from "@nestjs/mongoose";
@Module({
imports: [MongooseModule.forRoot("mongodb://localhost/nest")],
})
export class AppModule {}
Use Case: Build scalable applications requiring a NoSQL database like MongoDB.
4. Rate Limiting
Rate limiting prevents abuse by restricting the number of requests a user can make.
Installation:
npm install --save @nestjs/throttler
Implementation:
import { Module } from "@nestjs/common";
import { ThrottlerModule } from "@nestjs/throttler";
@Module({
imports: [
ThrottlerModule.forRoot({
ttl: 60, // Time-to-live in seconds
limit: 10, // Max requests per TTL
}),
],
})
export class AppModule {}
// Example Controller
import { Controller, Get, UseGuards } from "@nestjs/common";
import { ThrottlerGuard } from "@nestjs/throttler";
@Controller("api")
@UseGuards(ThrottlerGuard)
export class ApiController {
@Get("test")
getTest() {
return "This is a rate-limited endpoint!";
}
}
Use Case: Protect APIs from being overwhelmed by too many requests.
5. Content Security Policy (CSP)
CSP defines which resources (scripts, styles, etc.) browsers can load to mitigate XSS attacks.
Implementation:
import * as helmet from "helmet";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://trusted-scripts.com"],
styleSrc: ["'self'", "https://trusted-styles.com"],
},
})
);
await app.listen(3000);
}
bootstrap();
Use Case: Enforce strong security policies to reduce vulnerabilities.
6. Helmet for HTTP Headers
Helmet secures the app by setting various HTTP headers like X-Frame-Options
, X-XSS-Protection
, and X-Content-Type-Options
.
Installation:
npm install --save helmet
Implementation:
import * as helmet from "helmet";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(helmet());
await app.listen(3000);
}
bootstrap();
Use Case: Add essential security headers to every response.
7. Custom Logger (Store Logs in Database)
Capture and store application logs directly into a database for analysis.
Implementation:
// log.schema.ts
@Schema()
export class Log extends Document {
@Prop()
level: string;
@Prop()
message: string;
@Prop({ default: Date.now })
timestamp: Date;
}
export const LogSchema = SchemaFactory.createForClass(Log);
// logger.service.ts
import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { Log } from "./log.schema";
@Injectable()
export class LoggerService {
constructor(@InjectModel(Log.name) private logModel: Model<Log>) {}
async log(level: string, message: string) {
const log = new this.logModel({ level, message });
await log.save();
}
}
Use Case: Maintain an audit trail and monitor critical events.
8. PM2 Logs into Database
PM2 is a process manager that can redirect logs to a database using Winston.
Implementation:
import { createLogger, format, transports } from "winston";
import "winston-mongodb";
const logger = createLogger({
level: "info",
format: format.combine(format.timestamp(), format.json()),
transports: [
new transports.MongoDB({
db: "mongodb://localhost/logs",
collection: "pm2_logs",
}),
],
});
logger.info("Application started successfully");
Use Case: Centralized logging for applications managed by PM2.
9. Environment Variables with .env
Using .env
files allows developers to manage configurations securely and keep sensitive information out of the codebase.
Installation:
npm install --save @nestjs/config
Implementation:
// .env
PORT=3000
DATABASE_URL=mongodb://localhost/nest
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, // Makes the configuration globally available
}),
],
})
export class AppModule {}
// Usage
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppService {
constructor(private configService: ConfigService) {}
getDatabaseURL(): string {
return this.configService.get<string>('DATABASE_URL');
}
}
Use Case: Securely manage application configuration, such as database URLs and API keys.
Conclusion
Incorporating these tools into your NestJS application ensures enhanced security, better monitoring, and robust functionality. Features like .env
integration, Swagger documentation, Helmet headers, and rate limiting prepare your application for production-grade scalability and reliability.