1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 | 1x
1x
1x
1x
1x
1x
1x
1x
1x
6x
6x
6x
6x
6x
6x
1x
1x
2x
2x
2x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
2x
1x
1x
| import { BadRequestException, NotFoundException } from '@nestjs/common';
import { MODULE_PATH } from '@nestjs/common/constants';
import { HttpServer } from '@nestjs/common/interfaces';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { ApplicationConfig } from '../application-config';
import { CONTROLLER_MAPPING_MESSAGE } from '../helpers/messages';
import { InstanceWrapper, NestContainer } from '../injector/container';
import { MetadataScanner } from '../metadata-scanner';
import { Resolver } from './interfaces/resolver.interface';
import { RouterExceptionFilters } from './router-exception-filters';
import { RouterExplorer } from './router-explorer';
import { RouterProxy } from './router-proxy';
export class RoutesResolver implements Resolver {
private readonly logger = new Logger(RoutesResolver.name, true);
private readonly routerProxy = new RouterProxy();
private readonly routerExceptionsFilter: RouterExceptionFilters;
private readonly routerBuilder: RouterExplorer;
constructor(
private readonly container: NestContainer,
private readonly config: ApplicationConfig,
) {
this.routerExceptionsFilter = new RouterExceptionFilters(
container,
config,
container.getApplicationRef(),
);
this.routerBuilder = new RouterExplorer(
new MetadataScanner(),
this.container,
this.routerProxy,
this.routerExceptionsFilter,
this.config,
);
}
public resolve(appInstance, basePath: string) {
const modules = this.container.getModules();
modules.forEach(({ routes, metatype }, moduleName) => {
let path = metatype
? Reflect.getMetadata(MODULE_PATH, metatype)
: undefined;
path = path ? path + basePath : basePath;
this.registerRouters(routes, moduleName, path, appInstance);
});
}
public registerRouters(
routes: Map<string, InstanceWrapper<Controller>>,
moduleName: string,
basePath: string,
appInstance: HttpServer,
) {
routes.forEach(({ instance, metatype }) => {
const path = this.routerBuilder.extractRouterPath(metatype, basePath);
const controllerName = metatype.name;
this.logger.log(CONTROLLER_MAPPING_MESSAGE(controllerName, path));
this.routerBuilder.explore(
instance,
metatype,
moduleName,
appInstance,
path,
);
});
}
public registerNotFoundHandler() {
const applicationRef = this.container.getApplicationRef();
const callback = (req, res) => {
const method = applicationRef.getRequestMethod(req);
const url = applicationRef.getRequestUrl(req);
throw new NotFoundException(`Cannot ${method} ${url}`);
};
const handler = this.routerExceptionsFilter.create(
{},
callback,
undefined,
);
const proxy = this.routerProxy.createProxy(callback, handler);
applicationRef.setNotFoundHandler &&
applicationRef.setNotFoundHandler(proxy);
}
public registerExceptionHandler() {
const callback = (err, req, res, next) => {
throw this.mapExternalException(err);
};
const handler = this.routerExceptionsFilter.create(
{},
callback as any,
undefined,
);
const proxy = this.routerProxy.createExceptionLayerProxy(callback, handler);
const applicationRef = this.container.getApplicationRef();
applicationRef.setErrorHandler && applicationRef.setErrorHandler(proxy);
}
public mapExternalException(err: any) {
switch (true) {
case err instanceof SyntaxError:
return new BadRequestException(err.message);
default:
return err;
}
}
}
|