kimsengduong / nestjs-url-generator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

URL Generation Module for NestJS

CodeFactor NPM Version NPM Downloads License

Description

URL Generation is used to dynamically generate URL that point to NestJS controller method (Route).

nestjs-url-generator can generate plain and signed URLs

Installation

npm i --save nestjs-url-generator

Or if you use Yarn:

yarn add nestjs-url-generator

Requirements

nestjs-url-generator is built to work with Nest 7 and newer versions.

Basic Usage

Include Module

First you need to import [UrlGeneratorModule]:

app.module.ts

import { UrlGeneratorModule } from 'nestjs-url-generator';

@Module({
  imports: [
    UrlGeneratorModule.forRoot({
      secret: 'secret', // optional, required only for signed URL
      appUrl: 'localhost:3000',
    }),
  ],
})
export class ApplicationModule {}

Or Async Import With .ENV usage

.ENV

APP_KEY=secret
APP_URL=localhost:3000

signed-url.config.ts

import { UrlGeneratorModuleOptions } from 'nestjs-url-generator';

export function urlGeneratorModuleConfig(): UrlGeneratorModuleOptions {
  return {
    secret: process.env.APP_KEY,
    appUrl: process.env.APP_URL,
  };
}

app.module.ts

import { UrlGeneratorModule } from 'nestjs-url-generator';

@Module({
  imports: [
    ConfigModule.forRoot(),
    UrlGeneratorModule.forRootAsync({
      useFactory: () => urlGeneratorModuleConfig(),
    }),
  ],
})
export class ApplicationModule {}

Using Service

Now you need to register the service, by injecting it to the constructor. There are two methods for generating url:

generateUrlFromController({
  controller,
  controllerMethod,
  /*?*/ query,
  /*?*/ params,
});

generateUrlFromPath({
  relativePath,
  /*?*/ query,
  /*?*/ params,
});

app.controller.ts

import { UrlGeneratorService } from 'nestjs-url-generator';

@Controller()
export class AppController {
  constructor(private readonly urlGeneratorService: UrlGeneratorService) {}

  @Get('makeUrl')
  async makeUrl(): Promise<string> {
    const params = {
      version: '1.0',
      userId: 12,
    };

    const query = {
      email: 'email@email',
    };

    // This will generate:
    // localhost:3000/emailVerification/1.0/12?email=email%40email
    return this.urlGeneratorService.generateUrlFromController({
      controller: AppController,
      controllerMethod: AppController.prototype.emailVerification,
      query: query,
      params: params,
    });
  }
}

Generate Signed URL

There are two methods for generating url:

signedControllerUrl({
  controller,
  controllerMethod,
  /*?*/ expirationDate,
  /*?*/ query,
  /*?*/ params,
});

signedUrl({
  relativePath,
  /*?*/ expirationDate,
  /*?*/ query,
  /*?*/ params,
});

app.controller.ts

import { UrlGeneratorService } from 'nestjs-url-generator';

@Controller()
export class AppController {
  constructor(private readonly urlGeneratorService: UrlGeneratorService) {}

  @Get('makeSignedUrl')
  async makeSignedUrl(): Promise<string> {
    // This will generate:
    // localhost:3000/emailVerification?
    // expirationDate=2021-12-12T00%3A00%3A00.000Z&
    // signed=84b5a021c433d0ee961932ac0ec04d5dd5ffd6f7fdb60b46083cfe474dfae3c0
    return this.urlGeneratorService.signedControllerUrl({
      controller: AppController,
      controllerMethod: AppController.prototype.emailVerification,
      expirationDate: new Date('2021-12-12'),
      // or using DateTime library of your choice
      // will be expired 30 minutes after it was created
      expirationDate: dayjs().add(30, 'minute').toDate(),
    });
  }
}
  • [expirationDate] and [signed] query keys are used for signed URL.

  • By default, the signed URLs lives forever. You can add expiration date to them at the time of generating one.

Reminder

The difference between params & query in ExpressJS


Using Guard

You can use SignedUrlGuard to verify the signed url in controller.

If the url has been tampered or when the expiration date is due, then a Forbidden exception will be thrown.

app.controller.ts

import { UrlGeneratorGuard } from 'nestjs-url-generator';

@Controller()
export class AppController {
  constructor(private readonly urlGeneratorService: UrlGeneratorService) {}

  @Get('emailVerification')
  @UseGuards(UrlGeneratorGuard)
  async emailVerification(): Promise<string> {
    return 'You emailed has been verified.';
  }
}

Note

  • Changing the secret key will invalidate all signed urls
  • Signed URL is typically used for unsubscribe email, email verification, sign file permission, and more.

Generating Keys using node REPL

require('crypto').randomBytes(64, (err, buf) => {
  if (err) throw err;
  console.log(`${buf.length} bytes of random data: ${buf.toString('base64')}`);
  process.exit();
});

TODO

  • Create test (expiration, query clash, tampered, with or without globalPrefix, request with query & param)
  • Automate CI, npm run build, push, npm publish
  • Add warning if target for signerUrl doesn't have guard

About

License:MIT License


Languages

Language:TypeScript 95.0%Language:JavaScript 5.0%