@tramvai/module-server 1.84.0 → 1.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/server/error.d.ts +6 -3
- package/lib/server/express-compatibility.d.ts +25 -0
- package/lib/server/server.d.ts +2 -4
- package/lib/server/webApp.d.ts +25 -9
- package/lib/server.es.js +246 -82
- package/lib/server.js +255 -87
- package/package.json +17 -14
package/lib/server/error.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
2
|
import type { LOGGER_TOKEN } from '@tramvai/module-common';
|
|
3
|
-
|
|
4
|
-
export declare const errorHandler: (app:
|
|
3
|
+
import type { WEB_FASTIFY_APP_AFTER_ERROR_TOKEN, WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN, WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN } from '@tramvai/tokens-server-private';
|
|
4
|
+
export declare const errorHandler: (app: FastifyInstance, { log, beforeError, processError, afterError, }: {
|
|
5
5
|
log: ReturnType<typeof LOGGER_TOKEN>;
|
|
6
|
+
beforeError: typeof WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN;
|
|
7
|
+
processError: typeof WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN;
|
|
8
|
+
afterError: typeof WEB_FASTIFY_APP_AFTER_ERROR_TOKEN;
|
|
6
9
|
}) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fork of https://github.com/fastify/fastify-express
|
|
3
|
+
*/
|
|
4
|
+
/// <reference types="node" />
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import type { FastifyPluginCallback } from 'fastify';
|
|
7
|
+
declare module 'fastify' {
|
|
8
|
+
interface FastifyInstance {
|
|
9
|
+
/**
|
|
10
|
+
* Express middleware function
|
|
11
|
+
*/
|
|
12
|
+
use: express.Application['use'];
|
|
13
|
+
/**
|
|
14
|
+
* Express application instance
|
|
15
|
+
*/
|
|
16
|
+
express: express.Application;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
interface Options {
|
|
20
|
+
express: {
|
|
21
|
+
instance: express.Application;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export declare const fastifyExpressCompatibility: FastifyPluginCallback<Options, import("http").Server>;
|
|
25
|
+
export {};
|
package/lib/server/server.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import http from 'http';
|
|
3
|
-
import type { SERVER_TOKEN
|
|
3
|
+
import type { SERVER_TOKEN } from '@tramvai/tokens-server';
|
|
4
4
|
import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
|
|
5
5
|
import type { ENV_MANAGER_TOKEN } from '@tramvai/module-environment';
|
|
6
|
-
export declare const serverFactory: (
|
|
7
|
-
webApp: typeof WEB_APP_TOKEN;
|
|
8
|
-
}) => http.Server;
|
|
6
|
+
export declare const serverFactory: () => http.Server;
|
|
9
7
|
export declare const serverListenCommand: ({ server, logger, envManager, }: {
|
|
10
8
|
server: typeof SERVER_TOKEN;
|
|
11
9
|
logger: typeof LOGGER_TOKEN;
|
package/lib/server/webApp.d.ts
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
|
|
2
3
|
import type { COMMAND_LINE_RUNNER_TOKEN } from '@tramvai/core';
|
|
3
|
-
import type { WEB_APP_TOKEN, WEB_APP_BEFORE_INIT_TOKEN, WEB_APP_INIT_TOKEN, WEB_APP_AFTER_INIT_TOKEN, WEB_APP_LIMITER_TOKEN } from '@tramvai/tokens-server';
|
|
4
|
-
|
|
5
|
-
export declare const
|
|
6
|
-
|
|
4
|
+
import type { WEB_APP_TOKEN, WEB_APP_BEFORE_INIT_TOKEN, WEB_APP_INIT_TOKEN, WEB_APP_AFTER_INIT_TOKEN, WEB_APP_LIMITER_TOKEN, SERVER_TOKEN } from '@tramvai/tokens-server';
|
|
5
|
+
import type { WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_AFTER_INIT_TOKEN, WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, WEB_FASTIFY_APP_INIT_TOKEN, WEB_FASTIFY_APP_LIMITER_TOKEN, WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN, WEB_FASTIFY_APP_AFTER_ERROR_TOKEN, WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN } from '@tramvai/tokens-server-private';
|
|
6
|
+
export declare const webAppFactory: ({ server, expressApp, }: {
|
|
7
|
+
server: typeof SERVER_TOKEN;
|
|
8
|
+
expressApp: typeof WEB_APP_TOKEN;
|
|
9
|
+
}) => import("fastify").FastifyInstance<import("http").Server, import("http").IncomingMessage, import("http").ServerResponse, import("fastify").FastifyLoggerInstance> & PromiseLike<import("fastify").FastifyInstance<import("http").Server, import("http").IncomingMessage, import("http").ServerResponse, import("fastify").FastifyLoggerInstance>>;
|
|
10
|
+
export declare const webAppExpressFactory: ({ webApp }: {
|
|
11
|
+
webApp: typeof WEB_FASTIFY_APP_TOKEN;
|
|
12
|
+
}) => import("express-serve-static-core").Express;
|
|
13
|
+
export declare const webAppInitCommand: ({ app, expressApp, logger, commandLineRunner, beforeInit, init, afterInit, limiterRequest, expressBeforeInit, expressInit, expressAfterInit, expressLimiterRequest, beforeError, processError, afterError, }: {
|
|
14
|
+
app: typeof WEB_FASTIFY_APP_TOKEN;
|
|
15
|
+
expressApp: typeof WEB_APP_TOKEN;
|
|
7
16
|
logger: typeof LOGGER_TOKEN;
|
|
8
17
|
commandLineRunner: typeof COMMAND_LINE_RUNNER_TOKEN;
|
|
9
|
-
beforeInit: typeof
|
|
10
|
-
init: typeof
|
|
11
|
-
afterInit: typeof
|
|
12
|
-
limiterRequest: typeof
|
|
18
|
+
beforeInit: typeof WEB_FASTIFY_APP_BEFORE_INIT_TOKEN;
|
|
19
|
+
init: typeof WEB_FASTIFY_APP_INIT_TOKEN;
|
|
20
|
+
afterInit: typeof WEB_FASTIFY_APP_AFTER_INIT_TOKEN;
|
|
21
|
+
limiterRequest: typeof WEB_FASTIFY_APP_LIMITER_TOKEN;
|
|
22
|
+
expressBeforeInit: typeof WEB_APP_BEFORE_INIT_TOKEN;
|
|
23
|
+
expressInit: typeof WEB_APP_INIT_TOKEN;
|
|
24
|
+
expressAfterInit: typeof WEB_APP_AFTER_INIT_TOKEN;
|
|
25
|
+
expressLimiterRequest: typeof WEB_APP_LIMITER_TOKEN;
|
|
26
|
+
beforeError: typeof WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN;
|
|
27
|
+
processError: typeof WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN;
|
|
28
|
+
afterError: typeof WEB_FASTIFY_APP_AFTER_ERROR_TOKEN;
|
|
13
29
|
}) => () => Promise<void>;
|
package/lib/server.es.js
CHANGED
|
@@ -2,14 +2,20 @@ import { __decorate } from 'tslib';
|
|
|
2
2
|
import { Scope, APP_INFO_TOKEN, Module, provide, DI_TOKEN, COMMAND_LINE_RUNNER_TOKEN, commandLineListTokens } from '@tramvai/core';
|
|
3
3
|
import { SERVER_MODULE_PAPI_PUBLIC_ROUTE, SERVER_MODULE_PAPI_PUBLIC_URL, SERVER_MODULE_PAPI_PRIVATE_URL, WEB_APP_BEFORE_INIT_TOKEN, WEB_APP_TOKEN, SERVER_MODULE_PAPI_PRIVATE_ROUTE, SERVER_MODULE_STATICS_OPTIONS, SERVER_TOKEN, READINESS_PROBE_TOKEN, LIVENESS_PROBE_TOKEN, SPECIAL_SERVER_PATHS, PROXY_CONFIG_TOKEN, DEPENDENCIES_VERSION_FILTER_TOKEN, WEB_APP_INIT_TOKEN, WEB_APP_AFTER_INIT_TOKEN, WEB_APP_LIMITER_TOKEN } from '@tramvai/tokens-server';
|
|
4
4
|
export * from '@tramvai/tokens-server';
|
|
5
|
-
import {
|
|
5
|
+
import { WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_INIT_TOKEN, WEB_FASTIFY_APP_AFTER_INIT_TOKEN, WEB_FASTIFY_APP_LIMITER_TOKEN, WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN, WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN, WEB_FASTIFY_APP_AFTER_ERROR_TOKEN } from '@tramvai/tokens-server-private';
|
|
6
|
+
import { REQUEST, RESPONSE, FASTIFY_REQUEST, FASTIFY_RESPONSE, RESPONSE_MANAGER_TOKEN, LOGGER_TOKEN, ENV_MANAGER_TOKEN, ENV_USED_TOKEN } from '@tramvai/tokens-common';
|
|
6
7
|
import { MetricsModule } from '@tramvai/module-metrics';
|
|
7
8
|
import { CacheWarmupModule } from '@tramvai/module-cache-warmup';
|
|
8
9
|
import http from 'http';
|
|
10
|
+
import fastify from 'fastify';
|
|
9
11
|
import express from 'express';
|
|
10
12
|
import cookieParser from 'cookie-parser';
|
|
11
13
|
import bodyParser from 'body-parser';
|
|
12
|
-
import
|
|
14
|
+
import { fastifyCookie } from 'fastify-cookie';
|
|
15
|
+
import fastifyFormBody from 'fastify-formbody';
|
|
16
|
+
import fp from 'fastify-plugin';
|
|
17
|
+
import symbols from 'fastify/lib/symbols';
|
|
18
|
+
import isNil from '@tinkoff/utils/is/nil';
|
|
13
19
|
import { isRedirectFoundError, isNotFoundError, isHttpError } from '@tinkoff/errors';
|
|
14
20
|
import zlib from 'zlib';
|
|
15
21
|
import compression from 'compression';
|
|
@@ -17,11 +23,10 @@ import os from 'os';
|
|
|
17
23
|
import filterObj from '@tinkoff/utils/object/filter';
|
|
18
24
|
import flatten from '@tinkoff/utils/array/flatten';
|
|
19
25
|
import toArray from '@tinkoff/utils/array/toArray';
|
|
20
|
-
import { REQUEST as REQUEST$1, RESPONSE as RESPONSE$1, LOGGER_TOKEN, ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
|
|
21
26
|
import { create, middlewares, getPapiParameters, createPapiMethod } from '@tramvai/papi';
|
|
22
27
|
import { createChildContainer } from '@tinkoff/dippy';
|
|
23
28
|
import eachObj from '@tinkoff/utils/object/each';
|
|
24
|
-
import { createTerminus } from '@tinkoff/
|
|
29
|
+
import { createTerminus } from '@tinkoff/terminus';
|
|
25
30
|
import { parse } from '@tinkoff/url';
|
|
26
31
|
import { EventEmitter } from 'events';
|
|
27
32
|
import monkeypatch from '@tinkoff/monkeypatch';
|
|
@@ -31,10 +36,8 @@ import isObject from '@tinkoff/utils/is/object';
|
|
|
31
36
|
import { resolve } from 'path';
|
|
32
37
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
33
38
|
|
|
34
|
-
const serverFactory = (
|
|
35
|
-
|
|
36
|
-
server.on('request', webApp);
|
|
37
|
-
return server;
|
|
39
|
+
const serverFactory = () => {
|
|
40
|
+
return http.createServer();
|
|
38
41
|
};
|
|
39
42
|
const serverListenCommand = ({ server, logger, envManager, }) => {
|
|
40
43
|
const log = logger('server');
|
|
@@ -47,88 +50,220 @@ const serverListenCommand = ({ server, logger, envManager, }) => {
|
|
|
47
50
|
};
|
|
48
51
|
};
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Fork of https://github.com/fastify/fastify-express
|
|
55
|
+
*/
|
|
56
|
+
const kMiddlewares = Symbol('fastify-express-middlewares');
|
|
57
|
+
const expressPlugin = (fastify, options, next) => {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
fastify.decorate('use', use);
|
|
60
|
+
// eslint-disable-next-line no-param-reassign
|
|
61
|
+
fastify[kMiddlewares] = [];
|
|
62
|
+
fastify.decorate('express', (_b = (_a = options.express) === null || _a === void 0 ? void 0 : _a.instance) !== null && _b !== void 0 ? _b : express());
|
|
63
|
+
fastify.express.disable('x-powered-by');
|
|
64
|
+
fastify
|
|
65
|
+
.addHook('onRequest', enhanceRequest)
|
|
66
|
+
.addHook('onRequest', runConnect)
|
|
67
|
+
.addHook('onRegister', onRegister);
|
|
68
|
+
function use(path, fn) {
|
|
69
|
+
if (typeof path === 'string') {
|
|
70
|
+
const prefix = this[symbols.kRoutePrefix];
|
|
71
|
+
// eslint-disable-next-line no-param-reassign
|
|
72
|
+
path = prefix + (path === '/' && prefix.length > 0 ? '' : path);
|
|
55
73
|
}
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
this[kMiddlewares].push([path, fn]);
|
|
75
|
+
if (fn == null) {
|
|
76
|
+
this.express.use(path);
|
|
58
77
|
}
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
else {
|
|
79
|
+
this.express.use(path, fn);
|
|
80
|
+
}
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
function enhanceRequest(req, reply, next) {
|
|
84
|
+
req.raw.originalUrl = req.raw.url;
|
|
85
|
+
req.raw.id = req.id;
|
|
86
|
+
req.raw.hostname = req.hostname;
|
|
87
|
+
req.raw.ip = req.ip;
|
|
88
|
+
req.raw.ips = req.ips;
|
|
89
|
+
req.raw.log = req.log;
|
|
90
|
+
// eslint-disable-next-line no-param-reassign
|
|
91
|
+
reply.raw.log = req.log;
|
|
92
|
+
const originalProtocol = req.raw.protocol;
|
|
93
|
+
// Make it lazy as it does a bit of work
|
|
94
|
+
Object.defineProperty(req.raw, 'protocol', {
|
|
95
|
+
get() {
|
|
96
|
+
// added in Fastify@3.5, so handle it missing
|
|
97
|
+
return req.protocol || originalProtocol;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
next();
|
|
101
|
+
}
|
|
102
|
+
function runConnect(req, reply, next) {
|
|
103
|
+
if (this[kMiddlewares].length > 0) {
|
|
104
|
+
for (const [headerName, headerValue] of Object.entries(reply.getHeaders())) {
|
|
105
|
+
reply.raw.setHeader(headerName, headerValue);
|
|
106
|
+
}
|
|
107
|
+
this.express(req.raw, reply.raw, next);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
next();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function onRegister(instance) {
|
|
114
|
+
const middlewares = instance[kMiddlewares].slice();
|
|
115
|
+
// eslint-disable-next-line no-param-reassign
|
|
116
|
+
instance[kMiddlewares] = [];
|
|
117
|
+
instance.decorate('express', express());
|
|
118
|
+
instance.express.disable('x-powered-by');
|
|
119
|
+
instance.decorate('use', use);
|
|
120
|
+
for (const middleware of middlewares) {
|
|
121
|
+
instance.use(...middleware);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
next();
|
|
61
125
|
};
|
|
62
|
-
const
|
|
63
|
-
|
|
126
|
+
const fastifyExpressCompatibility = fp(expressPlugin, {
|
|
127
|
+
fastify: '>=3.0.0',
|
|
128
|
+
name: 'fastify-express',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const errorHandler = (app, { log, beforeError, processError, afterError, }) => {
|
|
132
|
+
app.setErrorHandler(async (error, request, reply) => {
|
|
133
|
+
const runHandlers = async (handlers) => {
|
|
134
|
+
if (handlers) {
|
|
135
|
+
for (const handler of handlers) {
|
|
136
|
+
const result = await handler(error, request, reply);
|
|
137
|
+
if (result) {
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
64
143
|
const requestInfo = {
|
|
65
|
-
ip:
|
|
66
|
-
requestId:
|
|
67
|
-
url:
|
|
144
|
+
ip: request.ip,
|
|
145
|
+
requestId: request.headers['x-request-id'],
|
|
146
|
+
url: request.url,
|
|
68
147
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
148
|
+
const beforeErrorResult = await runHandlers(beforeError);
|
|
149
|
+
if (!isNil(beforeErrorResult)) {
|
|
150
|
+
return beforeErrorResult;
|
|
151
|
+
}
|
|
152
|
+
if (isRedirectFoundError(error)) {
|
|
153
|
+
reply.header('cache-control', 'no-cache, no-store, must-revalidate');
|
|
154
|
+
reply.redirect(error.httpStatus || 307, error.nextUrl);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (isNotFoundError(error)) {
|
|
158
|
+
reply.status(404);
|
|
159
|
+
return '';
|
|
160
|
+
}
|
|
161
|
+
const processErrorResult = await runHandlers(processError);
|
|
162
|
+
if (!isNil(processErrorResult)) {
|
|
163
|
+
return processErrorResult;
|
|
164
|
+
}
|
|
165
|
+
if (isHttpError(error)) {
|
|
166
|
+
if (error.httpStatus >= 500) {
|
|
167
|
+
log.error({ event: 'send-server-error', error, requestInfo });
|
|
72
168
|
}
|
|
73
|
-
|
|
169
|
+
reply.status(error.httpStatus);
|
|
170
|
+
return '';
|
|
171
|
+
}
|
|
172
|
+
log.error({ event: 'send-server-error', error, requestInfo });
|
|
173
|
+
const afterErrorResult = await runHandlers(afterError);
|
|
174
|
+
if (!isNil(afterErrorResult)) {
|
|
175
|
+
return afterErrorResult;
|
|
74
176
|
}
|
|
75
|
-
|
|
76
|
-
finalhandler(req, res)(err);
|
|
177
|
+
throw error;
|
|
77
178
|
});
|
|
78
179
|
};
|
|
79
180
|
|
|
80
|
-
const webAppFactory = () => {
|
|
181
|
+
const webAppFactory = ({ server, expressApp, }) => {
|
|
182
|
+
const app = fastify({
|
|
183
|
+
serverFactory: (handler) => {
|
|
184
|
+
server.on('request', handler);
|
|
185
|
+
return server;
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
return app;
|
|
189
|
+
};
|
|
190
|
+
const webAppExpressFactory = ({ webApp }) => {
|
|
81
191
|
const app = express();
|
|
82
192
|
app.disable('etag');
|
|
83
193
|
app.disable('x-powered-by');
|
|
84
194
|
return app;
|
|
85
195
|
};
|
|
86
|
-
const webAppInitCommand = ({ app, logger, commandLineRunner, beforeInit, init, afterInit, limiterRequest, }) => {
|
|
196
|
+
const webAppInitCommand = ({ app, expressApp, logger, commandLineRunner, beforeInit, init, afterInit, limiterRequest, expressBeforeInit, expressInit, expressAfterInit, expressLimiterRequest, beforeError, processError, afterError, }) => {
|
|
87
197
|
const log = logger('server:webapp');
|
|
88
|
-
const runHandlers = (handlers) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
198
|
+
const runHandlers = (handlers, expressHandlers) => {
|
|
199
|
+
return Promise.all([
|
|
200
|
+
handlers && Promise.all(handlers.map((handler) => handler(app))),
|
|
201
|
+
expressHandlers && Promise.all(expressHandlers.map((handler) => handler(expressApp))),
|
|
202
|
+
]);
|
|
92
203
|
};
|
|
93
204
|
return async function webAppInit() {
|
|
94
|
-
|
|
95
|
-
await
|
|
96
|
-
|
|
205
|
+
errorHandler(app, { log, beforeError, processError, afterError });
|
|
206
|
+
await app.register(fastifyExpressCompatibility, {
|
|
207
|
+
express: {
|
|
208
|
+
instance: expressApp,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
await runHandlers(beforeInit, expressBeforeInit);
|
|
212
|
+
await runHandlers(limiterRequest, expressLimiterRequest);
|
|
213
|
+
await app.register(fastifyCookie);
|
|
214
|
+
await app.register(fastifyFormBody);
|
|
215
|
+
expressApp.use(bodyParser.urlencoded({
|
|
97
216
|
limit: '2mb',
|
|
98
217
|
extended: false,
|
|
99
218
|
}), cookieParser());
|
|
100
|
-
await runHandlers(init);
|
|
101
|
-
|
|
219
|
+
await runHandlers(init, expressInit);
|
|
220
|
+
// force express to execute to update server's request and response instances
|
|
221
|
+
app.use((req, res, next) => {
|
|
222
|
+
next();
|
|
223
|
+
});
|
|
224
|
+
app.all('*', async (request, reply) => {
|
|
102
225
|
try {
|
|
103
226
|
log.debug({
|
|
104
227
|
event: 'start:request',
|
|
105
228
|
message: 'Клиент зашел на страницу',
|
|
106
|
-
url:
|
|
229
|
+
url: request.url,
|
|
107
230
|
});
|
|
108
231
|
const di = await commandLineRunner.run('server', 'customer', [
|
|
109
232
|
{
|
|
110
233
|
provide: REQUEST,
|
|
111
234
|
scope: Scope.REQUEST,
|
|
112
|
-
useValue:
|
|
235
|
+
useValue: request.raw,
|
|
113
236
|
},
|
|
114
237
|
{
|
|
115
238
|
provide: RESPONSE,
|
|
116
239
|
scope: Scope.REQUEST,
|
|
117
|
-
useValue:
|
|
240
|
+
useValue: reply.raw,
|
|
241
|
+
},
|
|
242
|
+
// TODO: перевести использование на новые
|
|
243
|
+
// TODO: добавить для papi
|
|
244
|
+
{
|
|
245
|
+
provide: FASTIFY_REQUEST,
|
|
246
|
+
scope: Scope.REQUEST,
|
|
247
|
+
useValue: request,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
provide: FASTIFY_RESPONSE,
|
|
251
|
+
scope: Scope.REQUEST,
|
|
252
|
+
useValue: reply,
|
|
118
253
|
},
|
|
119
254
|
]);
|
|
120
255
|
const responseManager = di.get(RESPONSE_MANAGER_TOKEN);
|
|
121
|
-
if (
|
|
256
|
+
if (reply.sent) {
|
|
122
257
|
log.debug({
|
|
123
258
|
event: 'response-ended',
|
|
124
259
|
message: 'Response was already ended.',
|
|
125
|
-
url:
|
|
260
|
+
url: request.url,
|
|
126
261
|
});
|
|
127
262
|
}
|
|
128
263
|
else {
|
|
129
|
-
|
|
130
|
-
.
|
|
131
|
-
.
|
|
264
|
+
reply
|
|
265
|
+
.header('content-type', 'text/html')
|
|
266
|
+
.headers(responseManager.getHeaders())
|
|
132
267
|
.status(responseManager.getStatus())
|
|
133
268
|
.send(responseManager.getBody());
|
|
134
269
|
}
|
|
@@ -136,16 +271,15 @@ const webAppInitCommand = ({ app, logger, commandLineRunner, beforeInit, init, a
|
|
|
136
271
|
catch (err) {
|
|
137
272
|
if (err.di) {
|
|
138
273
|
const responseManager = err.di.get(RESPONSE_MANAGER_TOKEN);
|
|
139
|
-
if (responseManager && !
|
|
140
|
-
|
|
274
|
+
if (responseManager && !reply.sent) {
|
|
275
|
+
reply.headers(responseManager.getHeaders());
|
|
141
276
|
}
|
|
142
277
|
}
|
|
143
|
-
|
|
278
|
+
throw err;
|
|
144
279
|
}
|
|
145
280
|
});
|
|
146
|
-
|
|
147
|
-
await
|
|
148
|
-
errorHandler(app, { log });
|
|
281
|
+
await runHandlers(afterInit, expressAfterInit);
|
|
282
|
+
await app.ready();
|
|
149
283
|
};
|
|
150
284
|
};
|
|
151
285
|
|
|
@@ -213,11 +347,11 @@ function createApi(papiList, { di, logger }) {
|
|
|
213
347
|
var _a;
|
|
214
348
|
const childDI = createChildContainer(di);
|
|
215
349
|
childDI.register({
|
|
216
|
-
provide: REQUEST
|
|
350
|
+
provide: REQUEST,
|
|
217
351
|
useValue: req,
|
|
218
352
|
});
|
|
219
353
|
childDI.register({
|
|
220
|
-
provide: RESPONSE
|
|
354
|
+
provide: RESPONSE,
|
|
221
355
|
useValue: res,
|
|
222
356
|
});
|
|
223
357
|
return { ...rootDeps, ...childDI.getOfDeps((_a = papi.deps) !== null && _a !== void 0 ? _a : {}), req, res };
|
|
@@ -235,10 +369,20 @@ try {
|
|
|
235
369
|
Api = require('@tramvai/cli/lib/external/api').default; // eslint-disable-line import/no-unresolved
|
|
236
370
|
}
|
|
237
371
|
catch (e) { }
|
|
238
|
-
const getFileApi = () => {
|
|
372
|
+
const getFileApi = ({ logger }) => {
|
|
373
|
+
const log = logger('papi:fileApi');
|
|
239
374
|
const result = [];
|
|
240
375
|
eachObj((v, k) => {
|
|
241
376
|
const handler = (v.handler || v.default);
|
|
377
|
+
if (!handler) {
|
|
378
|
+
log.error({
|
|
379
|
+
message: `Cannot resolve a papi handler.
|
|
380
|
+
Check that you are using file based papi right way by docs https://tramvai.dev/docs/how-to/how-create-papi#automatic-handler-creation
|
|
381
|
+
In case you have not added any file papi handler, consider renaming directory ./src/api (by default) to the other name to resolve conflicts with papi, or
|
|
382
|
+
change settings application.commands.build.options.serverApiDir in tramvai.json`,
|
|
383
|
+
});
|
|
384
|
+
throw new Error('Not a papi');
|
|
385
|
+
}
|
|
242
386
|
const papiParameters = getPapiParameters(handler);
|
|
243
387
|
result.push(createPapiMethod({
|
|
244
388
|
...v,
|
|
@@ -252,7 +396,10 @@ const getFileApi = () => {
|
|
|
252
396
|
const fileApiProvider = {
|
|
253
397
|
provide: SERVER_MODULE_PAPI_PUBLIC_ROUTE,
|
|
254
398
|
multi: true,
|
|
255
|
-
|
|
399
|
+
useFactory: getFileApi,
|
|
400
|
+
deps: {
|
|
401
|
+
logger: LOGGER_TOKEN,
|
|
402
|
+
},
|
|
256
403
|
};
|
|
257
404
|
|
|
258
405
|
const sharedProviders = [
|
|
@@ -425,9 +572,9 @@ ServerGracefulShutdownModule = __decorate([
|
|
|
425
572
|
Module({
|
|
426
573
|
providers: [
|
|
427
574
|
{
|
|
428
|
-
provide:
|
|
575
|
+
provide: WEB_FASTIFY_APP_BEFORE_INIT_TOKEN,
|
|
429
576
|
multi: true,
|
|
430
|
-
useFactory: ({
|
|
577
|
+
useFactory: ({ app, server, logger, commandLineRunner, livenessProbe, readinessProbe, }) => {
|
|
431
578
|
const log = logger('server');
|
|
432
579
|
return function serverListen() {
|
|
433
580
|
createTerminus(server, app, {
|
|
@@ -470,8 +617,8 @@ ServerGracefulShutdownModule = __decorate([
|
|
|
470
617
|
};
|
|
471
618
|
},
|
|
472
619
|
deps: {
|
|
620
|
+
app: WEB_FASTIFY_APP_TOKEN,
|
|
473
621
|
server: SERVER_TOKEN,
|
|
474
|
-
app: WEB_APP_TOKEN,
|
|
475
622
|
logger: LOGGER_TOKEN,
|
|
476
623
|
commandLineRunner: COMMAND_LINE_RUNNER_TOKEN,
|
|
477
624
|
readinessProbe: { token: READINESS_PROBE_TOKEN, optional: true },
|
|
@@ -737,31 +884,48 @@ ServerModule = __decorate([
|
|
|
737
884
|
process.env.NODE_ENV !== 'production' && DebugHttpRequestsModule,
|
|
738
885
|
].filter(Boolean),
|
|
739
886
|
providers: [
|
|
740
|
-
{
|
|
741
|
-
provide:
|
|
887
|
+
provide({
|
|
888
|
+
provide: SERVER_TOKEN,
|
|
742
889
|
scope: Scope.SINGLETON,
|
|
890
|
+
useFactory: serverFactory,
|
|
891
|
+
}),
|
|
892
|
+
provide({
|
|
893
|
+
provide: WEB_FASTIFY_APP_TOKEN,
|
|
743
894
|
useFactory: webAppFactory,
|
|
744
|
-
|
|
895
|
+
scope: Scope.SINGLETON,
|
|
896
|
+
deps: {
|
|
897
|
+
server: SERVER_TOKEN,
|
|
898
|
+
},
|
|
899
|
+
}),
|
|
900
|
+
provide({
|
|
901
|
+
// BACKWARD: provide the express app as before
|
|
902
|
+
provide: WEB_APP_TOKEN,
|
|
903
|
+
scope: Scope.SINGLETON,
|
|
904
|
+
useFactory: webAppExpressFactory,
|
|
905
|
+
deps: {
|
|
906
|
+
webApp: WEB_FASTIFY_APP_TOKEN,
|
|
907
|
+
},
|
|
908
|
+
}),
|
|
745
909
|
{
|
|
746
910
|
provide: commandLineListTokens.init,
|
|
747
911
|
multi: true,
|
|
748
912
|
useFactory: webAppInitCommand,
|
|
749
913
|
deps: {
|
|
750
|
-
app:
|
|
751
|
-
|
|
914
|
+
app: WEB_FASTIFY_APP_TOKEN,
|
|
915
|
+
expressApp: WEB_APP_TOKEN,
|
|
916
|
+
logger: LOGGER_TOKEN,
|
|
752
917
|
commandLineRunner: COMMAND_LINE_RUNNER_TOKEN,
|
|
753
|
-
beforeInit: { token:
|
|
754
|
-
init: { token:
|
|
755
|
-
afterInit: { token:
|
|
756
|
-
limiterRequest: { token:
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
webApp: WEB_APP_TOKEN,
|
|
918
|
+
beforeInit: { token: WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, optional: true },
|
|
919
|
+
init: { token: WEB_FASTIFY_APP_INIT_TOKEN, optional: true },
|
|
920
|
+
afterInit: { token: WEB_FASTIFY_APP_AFTER_INIT_TOKEN, optional: true },
|
|
921
|
+
limiterRequest: { token: WEB_FASTIFY_APP_LIMITER_TOKEN, optional: true },
|
|
922
|
+
expressBeforeInit: { token: WEB_APP_BEFORE_INIT_TOKEN, optional: true },
|
|
923
|
+
expressInit: { token: WEB_APP_INIT_TOKEN, optional: true },
|
|
924
|
+
expressAfterInit: { token: WEB_APP_AFTER_INIT_TOKEN, optional: true },
|
|
925
|
+
expressLimiterRequest: { token: WEB_APP_LIMITER_TOKEN, optional: true },
|
|
926
|
+
beforeError: { token: WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN, optional: true },
|
|
927
|
+
processError: { token: WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN, optional: true },
|
|
928
|
+
afterError: { token: WEB_FASTIFY_APP_AFTER_ERROR_TOKEN, optional: true },
|
|
765
929
|
},
|
|
766
930
|
},
|
|
767
931
|
{
|
|
@@ -770,8 +934,8 @@ ServerModule = __decorate([
|
|
|
770
934
|
useFactory: serverListenCommand,
|
|
771
935
|
deps: {
|
|
772
936
|
server: SERVER_TOKEN,
|
|
773
|
-
logger: LOGGER_TOKEN
|
|
774
|
-
envManager: ENV_MANAGER_TOKEN
|
|
937
|
+
logger: LOGGER_TOKEN,
|
|
938
|
+
envManager: ENV_MANAGER_TOKEN,
|
|
775
939
|
},
|
|
776
940
|
},
|
|
777
941
|
{
|
|
@@ -779,8 +943,8 @@ ServerModule = __decorate([
|
|
|
779
943
|
multi: true,
|
|
780
944
|
useFactory: staticAppCommand,
|
|
781
945
|
deps: {
|
|
782
|
-
logger: LOGGER_TOKEN
|
|
783
|
-
envManager: ENV_MANAGER_TOKEN
|
|
946
|
+
logger: LOGGER_TOKEN,
|
|
947
|
+
envManager: ENV_MANAGER_TOKEN,
|
|
784
948
|
appInfo: APP_INFO_TOKEN,
|
|
785
949
|
},
|
|
786
950
|
},
|
|
@@ -810,7 +974,7 @@ ServerModule = __decorate([
|
|
|
810
974
|
useFactory: xHeadersFactory,
|
|
811
975
|
deps: {
|
|
812
976
|
app: WEB_APP_TOKEN,
|
|
813
|
-
envManager: ENV_MANAGER_TOKEN
|
|
977
|
+
envManager: ENV_MANAGER_TOKEN,
|
|
814
978
|
appInfo: APP_INFO_TOKEN,
|
|
815
979
|
},
|
|
816
980
|
},
|
package/lib/server.js
CHANGED
|
@@ -5,14 +5,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
6
|
var core = require('@tramvai/core');
|
|
7
7
|
var tokensServer = require('@tramvai/tokens-server');
|
|
8
|
-
var
|
|
8
|
+
var tokensServerPrivate = require('@tramvai/tokens-server-private');
|
|
9
|
+
var tokensCommon = require('@tramvai/tokens-common');
|
|
9
10
|
var moduleMetrics = require('@tramvai/module-metrics');
|
|
10
11
|
var moduleCacheWarmup = require('@tramvai/module-cache-warmup');
|
|
11
12
|
var http = require('http');
|
|
13
|
+
var fastify = require('fastify');
|
|
12
14
|
var express = require('express');
|
|
13
15
|
var cookieParser = require('cookie-parser');
|
|
14
16
|
var bodyParser = require('body-parser');
|
|
15
|
-
var
|
|
17
|
+
var fastifyCookie = require('fastify-cookie');
|
|
18
|
+
var fastifyFormBody = require('fastify-formbody');
|
|
19
|
+
var fp = require('fastify-plugin');
|
|
20
|
+
var symbols = require('fastify/lib/symbols');
|
|
21
|
+
var isNil = require('@tinkoff/utils/is/nil');
|
|
16
22
|
var errors = require('@tinkoff/errors');
|
|
17
23
|
var zlib = require('zlib');
|
|
18
24
|
var compression = require('compression');
|
|
@@ -20,11 +26,10 @@ var os = require('os');
|
|
|
20
26
|
var filterObj = require('@tinkoff/utils/object/filter');
|
|
21
27
|
var flatten = require('@tinkoff/utils/array/flatten');
|
|
22
28
|
var toArray = require('@tinkoff/utils/array/toArray');
|
|
23
|
-
var tokensCommon = require('@tramvai/tokens-common');
|
|
24
29
|
var papi = require('@tramvai/papi');
|
|
25
30
|
var dippy = require('@tinkoff/dippy');
|
|
26
31
|
var eachObj = require('@tinkoff/utils/object/each');
|
|
27
|
-
var
|
|
32
|
+
var terminus = require('@tinkoff/terminus');
|
|
28
33
|
var url = require('@tinkoff/url');
|
|
29
34
|
var events = require('events');
|
|
30
35
|
var monkeypatch = require('@tinkoff/monkeypatch');
|
|
@@ -37,10 +42,14 @@ var httpProxyMiddleware = require('http-proxy-middleware');
|
|
|
37
42
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
38
43
|
|
|
39
44
|
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
45
|
+
var fastify__default = /*#__PURE__*/_interopDefaultLegacy(fastify);
|
|
40
46
|
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
41
47
|
var cookieParser__default = /*#__PURE__*/_interopDefaultLegacy(cookieParser);
|
|
42
48
|
var bodyParser__default = /*#__PURE__*/_interopDefaultLegacy(bodyParser);
|
|
43
|
-
var
|
|
49
|
+
var fastifyFormBody__default = /*#__PURE__*/_interopDefaultLegacy(fastifyFormBody);
|
|
50
|
+
var fp__default = /*#__PURE__*/_interopDefaultLegacy(fp);
|
|
51
|
+
var symbols__default = /*#__PURE__*/_interopDefaultLegacy(symbols);
|
|
52
|
+
var isNil__default = /*#__PURE__*/_interopDefaultLegacy(isNil);
|
|
44
53
|
var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
|
|
45
54
|
var compression__default = /*#__PURE__*/_interopDefaultLegacy(compression);
|
|
46
55
|
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
@@ -53,10 +62,8 @@ var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
|
53
62
|
var isArray__default = /*#__PURE__*/_interopDefaultLegacy(isArray);
|
|
54
63
|
var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
|
|
55
64
|
|
|
56
|
-
const serverFactory = (
|
|
57
|
-
|
|
58
|
-
server.on('request', webApp);
|
|
59
|
-
return server;
|
|
65
|
+
const serverFactory = () => {
|
|
66
|
+
return http__default["default"].createServer();
|
|
60
67
|
};
|
|
61
68
|
const serverListenCommand = ({ server, logger, envManager, }) => {
|
|
62
69
|
const log = logger('server');
|
|
@@ -69,105 +76,236 @@ const serverListenCommand = ({ server, logger, envManager, }) => {
|
|
|
69
76
|
};
|
|
70
77
|
};
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Fork of https://github.com/fastify/fastify-express
|
|
81
|
+
*/
|
|
82
|
+
const kMiddlewares = Symbol('fastify-express-middlewares');
|
|
83
|
+
const expressPlugin = (fastify, options, next) => {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
fastify.decorate('use', use);
|
|
86
|
+
// eslint-disable-next-line no-param-reassign
|
|
87
|
+
fastify[kMiddlewares] = [];
|
|
88
|
+
fastify.decorate('express', (_b = (_a = options.express) === null || _a === void 0 ? void 0 : _a.instance) !== null && _b !== void 0 ? _b : express__default["default"]());
|
|
89
|
+
fastify.express.disable('x-powered-by');
|
|
90
|
+
fastify
|
|
91
|
+
.addHook('onRequest', enhanceRequest)
|
|
92
|
+
.addHook('onRequest', runConnect)
|
|
93
|
+
.addHook('onRegister', onRegister);
|
|
94
|
+
function use(path, fn) {
|
|
95
|
+
if (typeof path === 'string') {
|
|
96
|
+
const prefix = this[symbols__default["default"].kRoutePrefix];
|
|
97
|
+
// eslint-disable-next-line no-param-reassign
|
|
98
|
+
path = prefix + (path === '/' && prefix.length > 0 ? '' : path);
|
|
77
99
|
}
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
this[kMiddlewares].push([path, fn]);
|
|
101
|
+
if (fn == null) {
|
|
102
|
+
this.express.use(path);
|
|
80
103
|
}
|
|
81
|
-
|
|
82
|
-
|
|
104
|
+
else {
|
|
105
|
+
this.express.use(path, fn);
|
|
106
|
+
}
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
function enhanceRequest(req, reply, next) {
|
|
110
|
+
req.raw.originalUrl = req.raw.url;
|
|
111
|
+
req.raw.id = req.id;
|
|
112
|
+
req.raw.hostname = req.hostname;
|
|
113
|
+
req.raw.ip = req.ip;
|
|
114
|
+
req.raw.ips = req.ips;
|
|
115
|
+
req.raw.log = req.log;
|
|
116
|
+
// eslint-disable-next-line no-param-reassign
|
|
117
|
+
reply.raw.log = req.log;
|
|
118
|
+
const originalProtocol = req.raw.protocol;
|
|
119
|
+
// Make it lazy as it does a bit of work
|
|
120
|
+
Object.defineProperty(req.raw, 'protocol', {
|
|
121
|
+
get() {
|
|
122
|
+
// added in Fastify@3.5, so handle it missing
|
|
123
|
+
return req.protocol || originalProtocol;
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
next();
|
|
127
|
+
}
|
|
128
|
+
function runConnect(req, reply, next) {
|
|
129
|
+
if (this[kMiddlewares].length > 0) {
|
|
130
|
+
for (const [headerName, headerValue] of Object.entries(reply.getHeaders())) {
|
|
131
|
+
reply.raw.setHeader(headerName, headerValue);
|
|
132
|
+
}
|
|
133
|
+
this.express(req.raw, reply.raw, next);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
next();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function onRegister(instance) {
|
|
140
|
+
const middlewares = instance[kMiddlewares].slice();
|
|
141
|
+
// eslint-disable-next-line no-param-reassign
|
|
142
|
+
instance[kMiddlewares] = [];
|
|
143
|
+
instance.decorate('express', express__default["default"]());
|
|
144
|
+
instance.express.disable('x-powered-by');
|
|
145
|
+
instance.decorate('use', use);
|
|
146
|
+
for (const middleware of middlewares) {
|
|
147
|
+
instance.use(...middleware);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
next();
|
|
83
151
|
};
|
|
84
|
-
const
|
|
85
|
-
|
|
152
|
+
const fastifyExpressCompatibility = fp__default["default"](expressPlugin, {
|
|
153
|
+
fastify: '>=3.0.0',
|
|
154
|
+
name: 'fastify-express',
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const errorHandler = (app, { log, beforeError, processError, afterError, }) => {
|
|
158
|
+
app.setErrorHandler(async (error, request, reply) => {
|
|
159
|
+
const runHandlers = async (handlers) => {
|
|
160
|
+
if (handlers) {
|
|
161
|
+
for (const handler of handlers) {
|
|
162
|
+
const result = await handler(error, request, reply);
|
|
163
|
+
if (result) {
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
86
169
|
const requestInfo = {
|
|
87
|
-
ip:
|
|
88
|
-
requestId:
|
|
89
|
-
url:
|
|
170
|
+
ip: request.ip,
|
|
171
|
+
requestId: request.headers['x-request-id'],
|
|
172
|
+
url: request.url,
|
|
90
173
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
174
|
+
const beforeErrorResult = await runHandlers(beforeError);
|
|
175
|
+
if (!isNil__default["default"](beforeErrorResult)) {
|
|
176
|
+
return beforeErrorResult;
|
|
177
|
+
}
|
|
178
|
+
if (errors.isRedirectFoundError(error)) {
|
|
179
|
+
reply.header('cache-control', 'no-cache, no-store, must-revalidate');
|
|
180
|
+
reply.redirect(error.httpStatus || 307, error.nextUrl);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (errors.isNotFoundError(error)) {
|
|
184
|
+
reply.status(404);
|
|
185
|
+
return '';
|
|
186
|
+
}
|
|
187
|
+
const processErrorResult = await runHandlers(processError);
|
|
188
|
+
if (!isNil__default["default"](processErrorResult)) {
|
|
189
|
+
return processErrorResult;
|
|
190
|
+
}
|
|
191
|
+
if (errors.isHttpError(error)) {
|
|
192
|
+
if (error.httpStatus >= 500) {
|
|
193
|
+
log.error({ event: 'send-server-error', error, requestInfo });
|
|
94
194
|
}
|
|
95
|
-
|
|
195
|
+
reply.status(error.httpStatus);
|
|
196
|
+
return '';
|
|
197
|
+
}
|
|
198
|
+
log.error({ event: 'send-server-error', error, requestInfo });
|
|
199
|
+
const afterErrorResult = await runHandlers(afterError);
|
|
200
|
+
if (!isNil__default["default"](afterErrorResult)) {
|
|
201
|
+
return afterErrorResult;
|
|
96
202
|
}
|
|
97
|
-
|
|
98
|
-
finalhandler__default["default"](req, res)(err);
|
|
203
|
+
throw error;
|
|
99
204
|
});
|
|
100
205
|
};
|
|
101
206
|
|
|
102
|
-
const webAppFactory = () => {
|
|
207
|
+
const webAppFactory = ({ server, expressApp, }) => {
|
|
208
|
+
const app = fastify__default["default"]({
|
|
209
|
+
serverFactory: (handler) => {
|
|
210
|
+
server.on('request', handler);
|
|
211
|
+
return server;
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
return app;
|
|
215
|
+
};
|
|
216
|
+
const webAppExpressFactory = ({ webApp }) => {
|
|
103
217
|
const app = express__default["default"]();
|
|
104
218
|
app.disable('etag');
|
|
105
219
|
app.disable('x-powered-by');
|
|
106
220
|
return app;
|
|
107
221
|
};
|
|
108
|
-
const webAppInitCommand = ({ app, logger, commandLineRunner, beforeInit, init, afterInit, limiterRequest, }) => {
|
|
222
|
+
const webAppInitCommand = ({ app, expressApp, logger, commandLineRunner, beforeInit, init, afterInit, limiterRequest, expressBeforeInit, expressInit, expressAfterInit, expressLimiterRequest, beforeError, processError, afterError, }) => {
|
|
109
223
|
const log = logger('server:webapp');
|
|
110
|
-
const runHandlers = (handlers) => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
224
|
+
const runHandlers = (handlers, expressHandlers) => {
|
|
225
|
+
return Promise.all([
|
|
226
|
+
handlers && Promise.all(handlers.map((handler) => handler(app))),
|
|
227
|
+
expressHandlers && Promise.all(expressHandlers.map((handler) => handler(expressApp))),
|
|
228
|
+
]);
|
|
114
229
|
};
|
|
115
230
|
return async function webAppInit() {
|
|
116
|
-
|
|
117
|
-
await
|
|
118
|
-
|
|
231
|
+
errorHandler(app, { log, beforeError, processError, afterError });
|
|
232
|
+
await app.register(fastifyExpressCompatibility, {
|
|
233
|
+
express: {
|
|
234
|
+
instance: expressApp,
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
await runHandlers(beforeInit, expressBeforeInit);
|
|
238
|
+
await runHandlers(limiterRequest, expressLimiterRequest);
|
|
239
|
+
await app.register(fastifyCookie.fastifyCookie);
|
|
240
|
+
await app.register(fastifyFormBody__default["default"]);
|
|
241
|
+
expressApp.use(bodyParser__default["default"].urlencoded({
|
|
119
242
|
limit: '2mb',
|
|
120
243
|
extended: false,
|
|
121
244
|
}), cookieParser__default["default"]());
|
|
122
|
-
await runHandlers(init);
|
|
123
|
-
|
|
245
|
+
await runHandlers(init, expressInit);
|
|
246
|
+
// force express to execute to update server's request and response instances
|
|
247
|
+
app.use((req, res, next) => {
|
|
248
|
+
next();
|
|
249
|
+
});
|
|
250
|
+
app.all('*', async (request, reply) => {
|
|
124
251
|
try {
|
|
125
252
|
log.debug({
|
|
126
253
|
event: 'start:request',
|
|
127
254
|
message: 'Клиент зашел на страницу',
|
|
128
|
-
url:
|
|
255
|
+
url: request.url,
|
|
129
256
|
});
|
|
130
257
|
const di = await commandLineRunner.run('server', 'customer', [
|
|
131
258
|
{
|
|
132
|
-
provide:
|
|
259
|
+
provide: tokensCommon.REQUEST,
|
|
133
260
|
scope: core.Scope.REQUEST,
|
|
134
|
-
useValue:
|
|
261
|
+
useValue: request.raw,
|
|
135
262
|
},
|
|
136
263
|
{
|
|
137
|
-
provide:
|
|
264
|
+
provide: tokensCommon.RESPONSE,
|
|
138
265
|
scope: core.Scope.REQUEST,
|
|
139
|
-
useValue:
|
|
266
|
+
useValue: reply.raw,
|
|
267
|
+
},
|
|
268
|
+
// TODO: перевести использование на новые
|
|
269
|
+
// TODO: добавить для papi
|
|
270
|
+
{
|
|
271
|
+
provide: tokensCommon.FASTIFY_REQUEST,
|
|
272
|
+
scope: core.Scope.REQUEST,
|
|
273
|
+
useValue: request,
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
provide: tokensCommon.FASTIFY_RESPONSE,
|
|
277
|
+
scope: core.Scope.REQUEST,
|
|
278
|
+
useValue: reply,
|
|
140
279
|
},
|
|
141
280
|
]);
|
|
142
|
-
const responseManager = di.get(
|
|
143
|
-
if (
|
|
281
|
+
const responseManager = di.get(tokensCommon.RESPONSE_MANAGER_TOKEN);
|
|
282
|
+
if (reply.sent) {
|
|
144
283
|
log.debug({
|
|
145
284
|
event: 'response-ended',
|
|
146
285
|
message: 'Response was already ended.',
|
|
147
|
-
url:
|
|
286
|
+
url: request.url,
|
|
148
287
|
});
|
|
149
288
|
}
|
|
150
289
|
else {
|
|
151
|
-
|
|
152
|
-
.
|
|
153
|
-
.
|
|
290
|
+
reply
|
|
291
|
+
.header('content-type', 'text/html')
|
|
292
|
+
.headers(responseManager.getHeaders())
|
|
154
293
|
.status(responseManager.getStatus())
|
|
155
294
|
.send(responseManager.getBody());
|
|
156
295
|
}
|
|
157
296
|
}
|
|
158
297
|
catch (err) {
|
|
159
298
|
if (err.di) {
|
|
160
|
-
const responseManager = err.di.get(
|
|
161
|
-
if (responseManager && !
|
|
162
|
-
|
|
299
|
+
const responseManager = err.di.get(tokensCommon.RESPONSE_MANAGER_TOKEN);
|
|
300
|
+
if (responseManager && !reply.sent) {
|
|
301
|
+
reply.headers(responseManager.getHeaders());
|
|
163
302
|
}
|
|
164
303
|
}
|
|
165
|
-
|
|
304
|
+
throw err;
|
|
166
305
|
}
|
|
167
306
|
});
|
|
168
|
-
|
|
169
|
-
await
|
|
170
|
-
errorHandler(app, { log });
|
|
307
|
+
await runHandlers(afterInit, expressAfterInit);
|
|
308
|
+
await app.ready();
|
|
171
309
|
};
|
|
172
310
|
};
|
|
173
311
|
|
|
@@ -257,10 +395,20 @@ try {
|
|
|
257
395
|
Api = require('@tramvai/cli/lib/external/api').default; // eslint-disable-line import/no-unresolved
|
|
258
396
|
}
|
|
259
397
|
catch (e) { }
|
|
260
|
-
const getFileApi = () => {
|
|
398
|
+
const getFileApi = ({ logger }) => {
|
|
399
|
+
const log = logger('papi:fileApi');
|
|
261
400
|
const result = [];
|
|
262
401
|
eachObj__default["default"]((v, k) => {
|
|
263
402
|
const handler = (v.handler || v.default);
|
|
403
|
+
if (!handler) {
|
|
404
|
+
log.error({
|
|
405
|
+
message: `Cannot resolve a papi handler.
|
|
406
|
+
Check that you are using file based papi right way by docs https://tramvai.dev/docs/how-to/how-create-papi#automatic-handler-creation
|
|
407
|
+
In case you have not added any file papi handler, consider renaming directory ./src/api (by default) to the other name to resolve conflicts with papi, or
|
|
408
|
+
change settings application.commands.build.options.serverApiDir in tramvai.json`,
|
|
409
|
+
});
|
|
410
|
+
throw new Error('Not a papi');
|
|
411
|
+
}
|
|
264
412
|
const papiParameters = papi.getPapiParameters(handler);
|
|
265
413
|
result.push(papi.createPapiMethod({
|
|
266
414
|
...v,
|
|
@@ -274,7 +422,10 @@ const getFileApi = () => {
|
|
|
274
422
|
const fileApiProvider = {
|
|
275
423
|
provide: tokensServer.SERVER_MODULE_PAPI_PUBLIC_ROUTE,
|
|
276
424
|
multi: true,
|
|
277
|
-
|
|
425
|
+
useFactory: getFileApi,
|
|
426
|
+
deps: {
|
|
427
|
+
logger: tokensCommon.LOGGER_TOKEN,
|
|
428
|
+
},
|
|
278
429
|
};
|
|
279
430
|
|
|
280
431
|
const sharedProviders = [
|
|
@@ -447,12 +598,12 @@ ServerGracefulShutdownModule = tslib.__decorate([
|
|
|
447
598
|
core.Module({
|
|
448
599
|
providers: [
|
|
449
600
|
{
|
|
450
|
-
provide:
|
|
601
|
+
provide: tokensServerPrivate.WEB_FASTIFY_APP_BEFORE_INIT_TOKEN,
|
|
451
602
|
multi: true,
|
|
452
|
-
useFactory: ({
|
|
603
|
+
useFactory: ({ app, server, logger, commandLineRunner, livenessProbe, readinessProbe, }) => {
|
|
453
604
|
const log = logger('server');
|
|
454
605
|
return function serverListen() {
|
|
455
|
-
|
|
606
|
+
terminus.createTerminus(server, app, {
|
|
456
607
|
signal: 'SIGTERM',
|
|
457
608
|
timeout: GRACEFUL_SHUTDOWN_TIMEOUT,
|
|
458
609
|
logger: (msg, error) => {
|
|
@@ -492,8 +643,8 @@ ServerGracefulShutdownModule = tslib.__decorate([
|
|
|
492
643
|
};
|
|
493
644
|
},
|
|
494
645
|
deps: {
|
|
646
|
+
app: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
495
647
|
server: tokensServer.SERVER_TOKEN,
|
|
496
|
-
app: tokensServer.WEB_APP_TOKEN,
|
|
497
648
|
logger: tokensCommon.LOGGER_TOKEN,
|
|
498
649
|
commandLineRunner: core.COMMAND_LINE_RUNNER_TOKEN,
|
|
499
650
|
readinessProbe: { token: tokensServer.READINESS_PROBE_TOKEN, optional: true },
|
|
@@ -759,31 +910,48 @@ exports.ServerModule = tslib.__decorate([
|
|
|
759
910
|
process.env.NODE_ENV !== 'production' && DebugHttpRequestsModule,
|
|
760
911
|
].filter(Boolean),
|
|
761
912
|
providers: [
|
|
762
|
-
{
|
|
763
|
-
provide: tokensServer.
|
|
913
|
+
core.provide({
|
|
914
|
+
provide: tokensServer.SERVER_TOKEN,
|
|
764
915
|
scope: core.Scope.SINGLETON,
|
|
916
|
+
useFactory: serverFactory,
|
|
917
|
+
}),
|
|
918
|
+
core.provide({
|
|
919
|
+
provide: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
765
920
|
useFactory: webAppFactory,
|
|
766
|
-
|
|
921
|
+
scope: core.Scope.SINGLETON,
|
|
922
|
+
deps: {
|
|
923
|
+
server: tokensServer.SERVER_TOKEN,
|
|
924
|
+
},
|
|
925
|
+
}),
|
|
926
|
+
core.provide({
|
|
927
|
+
// BACKWARD: provide the express app as before
|
|
928
|
+
provide: tokensServer.WEB_APP_TOKEN,
|
|
929
|
+
scope: core.Scope.SINGLETON,
|
|
930
|
+
useFactory: webAppExpressFactory,
|
|
931
|
+
deps: {
|
|
932
|
+
webApp: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
933
|
+
},
|
|
934
|
+
}),
|
|
767
935
|
{
|
|
768
936
|
provide: core.commandLineListTokens.init,
|
|
769
937
|
multi: true,
|
|
770
938
|
useFactory: webAppInitCommand,
|
|
771
939
|
deps: {
|
|
772
|
-
app:
|
|
773
|
-
|
|
940
|
+
app: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
941
|
+
expressApp: tokensServer.WEB_APP_TOKEN,
|
|
942
|
+
logger: tokensCommon.LOGGER_TOKEN,
|
|
774
943
|
commandLineRunner: core.COMMAND_LINE_RUNNER_TOKEN,
|
|
775
|
-
beforeInit: { token:
|
|
776
|
-
init: { token:
|
|
777
|
-
afterInit: { token:
|
|
778
|
-
limiterRequest: { token:
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
webApp: tokensServer.WEB_APP_TOKEN,
|
|
944
|
+
beforeInit: { token: tokensServerPrivate.WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, optional: true },
|
|
945
|
+
init: { token: tokensServerPrivate.WEB_FASTIFY_APP_INIT_TOKEN, optional: true },
|
|
946
|
+
afterInit: { token: tokensServerPrivate.WEB_FASTIFY_APP_AFTER_INIT_TOKEN, optional: true },
|
|
947
|
+
limiterRequest: { token: tokensServerPrivate.WEB_FASTIFY_APP_LIMITER_TOKEN, optional: true },
|
|
948
|
+
expressBeforeInit: { token: tokensServer.WEB_APP_BEFORE_INIT_TOKEN, optional: true },
|
|
949
|
+
expressInit: { token: tokensServer.WEB_APP_INIT_TOKEN, optional: true },
|
|
950
|
+
expressAfterInit: { token: tokensServer.WEB_APP_AFTER_INIT_TOKEN, optional: true },
|
|
951
|
+
expressLimiterRequest: { token: tokensServer.WEB_APP_LIMITER_TOKEN, optional: true },
|
|
952
|
+
beforeError: { token: tokensServerPrivate.WEB_FASTIFY_APP_BEFORE_ERROR_TOKEN, optional: true },
|
|
953
|
+
processError: { token: tokensServerPrivate.WEB_FASTIFY_APP_PROCESS_ERROR_TOKEN, optional: true },
|
|
954
|
+
afterError: { token: tokensServerPrivate.WEB_FASTIFY_APP_AFTER_ERROR_TOKEN, optional: true },
|
|
787
955
|
},
|
|
788
956
|
},
|
|
789
957
|
{
|
|
@@ -792,8 +960,8 @@ exports.ServerModule = tslib.__decorate([
|
|
|
792
960
|
useFactory: serverListenCommand,
|
|
793
961
|
deps: {
|
|
794
962
|
server: tokensServer.SERVER_TOKEN,
|
|
795
|
-
logger:
|
|
796
|
-
envManager:
|
|
963
|
+
logger: tokensCommon.LOGGER_TOKEN,
|
|
964
|
+
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
797
965
|
},
|
|
798
966
|
},
|
|
799
967
|
{
|
|
@@ -801,13 +969,13 @@ exports.ServerModule = tslib.__decorate([
|
|
|
801
969
|
multi: true,
|
|
802
970
|
useFactory: staticAppCommand,
|
|
803
971
|
deps: {
|
|
804
|
-
logger:
|
|
805
|
-
envManager:
|
|
972
|
+
logger: tokensCommon.LOGGER_TOKEN,
|
|
973
|
+
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
806
974
|
appInfo: core.APP_INFO_TOKEN,
|
|
807
975
|
},
|
|
808
976
|
},
|
|
809
977
|
{
|
|
810
|
-
provide:
|
|
978
|
+
provide: tokensCommon.ENV_USED_TOKEN,
|
|
811
979
|
multi: true,
|
|
812
980
|
useValue: [
|
|
813
981
|
{ key: 'DEV_STATIC', optional: true, dehydrate: false },
|
|
@@ -832,7 +1000,7 @@ exports.ServerModule = tslib.__decorate([
|
|
|
832
1000
|
useFactory: xHeadersFactory,
|
|
833
1001
|
deps: {
|
|
834
1002
|
app: tokensServer.WEB_APP_TOKEN,
|
|
835
|
-
envManager:
|
|
1003
|
+
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
836
1004
|
appInfo: core.APP_INFO_TOKEN,
|
|
837
1005
|
},
|
|
838
1006
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.89.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "lib/browser.js",
|
|
6
6
|
"main": "lib/server.js",
|
|
@@ -20,34 +20,37 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@tinkoff/errors": "0.2.20",
|
|
23
|
-
"@tinkoff/
|
|
23
|
+
"@tinkoff/terminus": "0.0.1",
|
|
24
24
|
"@tinkoff/monkeypatch": "1.3.3",
|
|
25
25
|
"@tinkoff/url": "0.7.37",
|
|
26
|
-
"@tramvai/module-cache-warmup": "1.
|
|
27
|
-
"@tramvai/module-metrics": "1.
|
|
28
|
-
"@tramvai/papi": "1.
|
|
29
|
-
"@tramvai/tokens-server": "1.
|
|
26
|
+
"@tramvai/module-cache-warmup": "1.89.1",
|
|
27
|
+
"@tramvai/module-metrics": "1.89.1",
|
|
28
|
+
"@tramvai/papi": "1.89.1",
|
|
29
|
+
"@tramvai/tokens-server": "1.89.1",
|
|
30
|
+
"@tramvai/tokens-server-private": "1.89.1",
|
|
30
31
|
"body-parser": "^1.19.0",
|
|
31
32
|
"compression": "^1.7.4",
|
|
32
33
|
"cookie-parser": "^1.4.3",
|
|
33
34
|
"express": "^4.17.1",
|
|
34
|
-
"
|
|
35
|
+
"fastify": "^3.27.4",
|
|
36
|
+
"fastify-cookie": "^5.6.0",
|
|
37
|
+
"fastify-formbody": "^5.2.0",
|
|
38
|
+
"fastify-plugin": "^3.0.1",
|
|
35
39
|
"http-proxy-middleware": "^2.0.2"
|
|
36
40
|
},
|
|
37
41
|
"peerDependencies": {
|
|
38
|
-
"@tinkoff/utils": "^2.1.2",
|
|
39
|
-
"@tramvai/cli": "1.84.0",
|
|
40
|
-
"@tramvai/core": "1.84.0",
|
|
41
|
-
"@tramvai/module-common": "1.84.0",
|
|
42
|
-
"@tramvai/module-environment": "1.84.0",
|
|
43
|
-
"@tramvai/tokens-common": "1.84.0",
|
|
44
42
|
"@tinkoff/dippy": "0.7.39",
|
|
43
|
+
"@tinkoff/utils": "^2.1.2",
|
|
44
|
+
"@tramvai/cli": "1.89.1",
|
|
45
|
+
"@tramvai/core": "1.89.1",
|
|
46
|
+
"@tramvai/module-common": "1.89.1",
|
|
47
|
+
"@tramvai/module-environment": "1.89.1",
|
|
48
|
+
"@tramvai/tokens-common": "1.89.1",
|
|
45
49
|
"tslib": "^2.0.3"
|
|
46
50
|
},
|
|
47
51
|
"devDependencies": {
|
|
48
52
|
"@types/compression": "^1.7.0",
|
|
49
53
|
"@types/express": "^4.17.9",
|
|
50
|
-
"@types/finalhandler": "^1.1.0",
|
|
51
54
|
"@types/http-proxy-middleware": "^0.19.3"
|
|
52
55
|
},
|
|
53
56
|
"module": "lib/server.es.js",
|