From 03563978bcf15a09114a35626769e61763edd941 Mon Sep 17 00:00:00 2001 From: "Micael Levi (@micalevisk)" Date: Tue, 17 May 2022 09:08:28 -0400 Subject: [PATCH] feat(common,core): make `HttpServer#applyVersionFilter` mandatory --- .../interfaces/http/http-server.interface.ts | 8 +- packages/core/adapters/http-adapter.ts | 9 +- packages/core/router/router-explorer.ts | 127 +-- .../core/test/router/router-explorer.spec.ts | 736 ------------------ packages/core/test/utils/noop-adapter.spec.ts | 10 +- .../adapters/express-adapter.ts | 6 +- .../adapters/fastify-adapter.ts | 13 +- 7 files changed, 30 insertions(+), 879 deletions(-) diff --git a/packages/common/interfaces/http/http-server.interface.ts b/packages/common/interfaces/http/http-server.interface.ts index 46a717d44bd..d2e27de83dd 100644 --- a/packages/common/interfaces/http/http-server.interface.ts +++ b/packages/common/interfaces/http/http-server.interface.ts @@ -74,13 +74,9 @@ export interface HttpServer { close(): any; getType(): string; init?(): Promise; - applyVersionFilter?( + applyVersionFilter( handler: Function, version: VersionValue, versioningOptions: VersioningOptions, - ): = any, TResponse = any>( - req: TRequest, - res: TResponse, - next: () => void, - ) => any; + ): (req: TRequest, res: TResponse, next: () => void) => Function; } diff --git a/packages/core/adapters/http-adapter.ts b/packages/core/adapters/http-adapter.ts index 526afab3890..449c9e68c54 100644 --- a/packages/core/adapters/http-adapter.ts +++ b/packages/core/adapters/http-adapter.ts @@ -1,5 +1,5 @@ -import { HttpServer, RequestMethod } from '@nestjs/common'; -import { RequestHandler } from '@nestjs/common/interfaces'; +import { HttpServer, RequestMethod, VersioningOptions } from '@nestjs/common'; +import { RequestHandler, VersionValue } from '@nestjs/common/interfaces'; import { CorsOptions, CorsOptionsDelegate, @@ -121,4 +121,9 @@ export abstract class AbstractHttpAdapter< | ((path: string, callback: Function) => any) | Promise<(path: string, callback: Function) => any>; abstract getType(): string; + abstract applyVersionFilter( + handler: Function, + version: VersionValue, + versioningOptions: VersioningOptions, + ): (req: TRequest, res: TResponse, next: () => void) => Function; } diff --git a/packages/core/router/router-explorer.ts b/packages/core/router/router-explorer.ts index ab0517dc50b..4a7dd3c39dd 100644 --- a/packages/core/router/router-explorer.ts +++ b/packages/core/router/router-explorer.ts @@ -334,132 +334,7 @@ export class RouterExplorer { ) { const { versioningOptions } = routePathMetadata; const version = this.routePathFactory.getVersion(routePathMetadata); - if (router?.applyVersionFilter) { - return router.applyVersionFilter(handler, version, versioningOptions); - } - /** - * TODO(v9): This was left for backward-compatibility and can be removed. - */ - return = any, TResponse = any>( - req: TRequest, - res: TResponse, - next: () => void, - ) => { - if (version === VERSION_NEUTRAL) { - return handler(req, res, next); - } - // URL Versioning is done via the path, so the filter continues forward - if (versioningOptions.type === VersioningType.URI) { - return handler(req, res, next); - } - - // Custom Extractor Versioning Handler - if (versioningOptions.type === VersioningType.CUSTOM) { - const extractedVersion = versioningOptions.extractor(req) as - | string - | string[] - | Array; - - if (Array.isArray(version)) { - if ( - Array.isArray(extractedVersion) && - version.filter( - extractedVersion.includes as ( - value: string | symbol, - index: number, - array: Array, - ) => boolean, - ).length - ) { - return handler(req, res, next); - } else if ( - isString(extractedVersion) && - version.includes(extractedVersion) - ) { - return handler(req, res, next); - } - } else { - if ( - Array.isArray(extractedVersion) && - extractedVersion.includes(version) - ) { - return handler(req, res, next); - } else if ( - isString(extractedVersion) && - version === extractedVersion - ) { - return handler(req, res, next); - } - } - } - - // Media Type (Accept Header) Versioning Handler - if (versioningOptions.type === VersioningType.MEDIA_TYPE) { - const MEDIA_TYPE_HEADER = 'Accept'; - const acceptHeaderValue: string | undefined = - req.headers?.[MEDIA_TYPE_HEADER] || - req.headers?.[MEDIA_TYPE_HEADER.toLowerCase()]; - - const acceptHeaderVersionParameter = acceptHeaderValue - ? acceptHeaderValue.split(';')[1] - : undefined; - - // No version was supplied - if (isUndefined(acceptHeaderVersionParameter)) { - if (Array.isArray(version)) { - if (version.includes(VERSION_NEUTRAL)) { - return handler(req, res, next); - } - } - } else { - const headerVersion = acceptHeaderVersionParameter.split( - versioningOptions.key, - )[1]; - - if (Array.isArray(version)) { - if (version.includes(headerVersion)) { - return handler(req, res, next); - } - } else if (isString(version)) { - if (version === headerVersion) { - return handler(req, res, next); - } - } - } - } - // Header Versioning Handler - else if (versioningOptions.type === VersioningType.HEADER) { - const customHeaderVersionParameter: string | undefined = - req.headers?.[versioningOptions.header] || - req.headers?.[versioningOptions.header.toLowerCase()]; - - // No version was supplied - if (isUndefined(customHeaderVersionParameter)) { - if (Array.isArray(version)) { - if (version.includes(VERSION_NEUTRAL)) { - return handler(req, res, next); - } - } - } else { - if (Array.isArray(version)) { - if (version.includes(customHeaderVersionParameter)) { - return handler(req, res, next); - } - } else if (isString(version)) { - if (version === customHeaderVersionParameter) { - return handler(req, res, next); - } - } - } - } - - if (!next) { - throw new InternalServerErrorException( - 'HTTP adapter does not support filtering on version', - ); - } - return next(); - }; + return router.applyVersionFilter(handler, version, versioningOptions); } private createCallbackProxy( diff --git a/packages/core/test/router/router-explorer.spec.ts b/packages/core/test/router/router-explorer.spec.ts index 5f534321007..1094d4e040d 100644 --- a/packages/core/test/router/router-explorer.spec.ts +++ b/packages/core/test/router/router-explorer.spec.ts @@ -1,5 +1,3 @@ -import { VERSION_NEUTRAL } from '@nestjs/common'; -import { VersionValue } from '@nestjs/common/interfaces'; import { expect } from 'chai'; import * as sinon from 'sinon'; import { Controller } from '../../../common/decorators/core/controller.decorator'; @@ -10,7 +8,6 @@ import { } from '../../../common/decorators/http/request-mapping.decorator'; import { RequestMethod } from '../../../common/enums/request-method.enum'; import { VersioningType } from '../../../common/enums/version-type.enum'; -import { VersioningOptions } from '../../../common/interfaces/version-options.interface'; import { Injector } from '../../../core/injector/injector'; import { ApplicationConfig } from '../../application-config'; import { ExecutionContextHost } from '../../helpers/execution-context-host'; @@ -363,737 +360,4 @@ describe('RouterExplorer', () => { }); }); }); - - describe('applyVersionFilter', () => { - describe('when the versioning type is URI', () => { - describe('and the version is VERSION_NEUTRAL', () => { - it('should return the handler', () => { - const version: VersionValue = VERSION_NEUTRAL; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.URI, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - - it('should return the handler', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.URI, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - - describe('when the versioning type is MEDIA_TYPE', () => { - it('should return next if there is no Media Type header', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: {} }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return next if there is no version in the Media Type header', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - describe('when the handler version is an array', () => { - describe('and the version has VERSION_NEUTRAL', () => { - it('should return the handler if there is no version in the Media Type header', () => { - const version: VersionValue = [VERSION_NEUTRAL]; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - it('should return next if the version in the Media Type header does not match the handler version', () => { - const version: VersionValue = ['1', '2', VERSION_NEUTRAL]; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;v=3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - }); - - it('should return next if the version in the Media Type header does not match the handler version', () => { - const version = ['1', '2']; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;v=3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the Media Type header matches the handler version', () => { - const version = ['1', '2']; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;v=1' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - - describe('when the handler version is a string', () => { - it('should return next if the version in the Media Type header does not match the handler version', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;v=3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the Media Type header matches the handler version', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.MEDIA_TYPE, - key: 'v=', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;v=1' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - }); - - describe('when the versioning type is CUSTOM', () => { - const extractor = (request: { headers: { accept?: string } }) => { - const match = request.headers.accept?.match(/v(\d+\.?\d*)\+json$/); - if (match) { - return match[1]; - } - return null; - }; - - it('should return next if there is no pertinent request object', () => { - const version = '1'; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: {} }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return next if there is no version in the request object value', () => { - const version = '1'; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/json;' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - describe('when the handler version is an array', () => { - it('should return next if the version in the request object value does not match the handler version', () => { - const version = ['1', '2']; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/foo.v3+json' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the request object value matches the handler version', () => { - const version = ['1', '2']; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/foo.v2+json' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - - describe('when the handler version is a string', () => { - it('should return next if the version in the request object value does not match the handler version', () => { - const version = '1'; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/foo.v2+json' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the request object value matches the handler version', () => { - const version = '1'; - const versioningOptions: VersioningOptions = { - type: VersioningType.CUSTOM, - extractor, - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { accept: 'application/foo.v1+json' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - }); - - describe('when the versioning type is HEADER', () => { - it('should return next if there is no Custom Header', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: {} }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return next if there is no version in the Custom Header', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - describe('when the handler version is an array', () => { - describe('and the version has VERSION_NEUTRAL', () => { - it('should return the handler if there is no version in the Custom Header', () => { - const version: VersionValue = [VERSION_NEUTRAL]; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - it('should return next if the version in the Custom Header does not match the handler version', () => { - const version: VersionValue = ['1', '2', VERSION_NEUTRAL]; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - }); - - it('should return next if the version in the Custom Header does not match the handler version', () => { - const version = ['1', '2']; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the Custom Header matches the handler version', () => { - const version = ['1', '2']; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '1' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - - describe('when the handler version is a string', () => { - it('should return next if the version in the Custom Header does not match the handler version', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '3' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - - it('should return the handler if the version in the Custom Header matches the handler version', () => { - const version = '1'; - const versioningOptions: RoutePathMetadata['versioningOptions'] = { - type: VersioningType.HEADER, - header: 'X-API-Version', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = { headers: { 'X-API-Version': '1' } }; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(handler.calledWith(req, res, next)).to.be.true; - }); - }); - }); - - describe('when versioning type is unrecognized', () => { - it('should throw an error if there is no next function', () => { - const version = '1'; - const versioningOptions: any = { - type: 'UNKNOWN', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = null; - - expect(() => versionFilter(req, res, next)).to.throw( - 'HTTP adapter does not support filtering on version', - ); - }); - - it('should return next', () => { - const version = '1'; - const versioningOptions: any = { - type: 'UNKNOWN', - }; - const handler = sinon.stub(); - - const routePathMetadata: RoutePathMetadata = { - methodVersion: version, - versioningOptions, - }; - const versionFilter = (routerBuilder as any).applyVersionFilter( - null, - routePathMetadata, - handler, - ); - - const req = {}; - const res = {}; - const next = sinon.stub(); - - versionFilter(req, res, next); - - expect(next.called).to.be.true; - }); - }); - }); }); diff --git a/packages/core/test/utils/noop-adapter.spec.ts b/packages/core/test/utils/noop-adapter.spec.ts index c2e73d09fd6..2f6d2db8722 100644 --- a/packages/core/test/utils/noop-adapter.spec.ts +++ b/packages/core/test/utils/noop-adapter.spec.ts @@ -1,4 +1,5 @@ -import { RequestMethod } from '@nestjs/common'; +import { RequestMethod, VersioningOptions } from '@nestjs/common'; +import { VersionValue } from '@nestjs/common/interfaces'; import { AbstractHttpAdapter } from '../../adapters'; export class NoopHttpAdapter extends AbstractHttpAdapter { @@ -25,4 +26,11 @@ export class NoopHttpAdapter extends AbstractHttpAdapter { getType() { return ''; } + applyVersionFilter( + handler: Function, + version: VersionValue, + versioningOptions: VersioningOptions, + ) { + return handler; + } } diff --git a/packages/platform-express/adapters/express-adapter.ts b/packages/platform-express/adapters/express-adapter.ts index 8cca8922c1e..8c7f1a387b7 100644 --- a/packages/platform-express/adapters/express-adapter.ts +++ b/packages/platform-express/adapters/express-adapter.ts @@ -4,12 +4,10 @@ import { RequestMethod, StreamableFile, VersioningType, -} from '@nestjs/common'; -import { VersioningOptions, - VersionValue, VERSION_NEUTRAL, -} from '@nestjs/common/interfaces'; +} from '@nestjs/common'; +import { VersionValue } from '@nestjs/common/interfaces'; import { CorsOptions, CorsOptionsDelegate, diff --git a/packages/platform-fastify/adapters/fastify-adapter.ts b/packages/platform-fastify/adapters/fastify-adapter.ts index 3113a4a29a0..25c61c7a357 100644 --- a/packages/platform-fastify/adapters/fastify-adapter.ts +++ b/packages/platform-fastify/adapters/fastify-adapter.ts @@ -6,8 +6,9 @@ import { StreamableFile, VersioningOptions, VersioningType, + VERSION_NEUTRAL, } from '@nestjs/common'; -import { VersionValue, VERSION_NEUTRAL } from '@nestjs/common/interfaces'; +import { VersionValue } from '@nestjs/common/interfaces'; import { CorsOptions, CorsOptionsDelegate, @@ -68,7 +69,11 @@ type FastifyHttpsOptions< https: https.ServerOptions; }; -type VersionedRoute = Function & { +type VersionedRoute = (( + req: TRequest, + res: TResponse, + next: Function, +) => Function) & { version: VersionValue; versioningOptions: VersioningOptions; }; @@ -254,11 +259,11 @@ export class FastifyAdapter< handler: Function, version: VersionValue, versioningOptions: VersioningOptions, - ) { + ): VersionedRoute { if (!this.versioningOptions) { this.versioningOptions = versioningOptions; } - const versionedRoute = handler as VersionedRoute; + const versionedRoute = handler as VersionedRoute; versionedRoute.version = version; return versionedRoute; }