Sling Academy
Home/Node.js/How to Bulk Redirect URLs in NestJS

How to Bulk Redirect URLs in NestJS

Last updated: December 31, 2023

Introduction

Handling bulk URL redirects efficiently can be essential for both SEO and user experience when restructuring websites. This tutorial walks you through setting up bulk redirects in a NestJS application using modern TypeScript syntax.

Prerequisites

  • Basic knowledge of TypeScript and NestJS
  • NestJS CLI installed and ready
  • A new or existing NestJS project

Creating a Redirection Module

To get started, we’ll create a dedicated module for handling redirects:

$ nest generate module redirects

Implementing a Simple Redirect

In your redirects module, set up a simple redirect with the controller and a predefined list of URL mappings.

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

@Controller('*') // Catch-all route
export class RedirectsController {
  private readonly urlMap = new Map<string, string>([
    ['/old-path', '/new-path'],
    ['/previous-page', '/current-page'],
    // add more mappings as needed
  ]);

  @Get()
  @Redirect()
  handleRedirect(@Req() req): any {
    const targetUrl = this.urlMap.get(req.path);
    if (targetUrl) {
      return { url: targetUrl, statusCode: 301 };
    }
    // Handle case when no redirect is found (optional)
    // e.g., redirect to a 404 page or a default route
  }
}

Advanced Bulk Redirect Management

For managing a large number of redirects, store them in a data source such as a file or a database. Here’s how to fetch redirect mappings from a JSON file:

import { Injectable } from '@nestjs/common';
import * as redirectData from './redirects.json';

@Injectable()
export class RedirectsService {
  private readonly urlMap: Map<string, string>;

  constructor() {
    this.urlMap = new Map(Object.entries(redirectData));
  }

  getUrlMapping(path: string): string {
    return this.urlMap.get(path);
  }
}

In the ‘redirects.json’ file:

{
  "/very-old-url": "/new-sexy-url",
  "/old-product-page": "/new-product-page"
}

Now, wire this service with the redirects controller to handle the lookups dynamically:

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

@Controller('*')
export class RedirectsController {

  constructor(@Inject(RedirectsService) private redirectsService: RedirectsService) {}

  @Get()
  @Redirect()
  handleRedirect(@Req() req): any {
    const targetUrl = this.redirectsService.getUrlMapping(req.path);
    if (targetUrl) {
      return { url: targetUrl, statusCode: 301 };
    }
      // Handle no-redirect-found logic here
  }
}

Database-Driven Redirection

When redirects scale up, a database solution becomes essential. Integrate a database model and service to retrieve redirect mappings.

Create a redirect entity and a corresponding module and service to query the database:

// redirects.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Redirect {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  fromPath: string;

  @Column()
  toPath: string;
} // Implement the service and module using TypeORM repository

Then, modify the redirects service to use database fetching:

// ... other imports
import { RedirectRepository } from './redirect.repository';

// Inside the RedirectsService:

async getUrlMapping(path: string): Promise {
  const redirectEntity =  await this.redirectRepository.findOne({ fromPath: path });
  return redirectEntity?.toPath;
}

And update the controller:

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

// ... other imports

@Controller('*')
export class RedirectsController {

  // ...constructor and other methods

  @Get()
  @Redirect()
  async handleRedirect(@Req() req): Promise {
    const targetUrl = await this.redirectsService.getUrlMapping(req.path);
    if (targetUrl) {
      return { url: targetUrl, statusCode: 301 };
    }
      // Handle no-redirect-found logic here
  }
}

Handling Wildcard and Regex Patterns

For complex matching like wildcards or regular expressions, enhance your service method:

async getUrlMapping(path: string): Promise {
  // Check for exact matches first
  let redirectEntity = await this.redirectRepository.findOne({ fromPath: path });
  if (!redirectEntity) {
    // Seek wildcard or regex matches next
    // Logic for handling wildcards or regex matches
  }
  return redirectEntity?.toPath;
}

You can extend this by implementing regex-based redirect matching inside the service method. It’s a more complex solution that depends on the number and type of redirects you need to handle.

Testing Your Redirects

Once the redirect system is in place, write unit and e2e tests to ensure it maintains the expected behavior as your application scales and changes.

Conclusion

Bulk URL redirect handling in NestJS can be streamlined for a variety of complexities. By implementing simple redirects and progressively enhancing the system with external data sources and database integration, you can maintain robust redirection that scales seamlessly with your application’s growth.

Next Article: NestJS: How to Delete a File after Response is Sent to Client

Previous Article: How to Redirect to Another URL in NestJS

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