Lesson 17-NestJS Versioning

Versioning Types

URI versioning specifies the version number through the URL path.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { VersioningType } from '@nestjs/common';
import { APP_VERSIONING } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        // Middleware versioning example
        console.log('Middleware version:', req.version);
        next();
      })
      .forRoutes('*');
  }
}

// app.controller.ts
import { Controller, Get, Version, VERSION_NEUTRAL } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Version('1')
  getHelloV1(): string {
    return 'Hello World V1!';
  }

  @Get()
  @Version('2')
  getHelloV2(): string {
    return 'Hello World V2!';
  }

  @Get()
  @Version(VERSION_NEUTRAL)
  getHelloNeutral(): string {
    return 'Hello World Neutral!';
  }
}

Header Versioning Type

Header versioning specifies the version number through HTTP request headers.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { VersioningType } from '@nestjs/common';
import { APP_VERSIONING } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        // Middleware versioning example
        console.log('Middleware version:', req.version);
        next();
      })
      .forRoutes('*');
  }
}

// app.controller.ts
import { Controller, Get, Version, VERSION_NEUTRAL } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Version('1')
  getHelloV1(): string {
    return 'Hello World V1!';
  }

  @Get()
  @Version('2')
  getHelloV2(): string {
    return 'Hello World V2!';
  }

  @Get()
  @Version(VERSION_NEUTRAL)
  getHelloNeutral(): string {
    return 'Hello World Neutral!';
  }
}

Media Type Versioning Type

Media type versioning specifies the version number through the Accept request header.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { VersioningType } from '@nestjs/common';
import { APP_VERSIONING } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        // Middleware versioning example
        console.log('Middleware version:', req.version);
        next();
      })
      .forRoutes('*');
  }
}

// app.controller.ts
import { Controller, Get, Version, VERSION_NEUTRAL } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Version('1')
  getHelloV1(): string {
    return 'Hello World V1!';
  }

  @Get()
  @Version('2')
  getHelloV2(): string {
    return 'Hello World V2!';
  }

  @Get()
  @Version(VERSION_NEUTRAL)
  getHelloNeutral(): string {
    return 'Hello World Neutral!';
  }
}

Custom Versioning Type

You can create a custom versioning type, such as using a custom request header or query parameter.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { VersioningType } from '@nestjs/common';
import { APP_VERSIONING } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        // Middleware versioning example
        console.log('Middleware version:', req.version);
        next();
      })
      .forRoutes('*');
  }
}

// app.controller.ts
import { Controller, Get, Version, VERSION_NEUTRAL } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Version('1')
  getHelloV1(): string {
    return 'Hello World V1!';
  }

  @Get()
  @Version('2')
  getHelloV2(): string {
    return 'Hello World V2!';
  }

  @Get()
  @Version(VERSION_NEUTRAL)
  getHelloNeutral(): string {
    return 'Hello World Neutral!';
  }
}

Usage

  • Controller Versioning: Set versions at the controller level.
  • Route Versioning: Set versions at the route level.
  • Multiple Versions: Support multiple versions simultaneously.
  • Version Neutral: Use VERSION_NEUTRAL to mark routes without a version.
  • Global Default Version: Set a global default version.
  • Middleware Versioning: Access version information in middleware.

Example
Suppose you have an application with two API versions: V1 and V2. We will use URI versioning and set the global default version to V1.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { VersioningType } from '@nestjs/common';
import { APP_VERSIONING } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        // Middleware versioning example
        console.log('Middleware version:', req.version);
        next();
      })
      .forRoutes('*');
  }
}

// app.controller.ts
import { Controller, Get, Version, VERSION_NEUTRAL } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Version('1')
  getHelloV1(): string {
    return 'Hello World V1!';
  }

  @Get()
  @Version('2')
  getHelloV2(): string {
    return 'Hello World V2!';
  }

  @Get()
  @Version(VERSION_NEUTRAL)
  getHelloNeutral(): string {
    return 'Hello World Neutral!';
  }
}

Setting Global Version

Set the global version in the main.ts file:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableVersioning({
    type: VersioningType.URI, // Set versioning type to URI
    defaultVersion: ['1'], // Set global default version to V1
  });
  await app.listen(3000);
}
bootstrap();

Request Examples

URI Versioning:

  • GET /v1/hello returns “Hello World V1!”
  • GET /v2/hello returns “Hello World V2!”

Header Versioning:

  • GET /hello with header X-Version: 1 returns “Hello World V1!”
  • GET /hello with header X-Version: 2 returns “Hello World V2!”

Media Type Versioning:

  • GET /hello with header Accept: application/vnd.api+json;version=1 returns “Hello World V1!”
  • GET /hello with header Accept: application/vnd.api+json;version=2 returns “Hello World V2!”
Share your love