Sling Academy
Home/Node.js/How to get client IP address in NestJS

How to get client IP address in NestJS

Last updated: January 02, 2024

Overview

Learning how to retrieve a client’s IP address in NestJS is essential for many web applications that depend on geolocation, rate limiting, logging, or authentication. This article delves into several methods to achieve this, tailored for NestJS applications.

Prerequisites

Before we begin, ensure you have the following installed:

  • Node.js (>= 10.x)
  • NestJS CLI

Also, you should have a basic understanding of TypeScript and NestJS fundamentals to follow along effectively.

Basic Method: Using Request Object

To begin, we will look at the most straightforward approach – accessing the IP directly from the request object.

import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('get-ip')
export class IpController {
  @Get()
  public getClientIp(@Req() request: Request): string {
    return request.ip;
  }
}

Note that NestJS uses Express under the hood, and the request.ip is a feature of Express that captures the client’s IP address.

Using Request Headers

In scenarios where your app is behind a proxy or load balancer, retrieving the IP directly from the request might not give you the actual client IP due to IP masquerading.

To overcome this, inspect the X-Forwarded-For header, which proxies typically use to forward the originating IP address of a client connecting to a web server.

import { Controller, Get, Headers } from '@nestjs/common';

@Controller('get-ip')
export class IpController {
  @Get('header')
  public getClientIpThroughHeader(@Headers('x-forwarded-for') ip: string): string {
    const clientIp = ip.split(',')[0];
    return clientIp;
  }
}

This method splits the X-Forwarded-For header since it can contain a list of IPs if the request passed through multiple proxies.

Creating a Custom Decorator

If getting the IP address is a common task in your application, creating a custom decorator to encapsulate this logic is a good approach.

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const ClientIp = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): string => {
    const request = ctx.switchToHttp().getRequest();
    const ip = (request.headers['x-forwarded-for'] || '').split(',')[0] || request.ip;
    return ip;
  },
);

Using this decorator, the method in any controller can now look like:

import { Controller, Get} from '@nestjs/common';

@Controller('get-ip')
export class IpController {
  @Get('decorator')
  public getClientIp(@ClientIp() ip: string): string {
    return ip;
  }
}

Advanced: IP Extraction in Middleware

For applications needing the IP for various middleware-level operations like rate limiting or logging, you can decode the IP at the middleware stage and make it universally available in the request object.

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

@Injectable()
export class IpMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    req['clientIp'] = (req.headers['x-forwarded-for'] || '').split(',')[0].trim() || req.connection.remoteAddress;
    next();
  }
}

To apply this middleware globally, alter your main.ts file:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { IpMiddleware } from './ip.middleware';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.use(new IpMiddleware().use);
  await app.listen(3000);
}
bootstrap();

Assessing Client’s IP with Guards

NestJS Guards can also be an effective location for IP assessment, especially when you want to add additional authentication logic based on IP addresses.

... 
// The implementation of a guard that checks the IP address would typically involve an canActivate method that contains similar logic to the above examples.

Dealing with IPv6 and Compatibility

The approaches above work for both IPv4 and IPv6. However, IPv6 addresses are sometimes accompanied by a prefix which you may need to strip off depending on your use case. Care should be taken to properly parse and format IP addresses in such scenarios.

Using a Trust Proxy

If you’re utilizing a service like Heroku or other cloud providers, you might need to enable trust proxy settings inside your NestJS app to handle IP retrieval securely and correctly.

// main.ts
const app = await NestFactory.create(AppModule);
app.set('trust proxy', true);
...

By setting ‘trust proxy’, we tell Express to trust the headers set by our proxy and thus the forwarded IP addresses.

Conclusion

Understanding the network configuration of your deployment environment is key to correctly implementing client IP address extraction in a NestJS application. Different scenarios may require different approaches, and it’s important to consider the implications of each to ensure that security and functionality are upheld. With the techniques discussed in this tutorial, you should be positioned to effectively manage and use IP information within your NestJS applications.

Next Article: How to Deploy a NestJS Application to Digital Ocean

Previous Article: NestJS & SQLite: A Basic CRUD Example

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates