mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
add host option for @Controller
This commit is contained in:
@@ -40,6 +40,17 @@ describe('Hello world (express instance)', () => {
|
||||
.expect('Hello world!');
|
||||
});
|
||||
|
||||
it(`/GET { host: ":tenant.example.com" } not matched`, () => {
|
||||
return request(server)
|
||||
.get('/host')
|
||||
.expect(404)
|
||||
.expect({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Cannot GET /host',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
import { fail } from 'assert';
|
||||
|
||||
describe('Hello world (fastify adapter)', () => {
|
||||
let app: NestFastifyApplication;
|
||||
@@ -47,6 +48,27 @@ describe('Hello world (fastify adapter)', () => {
|
||||
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
|
||||
});
|
||||
|
||||
it(`/GET { host: ":tenant.example.com" } not matched`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/host',
|
||||
})
|
||||
.then(
|
||||
({ payload }) => {
|
||||
fail(`Unexpected success: ${payload}`);
|
||||
},
|
||||
err => {
|
||||
expect(err.message).to.be.eql({
|
||||
error: 'Internal Server Error',
|
||||
message:
|
||||
'HTTP Adapter does not support filtering on { host: "host.example.com" }',
|
||||
statusCode: 500,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -10,42 +10,60 @@ describe('Hello world (default adapter)', () => {
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [ApplicationModule],
|
||||
})
|
||||
.compile();
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('/GET', () => {
|
||||
it(`should return "Hello world!"`, () => {
|
||||
return request(server)
|
||||
.get('/hello')
|
||||
.expect(200)
|
||||
.expect('Hello world!');
|
||||
[
|
||||
{
|
||||
host: 'example.com',
|
||||
path: '/hello',
|
||||
greeting: 'Hello world!',
|
||||
},
|
||||
{
|
||||
host: 'host.example.com',
|
||||
path: '/host',
|
||||
greeting: 'Host Greeting!',
|
||||
},
|
||||
].forEach(({ host, path, greeting }) => {
|
||||
describe(`host=${host}`, () => {
|
||||
describe('/GET', () => {
|
||||
it(`should return "${greeting}"`, () => {
|
||||
return request(server)
|
||||
.get(path)
|
||||
.set('Host', host)
|
||||
.expect(200)
|
||||
.expect(greeting);
|
||||
});
|
||||
|
||||
it(`should attach response header`, () => {
|
||||
return request(server)
|
||||
.get(path)
|
||||
.set('Host', host)
|
||||
.expect(200)
|
||||
.expect('Authorization', 'Bearer');
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (Promise/async) returns "${greeting}"`, () => {
|
||||
return request(server)
|
||||
.get(`${path}/async`)
|
||||
.set('Host', host)
|
||||
.expect(200)
|
||||
.expect(greeting);
|
||||
});
|
||||
|
||||
it(`/GET (Observable stream) "${greeting}"`, () => {
|
||||
return request(server)
|
||||
.get(`${path}/stream`)
|
||||
.set('Host', host)
|
||||
.expect(200)
|
||||
.expect(greeting);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should attach response header`, () => {
|
||||
return request(server)
|
||||
.get('/hello')
|
||||
.expect(200)
|
||||
.expect('Authorization', 'Bearer');
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (Promise/async)`, () => {
|
||||
return request(server)
|
||||
.get('/hello/async')
|
||||
.expect(200)
|
||||
.expect('Hello world!');
|
||||
});
|
||||
|
||||
it(`/GET (Observable stream)`, () => {
|
||||
return request(server)
|
||||
.get('/hello/stream')
|
||||
.expect(200)
|
||||
.expect('Hello world!');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
||||
@@ -10,15 +10,14 @@ describe('Hello world (default adapter)', () => {
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [ApplicationModule],
|
||||
})
|
||||
.compile();
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`should execute locally injected pipe`, () => {
|
||||
it(`host=example.com should execute locally injected pipe by HelloController`, () => {
|
||||
return request(server)
|
||||
.get('/hello/local-pipe/1')
|
||||
.expect(200)
|
||||
@@ -27,6 +26,28 @@ describe('Hello world (default adapter)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it(`host=host.example.com should execute locally injected pipe by HostController`, () => {
|
||||
return request(server)
|
||||
.get('/host/local-pipe/1')
|
||||
.set('Host', 'host.example.com')
|
||||
.expect(200)
|
||||
.expect({
|
||||
id: '1',
|
||||
host: true,
|
||||
});
|
||||
});
|
||||
|
||||
it(`should return 404 for mismatched host`, () => {
|
||||
return request(server)
|
||||
.get('/host/local-pipe/1')
|
||||
.expect(404)
|
||||
.expect({
|
||||
error: 'Not Found',
|
||||
message: 'Cannot GET /host/local-pipe/1',
|
||||
statusCode: 404,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HelloModule } from './hello/hello.module';
|
||||
import { HostModule } from './host/host.module';
|
||||
|
||||
@Module({
|
||||
imports: [HelloModule],
|
||||
imports: [HelloModule, HostModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
|
||||
10
integration/hello-world/src/host/dto/test.dto.ts
Normal file
10
integration/hello-world/src/host/dto/test.dto.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
|
||||
|
||||
export class TestDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
string: string;
|
||||
|
||||
@IsNumber()
|
||||
number: number;
|
||||
}
|
||||
36
integration/hello-world/src/host/host.controller.ts
Normal file
36
integration/hello-world/src/host/host.controller.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Controller, Get, Header, Param } from '@nestjs/common';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { HostService } from './host.service';
|
||||
import { UserByIdPipe } from './users/user-by-id.pipe';
|
||||
|
||||
@Controller({
|
||||
path: 'host',
|
||||
host: 'host.example.com',
|
||||
})
|
||||
export class HostController {
|
||||
constructor(private readonly hostService: HostService) {}
|
||||
|
||||
@Get()
|
||||
@Header('Authorization', 'Bearer')
|
||||
greeting(): string {
|
||||
return this.hostService.greeting();
|
||||
}
|
||||
|
||||
@Get('async')
|
||||
async asyncGreeting(): Promise<string> {
|
||||
return await this.hostService.greeting();
|
||||
}
|
||||
|
||||
@Get('stream')
|
||||
streamGreeting(): Observable<string> {
|
||||
return of(this.hostService.greeting());
|
||||
}
|
||||
|
||||
@Get('local-pipe/:id')
|
||||
localPipe(
|
||||
@Param('id', UserByIdPipe)
|
||||
user: any,
|
||||
): any {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
10
integration/hello-world/src/host/host.module.ts
Normal file
10
integration/hello-world/src/host/host.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HostController } from './host.controller';
|
||||
import { HostService } from './host.service';
|
||||
import { UsersService } from './users/users.service';
|
||||
|
||||
@Module({
|
||||
controllers: [HostController],
|
||||
providers: [HostService, UsersService],
|
||||
})
|
||||
export class HostModule {}
|
||||
8
integration/hello-world/src/host/host.service.ts
Normal file
8
integration/hello-world/src/host/host.service.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class HostService {
|
||||
greeting(): string {
|
||||
return 'Host Greeting!';
|
||||
}
|
||||
}
|
||||
11
integration/hello-world/src/host/users/user-by-id.pipe.ts
Normal file
11
integration/hello-world/src/host/users/user-by-id.pipe.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
|
||||
import { UsersService } from './users.service';
|
||||
|
||||
@Injectable()
|
||||
export class UserByIdPipe implements PipeTransform<string> {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
|
||||
transform(value: string, metadata: ArgumentMetadata) {
|
||||
return this.usersService.findById(value);
|
||||
}
|
||||
}
|
||||
8
integration/hello-world/src/host/users/users.service.ts
Normal file
8
integration/hello-world/src/host/users/users.service.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
findById(id: string) {
|
||||
return { id, host: true };
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ export const METADATA = {
|
||||
|
||||
export const SHARED_MODULE_METADATA = '__module:shared__';
|
||||
export const GLOBAL_MODULE_METADATA = '__module:global__';
|
||||
export const HOST_METADATA = 'host';
|
||||
export const PATH_METADATA = 'path';
|
||||
export const PARAMTYPES_METADATA = 'design:paramtypes';
|
||||
export const SELF_DECLARED_DEPS_METADATA = 'self:paramtypes';
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { PATH_METADATA, SCOPE_OPTIONS_METADATA } from '../../constants';
|
||||
import {
|
||||
HOST_METADATA,
|
||||
PATH_METADATA,
|
||||
SCOPE_OPTIONS_METADATA,
|
||||
} from '../../constants';
|
||||
import { isString, isUndefined } from '../../utils/shared.utils';
|
||||
import { ScopeOptions } from './../../interfaces/scope-options.interface';
|
||||
|
||||
@@ -15,6 +19,15 @@ export interface ControllerOptions extends ScopeOptions {
|
||||
* @see [Routing](https://docs.nestjs.com/controllers#routing)
|
||||
*/
|
||||
path?: string;
|
||||
|
||||
/**
|
||||
* Specifies an optional HTTP Request host filter. When configured, methods
|
||||
* within the controller will only be routed if the request host matches the
|
||||
* specified value.
|
||||
*
|
||||
* @see [Routing](https://docs.nestjs.com/controllers#routing)
|
||||
*/
|
||||
host?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,14 +140,19 @@ export function Controller(
|
||||
prefixOrOptions?: string | ControllerOptions,
|
||||
): ClassDecorator {
|
||||
const defaultPath = '/';
|
||||
const [path, scopeOptions] = isUndefined(prefixOrOptions)
|
||||
? [defaultPath, undefined]
|
||||
const [path, host, scopeOptions] = isUndefined(prefixOrOptions)
|
||||
? [defaultPath, undefined, undefined]
|
||||
: isString(prefixOrOptions)
|
||||
? [prefixOrOptions, undefined]
|
||||
: [prefixOrOptions.path || defaultPath, { scope: prefixOrOptions.scope }];
|
||||
? [prefixOrOptions, undefined, undefined]
|
||||
: [
|
||||
prefixOrOptions.path || defaultPath,
|
||||
prefixOrOptions.host,
|
||||
{ scope: prefixOrOptions.scope },
|
||||
];
|
||||
|
||||
return (target: object) => {
|
||||
Reflect.defineMetadata(PATH_METADATA, path, target);
|
||||
Reflect.defineMetadata(HOST_METADATA, host, target);
|
||||
Reflect.defineMetadata(SCOPE_OPTIONS_METADATA, scopeOptions, target);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,19 +3,45 @@ import { Controller } from '../../decorators/core/controller.decorator';
|
||||
|
||||
describe('@Controller', () => {
|
||||
const reflectedPath = 'test';
|
||||
const reflectedHost = 'api.example.com';
|
||||
|
||||
@Controller(reflectedPath)
|
||||
class Test {}
|
||||
|
||||
@Controller()
|
||||
class EmptyDecorator {}
|
||||
|
||||
@Controller({ path: reflectedPath, host: reflectedHost })
|
||||
class PathAndHostDecorator {}
|
||||
|
||||
@Controller({ host: reflectedHost })
|
||||
class HostOnlyDecorator {}
|
||||
|
||||
it('should enhance controller with expected path metadata', () => {
|
||||
const path = Reflect.getMetadata('path', Test);
|
||||
expect(path).to.be.eql(reflectedPath);
|
||||
const path2 = Reflect.getMetadata('path', PathAndHostDecorator);
|
||||
expect(path2).to.be.eql(reflectedPath);
|
||||
});
|
||||
|
||||
it('should enhance controller with expected host metadata', () => {
|
||||
const host = Reflect.getMetadata('host', PathAndHostDecorator);
|
||||
expect(host).to.be.eql(reflectedHost);
|
||||
const host2 = Reflect.getMetadata('host', HostOnlyDecorator);
|
||||
expect(host2).to.be.eql(reflectedHost);
|
||||
});
|
||||
|
||||
it('should set default path when no object passed as param', () => {
|
||||
const path = Reflect.getMetadata('path', EmptyDecorator);
|
||||
expect(path).to.be.eql('/');
|
||||
const path2 = Reflect.getMetadata('path', HostOnlyDecorator);
|
||||
expect(path2).to.be.eql('/');
|
||||
});
|
||||
|
||||
it('should not set host when no host passed as param', () => {
|
||||
const host = Reflect.getMetadata('host', Test);
|
||||
expect(host).to.be.undefined;
|
||||
const host2 = Reflect.getMetadata('host', EmptyDecorator);
|
||||
expect(host2).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,8 +8,8 @@ export const MODULE_INIT_MESSAGE = (
|
||||
export const ROUTE_MAPPED_MESSAGE = (path: string, method: string | number) =>
|
||||
`Mapped {${path}, ${RequestMethod[method]}} route`;
|
||||
|
||||
export const CONTROLLER_MAPPING_MESSAGE = (name: string, path: string) =>
|
||||
`${name} {${path}}:`;
|
||||
export const CONTROLLER_MAPPING_MESSAGE = (name: string, host: string, path: string) =>
|
||||
`${name} {${host || '<any>'}, ${path}}:`;
|
||||
|
||||
export const INVALID_EXECUTION_CONTEXT = (
|
||||
methodName: string,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { HttpServer } from '@nestjs/common';
|
||||
import { METHOD_METADATA, PATH_METADATA } from '@nestjs/common/constants';
|
||||
import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
|
||||
import { InternalServerErrorException } from '@nestjs/common/exceptions';
|
||||
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
|
||||
import { Type } from '@nestjs/common/interfaces/type.interface';
|
||||
import { Logger } from '@nestjs/common/services/logger.service';
|
||||
@@ -33,6 +34,7 @@ import { REQUEST_CONTEXT_ID } from './request/request-constants';
|
||||
import { RouteParamsFactory } from './route-params-factory';
|
||||
import { RouterExecutionContext } from './router-execution-context';
|
||||
import { RouterProxy, RouterProxyCallback } from './router-proxy';
|
||||
import * as pathToRegexp from 'path-to-regexp';
|
||||
|
||||
export interface RoutePathProperties {
|
||||
path: string[];
|
||||
@@ -72,6 +74,7 @@ export class RouterExplorer {
|
||||
module: string,
|
||||
applicationRef: T,
|
||||
basePath: string,
|
||||
host: string,
|
||||
) {
|
||||
const { instance } = instanceWrapper;
|
||||
const routerPaths = this.scanForPaths(instance);
|
||||
@@ -81,6 +84,7 @@ export class RouterExplorer {
|
||||
instanceWrapper,
|
||||
module,
|
||||
basePath,
|
||||
host,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -146,6 +150,7 @@ export class RouterExplorer {
|
||||
instanceWrapper: InstanceWrapper,
|
||||
module: string,
|
||||
basePath: string,
|
||||
host: string,
|
||||
) {
|
||||
(routePaths || []).forEach(pathProperties => {
|
||||
const { path, requestMethod } = pathProperties;
|
||||
@@ -155,6 +160,7 @@ export class RouterExplorer {
|
||||
instanceWrapper,
|
||||
module,
|
||||
basePath,
|
||||
host,
|
||||
);
|
||||
path.forEach(p =>
|
||||
this.logger.log(ROUTE_MAPPED_MESSAGE(p, requestMethod)),
|
||||
@@ -168,6 +174,7 @@ export class RouterExplorer {
|
||||
instanceWrapper: InstanceWrapper,
|
||||
moduleKey: string,
|
||||
basePath: string,
|
||||
host: string,
|
||||
) {
|
||||
const {
|
||||
path: paths,
|
||||
@@ -185,35 +192,56 @@ export class RouterExplorer {
|
||||
|
||||
const isRequestScoped = !instanceWrapper.isDependencyTreeStatic();
|
||||
const module = this.container.getModuleByKey(moduleKey);
|
||||
const handler = isRequestScoped
|
||||
? this.createRequestScopedHandler(
|
||||
instanceWrapper,
|
||||
requestMethod,
|
||||
module,
|
||||
moduleKey,
|
||||
methodName,
|
||||
)
|
||||
: this.createCallbackProxy(
|
||||
instance,
|
||||
targetCallback,
|
||||
methodName,
|
||||
moduleKey,
|
||||
requestMethod,
|
||||
);
|
||||
const hostHandler = this.applyHostFilter(host, handler);
|
||||
|
||||
if (isRequestScoped) {
|
||||
const handler = this.createRequestScopedHandler(
|
||||
instanceWrapper,
|
||||
requestMethod,
|
||||
module,
|
||||
moduleKey,
|
||||
methodName,
|
||||
);
|
||||
|
||||
paths.forEach(path => {
|
||||
const fullPath = stripSlash(basePath) + path;
|
||||
routerMethod(stripSlash(fullPath) || '/', handler);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const proxy = this.createCallbackProxy(
|
||||
instance,
|
||||
targetCallback,
|
||||
methodName,
|
||||
moduleKey,
|
||||
requestMethod,
|
||||
);
|
||||
paths.forEach(path => {
|
||||
const fullPath = stripSlash(basePath) + path;
|
||||
routerMethod(stripSlash(fullPath) || '/', proxy);
|
||||
routerMethod(stripSlash(fullPath) || '/', hostHandler);
|
||||
});
|
||||
}
|
||||
|
||||
private applyHostFilter(host, handler) {
|
||||
if (!host) {
|
||||
return (req, res, next) => {
|
||||
req.hosts = {};
|
||||
return handler(req, res, next);
|
||||
};
|
||||
}
|
||||
|
||||
const httpAdapterRef = this.container.getHttpAdapterRef();
|
||||
const keys = [];
|
||||
const re = pathToRegexp(host, keys);
|
||||
|
||||
return (req, res, next) => {
|
||||
req.hosts = {};
|
||||
const hostname = httpAdapterRef.getRequestHostname(req) || '';
|
||||
const match = hostname.match(re);
|
||||
if (match) {
|
||||
keys.forEach((key, i) => req.hosts[key.name] = match[i + 1]);
|
||||
return handler(req, res, next);
|
||||
}
|
||||
if (!next) {
|
||||
throw new InternalServerErrorException(`HTTP Adapter does not support filtering on { host: "${host}" }`);
|
||||
}
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
private createCallbackProxy(
|
||||
instance: Controller,
|
||||
callback: RouterProxyCallback,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||
import { MODULE_PATH } from '@nestjs/common/constants';
|
||||
import { HOST_METADATA, MODULE_PATH } from '@nestjs/common/constants';
|
||||
import { HttpServer, Type } from '@nestjs/common/interfaces';
|
||||
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
|
||||
import { Logger } from '@nestjs/common/services/logger.service';
|
||||
@@ -60,18 +60,19 @@ export class RoutesResolver implements Resolver {
|
||||
) {
|
||||
routes.forEach(instanceWrapper => {
|
||||
const { metatype } = instanceWrapper;
|
||||
const host = Reflect.getMetadata(HOST_METADATA, metatype);
|
||||
const path = this.routerBuilder.extractRouterPath(
|
||||
metatype as Type<any>,
|
||||
basePath,
|
||||
);
|
||||
const controllerName = metatype.name;
|
||||
|
||||
this.logger.log(CONTROLLER_MAPPING_MESSAGE(controllerName, path));
|
||||
this.logger.log(CONTROLLER_MAPPING_MESSAGE(controllerName, host, path));
|
||||
this.routerBuilder.explore(
|
||||
instanceWrapper,
|
||||
moduleName,
|
||||
applicationRef,
|
||||
path,
|
||||
host,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('RouterExplorer', () => {
|
||||
{ path: ['foo', 'bar'], requestMethod: RequestMethod.GET },
|
||||
];
|
||||
|
||||
routerBuilder.applyPathsToRouterProxy(null, paths as any, null, '', '');
|
||||
routerBuilder.applyPathsToRouterProxy(null, paths as any, null, '', '', '');
|
||||
|
||||
expect(bindStub.calledWith(null, paths[0], null)).to.be.true;
|
||||
expect(bindStub.callCount).to.be.eql(paths.length);
|
||||
|
||||
@@ -20,6 +20,12 @@ describe('RoutesResolver', () => {
|
||||
public anotherTest() {}
|
||||
}
|
||||
|
||||
@Controller({ host: 'api.example.com' })
|
||||
class TestHostRoute {
|
||||
@Get()
|
||||
public getTest() {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
controllers: [TestRoute],
|
||||
})
|
||||
@@ -63,7 +69,7 @@ describe('RoutesResolver', () => {
|
||||
});
|
||||
|
||||
describe('registerRouters', () => {
|
||||
it('should method register controllers to router instance', () => {
|
||||
it('should register controllers to router instance', () => {
|
||||
const routes = new Map();
|
||||
const routeWrapper = new InstanceWrapper({
|
||||
instance: new TestRoute(),
|
||||
@@ -88,6 +94,32 @@ describe('RoutesResolver', () => {
|
||||
expect(exploreSpy.calledWith(routeWrapper, moduleName, appInstance, ''))
|
||||
.to.be.true;
|
||||
});
|
||||
|
||||
it('should register with host when specified', () => {
|
||||
const routes = new Map();
|
||||
const routeWrapper = new InstanceWrapper({
|
||||
instance: new TestHostRoute(),
|
||||
metatype: TestHostRoute,
|
||||
});
|
||||
routes.set('TestHostRoute', routeWrapper);
|
||||
|
||||
const appInstance = new NoopHttpAdapter(router);
|
||||
const exploreSpy = sinon.spy(
|
||||
(routesResolver as any).routerBuilder,
|
||||
'explore',
|
||||
);
|
||||
const moduleName = '';
|
||||
modules.set(moduleName, {});
|
||||
|
||||
sinon
|
||||
.stub((routesResolver as any).routerBuilder, 'extractRouterPath')
|
||||
.callsFake(() => '');
|
||||
routesResolver.registerRouters(routes, moduleName, '', appInstance);
|
||||
|
||||
expect(exploreSpy.called).to.be.true;
|
||||
expect(exploreSpy.calledWith(routeWrapper, moduleName, appInstance, '', 'api.example.com'))
|
||||
.to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolve', () => {
|
||||
|
||||
Reference in New Issue
Block a user