badmfck-api-server 3.8.3 → 3.8.4
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.
@@ -32,8 +32,6 @@ export interface APIServiceOptions<TInterceptor = unknown> {
|
|
32
32
|
projectName: string;
|
33
33
|
endpoints: IBaseEndpoint[];
|
34
34
|
jsonLimit: string;
|
35
|
-
onNetworkLog?: ((log: APIServiceNetworkLogItem) => void) | null;
|
36
|
-
onError?: ((...rest: any[]) => void) | null;
|
37
35
|
isProductionEnvironment: boolean;
|
38
36
|
interceptor?: IInterceptor<TInterceptor>;
|
39
37
|
postproducer?: (req: HTTPRequestVO | undefined | null, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null) => Promise<TransferPacketVO>;
|
@@ -48,10 +46,10 @@ export interface APIServiceOptions<TInterceptor = unknown> {
|
|
48
46
|
fileLimit: number;
|
49
47
|
}
|
50
48
|
type InferInterceptor<T> = T extends IInterceptor<infer U> ? U : unknown;
|
51
|
-
export declare
|
52
|
-
interceptor?: I;
|
53
|
-
})
|
54
|
-
export declare const
|
49
|
+
export declare const getDefaultOptions: <I extends IInterceptor<any> | undefined>(overrides?: (Omit<Partial<APIServiceOptions<InferInterceptor<NonNullable<I>>>>, "interceptor"> & {
|
50
|
+
interceptor?: I | undefined;
|
51
|
+
}) | undefined) => APIServiceOptions<InferInterceptor<NonNullable<I>>>;
|
52
|
+
export declare const REQ_DEPREACTED_CREATE_NET_LOG: Req<void, APIServiceNetworkLogItem>;
|
55
53
|
export declare const REQ_HTTP_LOG: Req<void, APIServiceNetworkLogItem[]>;
|
56
54
|
export declare const REQ_HTTP_REQUESTS_COUNT: Req<void, number>;
|
57
55
|
export declare const REQ_HTTP_SERVER: Req<void, {
|
@@ -72,7 +70,8 @@ export declare class APIService extends BaseService {
|
|
72
70
|
netLog: APIServiceNetworkLogItem[];
|
73
71
|
constructor(options: APIServiceOptions);
|
74
72
|
init(): Promise<void>;
|
75
|
-
|
73
|
+
addNetlog(data: TransferPacketVO, req: HTTPRequestVO, created: number, time: number): void;
|
74
|
+
sendResponse(ref: string, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, req?: HTTPRequestVO): Promise<void>;
|
76
75
|
checkDataLength(data: any, result?: any, lvl?: number): any;
|
77
76
|
}
|
78
77
|
export {};
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
27
|
};
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
-
exports.APIService = exports.Initializer = exports.REQ_DOC_USERS = exports.REQ_MONITOR_USERS = exports.REQ_INTERNAL_CALL = exports.REQ_HTTP_SERVER = exports.REQ_HTTP_REQUESTS_COUNT = exports.REQ_HTTP_LOG = exports.
|
29
|
+
exports.APIService = exports.Initializer = exports.REQ_DOC_USERS = exports.REQ_MONITOR_USERS = exports.REQ_INTERNAL_CALL = exports.REQ_HTTP_SERVER = exports.REQ_HTTP_REQUESTS_COUNT = exports.REQ_HTTP_LOG = exports.REQ_DEPREACTED_CREATE_NET_LOG = exports.getDefaultOptions = void 0;
|
30
30
|
const express_1 = __importDefault(require("express"));
|
31
31
|
const BaseService_1 = require("./BaseService");
|
32
32
|
const cors_1 = __importDefault(require("cors"));
|
@@ -35,9 +35,7 @@ const DefaultErrors_1 = __importStar(require("./structures/DefaultErrors"));
|
|
35
35
|
const badmfck_signal_1 = require("badmfck-signal");
|
36
36
|
const LogService_1 = require("./LogService");
|
37
37
|
const Monitor_1 = require("./monitor/Monitor");
|
38
|
-
const path_1 = __importDefault(require("path"));
|
39
38
|
const express_fileupload_1 = __importDefault(require("express-fileupload"));
|
40
|
-
const os_1 = __importDefault(require("os"));
|
41
39
|
const Liveness_1 = require("./routes/Liveness");
|
42
40
|
const Readiness_1 = require("./routes/Readiness");
|
43
41
|
const http_1 = __importDefault(require("http"));
|
@@ -47,36 +45,35 @@ const MonitorService_1 = require("./MonitorService");
|
|
47
45
|
const MysqlAdapter_1 = require("./db/MysqlAdapter");
|
48
46
|
const DocumentService_1 = require("./DocumentService");
|
49
47
|
const Documentation_1 = require("./documentation/Documentation");
|
48
|
+
let nextLogID = 0;
|
50
49
|
function bindRequestToOptions(opts, req) {
|
51
50
|
return req;
|
52
51
|
}
|
53
|
-
function
|
52
|
+
function defaultOptions() {
|
54
53
|
return {
|
55
|
-
port:
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
},
|
60
|
-
baseEndPoint: '/api/',
|
61
|
-
corsHostWhiteList: [
|
62
|
-
'http://localhost:3000',
|
63
|
-
],
|
54
|
+
port: 8080,
|
55
|
+
baseEndPoint: "/api/",
|
56
|
+
corsHostWhiteList: [],
|
57
|
+
projectName: "App",
|
64
58
|
endpoints: [],
|
65
59
|
jsonLimit: "10mb",
|
66
|
-
onNetworkLog: function (log) {
|
67
|
-
(0, LogService_1.logAPI)("${APIService.js}", log);
|
68
|
-
},
|
69
|
-
onError: function (err) {
|
70
|
-
(0, LogService_1.logError)("${APIService.js}", err);
|
71
|
-
},
|
72
|
-
projectName: "API Service",
|
73
60
|
isProductionEnvironment: false,
|
74
|
-
|
75
|
-
|
61
|
+
interceptor: undefined,
|
62
|
+
postproducer: undefined,
|
63
|
+
preproducer: undefined,
|
64
|
+
access: {},
|
65
|
+
monitor: undefined,
|
66
|
+
appVersion: undefined,
|
67
|
+
fileTempDir: "/tmp",
|
68
|
+
fileLimit: 10_000_000,
|
76
69
|
};
|
77
70
|
}
|
71
|
+
const getDefaultOptions = (overrides) => {
|
72
|
+
const base = defaultOptions();
|
73
|
+
return { ...base, ...overrides };
|
74
|
+
};
|
78
75
|
exports.getDefaultOptions = getDefaultOptions;
|
79
|
-
exports.
|
76
|
+
exports.REQ_DEPREACTED_CREATE_NET_LOG = new badmfck_signal_1.Req(undefined, "REQ_CREATE_NET_LOG");
|
80
77
|
exports.REQ_HTTP_LOG = new badmfck_signal_1.Req(undefined, "REQ_HTTP_LOG");
|
81
78
|
exports.REQ_HTTP_REQUESTS_COUNT = new badmfck_signal_1.Req(undefined, "REQ_HTTP_REQUESTS_COUNT");
|
82
79
|
exports.REQ_HTTP_SERVER = new badmfck_signal_1.Req(undefined, "REQ_HTTP_SERVER");
|
@@ -98,7 +95,7 @@ async function Initializer(services) {
|
|
98
95
|
exports.Initializer = Initializer;
|
99
96
|
class APIService extends BaseService_1.BaseService {
|
100
97
|
static nextLogID = 0;
|
101
|
-
version = "3.8.
|
98
|
+
version = "3.8.4";
|
102
99
|
options;
|
103
100
|
monitor = null;
|
104
101
|
started = new Date();
|
@@ -124,21 +121,7 @@ class APIService extends BaseService_1.BaseService {
|
|
124
121
|
exports.REQ_HTTP_REQUESTS_COUNT.listener = async () => this.requestsCount;
|
125
122
|
}
|
126
123
|
async init() {
|
127
|
-
exports.REQ_HTTP_LOG.listener = async (
|
128
|
-
exports.REQ_CREATE_NET_LOG.listener = async (ignore) => {
|
129
|
-
const log = {
|
130
|
-
created: +new Date(),
|
131
|
-
time: 0,
|
132
|
-
request: {},
|
133
|
-
response: {},
|
134
|
-
error: null,
|
135
|
-
id: APIService.nextLogID++
|
136
|
-
};
|
137
|
-
this.netLog.push(log);
|
138
|
-
if (this.netLog.length > 1000)
|
139
|
-
this.netLog.shift();
|
140
|
-
return log;
|
141
|
-
};
|
124
|
+
exports.REQ_HTTP_LOG.listener = async (_) => this.netLog;
|
142
125
|
exports.REQ_INTERNAL_CALL.listener = async (req) => {
|
143
126
|
for (let i of this.options.endpoints) {
|
144
127
|
if (!i || !i.endpoints)
|
@@ -170,7 +153,17 @@ class APIService extends BaseService_1.BaseService {
|
|
170
153
|
error: DefaultErrors_1.default.FILE_TOO_LARGE,
|
171
154
|
data: null,
|
172
155
|
httpStatus: 413,
|
173
|
-
}, +new Date(), req.path
|
156
|
+
}, +new Date(), req.path, {
|
157
|
+
endpoint: req.path,
|
158
|
+
headers: req.headers,
|
159
|
+
method: req.method,
|
160
|
+
data: req.body,
|
161
|
+
params: req.params,
|
162
|
+
interceptorResult: null,
|
163
|
+
raw: req,
|
164
|
+
response: undefined,
|
165
|
+
files: undefined
|
166
|
+
});
|
174
167
|
},
|
175
168
|
limits: { fileSize: this.options.fileLimit },
|
176
169
|
useTempFiles: true,
|
@@ -184,12 +177,6 @@ class APIService extends BaseService_1.BaseService {
|
|
184
177
|
return;
|
185
178
|
}
|
186
179
|
const tme = +new Date();
|
187
|
-
const log = await exports.REQ_CREATE_NET_LOG.request();
|
188
|
-
log.request = {
|
189
|
-
method: req.method,
|
190
|
-
data: "",
|
191
|
-
params: req.params
|
192
|
-
};
|
193
180
|
let responseError = DefaultErrors_1.default.UNKNOWN_REQUEST;
|
194
181
|
if (typeof err === "object" && err.status === 400 && 'body' in err && err.type === 'entity.parse.failed') {
|
195
182
|
responseError = DefaultErrors_1.default.JSON_MALFORMED;
|
@@ -198,7 +185,17 @@ class APIService extends BaseService_1.BaseService {
|
|
198
185
|
error: responseError,
|
199
186
|
data: null,
|
200
187
|
httpStatus: 400
|
201
|
-
}, tme, "",
|
188
|
+
}, tme, "", {
|
189
|
+
endpoint: "",
|
190
|
+
headers: req.headers,
|
191
|
+
method: req.method,
|
192
|
+
data: req.body,
|
193
|
+
params: req.params,
|
194
|
+
interceptorResult: null,
|
195
|
+
raw: req,
|
196
|
+
response: undefined,
|
197
|
+
files: undefined
|
198
|
+
});
|
202
199
|
});
|
203
200
|
const corsOptions = {
|
204
201
|
origin: (origin, callback) => {
|
@@ -219,16 +216,6 @@ class APIService extends BaseService_1.BaseService {
|
|
219
216
|
app.all(ep, async (req, res) => {
|
220
217
|
this.requestsCount++;
|
221
218
|
const tme = +new Date();
|
222
|
-
let log = null;
|
223
|
-
if (!i.ignoreHttpLogging) {
|
224
|
-
log = await exports.REQ_CREATE_NET_LOG.request();
|
225
|
-
log.request = {
|
226
|
-
url: req.url,
|
227
|
-
method: req.method,
|
228
|
-
data: this.checkDataLength(req.body),
|
229
|
-
params: this.checkDataLength(req.params)
|
230
|
-
};
|
231
|
-
}
|
232
219
|
const execute = async () => {
|
233
220
|
const body = req.body;
|
234
221
|
if (req.query && typeof req.query === "object") {
|
@@ -262,10 +249,10 @@ class APIService extends BaseService_1.BaseService {
|
|
262
249
|
stack = [e];
|
263
250
|
}
|
264
251
|
if ((0, MysqlAdapter_1.isError)(e)) {
|
265
|
-
this.sendResponse(req.get("Referer") ?? "", res, { error: { ...DefaultErrors_1.default.DB_ERROR, details: e.message } }, tme, ep,
|
252
|
+
this.sendResponse(req.get("Referer") ?? "", res, { error: { ...DefaultErrors_1.default.DB_ERROR, details: e.message } }, tme, ep, httpRequest);
|
266
253
|
return;
|
267
254
|
}
|
268
|
-
this.sendResponse(req.get("Referer") ?? "", res, { error: { code: 10002, message: "Internal server error!", stack: stack, details: details }, data: null, httpStatus: 500 }, tme, ep,
|
255
|
+
this.sendResponse(req.get("Referer") ?? "", res, { error: { code: 10002, message: "Internal server error!", stack: stack, details: details }, data: null, httpStatus: 500 }, tme, ep, httpRequest);
|
269
256
|
return;
|
270
257
|
}
|
271
258
|
}
|
@@ -292,7 +279,7 @@ class APIService extends BaseService_1.BaseService {
|
|
292
279
|
const httpRequestBound = bindRequestToOptions(this.options, httpRequest);
|
293
280
|
interceptorResult = await this.options.interceptor.intercept(httpRequest);
|
294
281
|
if (DefaultErrors_1.ErrorUtils.isError(interceptorResult) && !allowInterceptorError) {
|
295
|
-
this.sendResponse(req.get("Referer") ?? "", res, interceptorResult, tme, ep,
|
282
|
+
this.sendResponse(req.get("Referer") ?? "", res, interceptorResult, tme, ep, httpRequest);
|
296
283
|
return;
|
297
284
|
}
|
298
285
|
httpRequestBound.interceptorResult = interceptorResult;
|
@@ -301,7 +288,7 @@ class APIService extends BaseService_1.BaseService {
|
|
301
288
|
}
|
302
289
|
const precheck = await i.__precheck(httpRequest);
|
303
290
|
if (precheck && precheck.error) {
|
304
|
-
this.sendResponse(req.get("Referer") ?? "", res, precheck, tme, ep,
|
291
|
+
this.sendResponse(req.get("Referer") ?? "", res, precheck, tme, ep, httpRequest);
|
305
292
|
return;
|
306
293
|
}
|
307
294
|
httpRequest.precheck = precheck;
|
@@ -337,10 +324,10 @@ class APIService extends BaseService_1.BaseService {
|
|
337
324
|
error: { ...DefaultErrors_1.default.DB_ERROR, details: e.message }
|
338
325
|
};
|
339
326
|
}
|
340
|
-
this.sendResponse(req.get("Referer") ?? "", res, data, tme, ep,
|
327
|
+
this.sendResponse(req.get("Referer") ?? "", res, data, tme, ep, httpRequest);
|
341
328
|
return;
|
342
329
|
}
|
343
|
-
this.sendResponse(req.get("Referer") ?? "", res, result, tme, ep,
|
330
|
+
this.sendResponse(req.get("Referer") ?? "", res, result, tme, ep, httpRequest);
|
344
331
|
};
|
345
332
|
execute();
|
346
333
|
});
|
@@ -352,23 +339,51 @@ class APIService extends BaseService_1.BaseService {
|
|
352
339
|
error: DefaultErrors_1.default.UNKNOWN_REQUEST,
|
353
340
|
data: null,
|
354
341
|
httpStatus: 404
|
355
|
-
}, tme, req.path
|
342
|
+
}, tme, req.path, {
|
343
|
+
endpoint: req.path,
|
344
|
+
headers: req.headers,
|
345
|
+
method: req.method,
|
346
|
+
data: req.body,
|
347
|
+
params: req.params,
|
348
|
+
interceptorResult: null,
|
349
|
+
raw: req,
|
350
|
+
response: undefined,
|
351
|
+
files: undefined
|
352
|
+
});
|
356
353
|
});
|
357
354
|
server.listen(this.options.port, () => {
|
358
355
|
(0, LogService_1.logAPI)('${APIService.js}', 'API Service started at: ' + this.options.port + ", with base endpoint:" + this.options.baseEndPoint + ", ver.: " + this.version);
|
359
356
|
});
|
360
357
|
}
|
361
|
-
|
358
|
+
addNetlog(data, req, created, time) {
|
359
|
+
const logItem = {
|
360
|
+
id: nextLogID++,
|
361
|
+
created: created,
|
362
|
+
time: time,
|
363
|
+
request: {
|
364
|
+
endpoint: req?.endpoint,
|
365
|
+
headers: req?.headers,
|
366
|
+
method: req?.method,
|
367
|
+
data: req?.data,
|
368
|
+
params: req?.params,
|
369
|
+
interceptorResult: req?.interceptorResult
|
370
|
+
},
|
371
|
+
response: data
|
372
|
+
};
|
373
|
+
this.netLog.push(logItem);
|
374
|
+
if (this.netLog.length > 100)
|
375
|
+
this.netLog.shift();
|
376
|
+
}
|
377
|
+
async sendResponse(ref, res, data, requestTime, endpoint, req) {
|
362
378
|
if (data.blockResponse) {
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
this.options.onNetworkLog(log);
|
379
|
+
(0, LogService_1.logAPI)("Response blocked");
|
380
|
+
if (req)
|
381
|
+
this.addNetlog(data, req, requestTime, 0);
|
367
382
|
return;
|
368
383
|
}
|
369
384
|
if (this.options.postproducer) {
|
370
385
|
try {
|
371
|
-
data = await this.options.postproducer(req, res, data, requestTime, endpoint
|
386
|
+
data = await this.options.postproducer(req, res, data, requestTime, endpoint);
|
372
387
|
}
|
373
388
|
catch (e) {
|
374
389
|
(0, LogService_1.logError)("Postproducer error", e);
|
@@ -381,37 +396,28 @@ class APIService extends BaseService_1.BaseService {
|
|
381
396
|
data.endpoint = endpoint ?? "no_endpoint";
|
382
397
|
if (this.options.appVersion)
|
383
398
|
data.version = this.options.appVersion;
|
384
|
-
if (log) {
|
385
|
-
log.time = data.responseTime;
|
386
|
-
log.referer = ref;
|
387
|
-
}
|
388
399
|
MonitorService_1.S_STAT_REGISTRATE_REQUEST.invoke(data);
|
389
400
|
if (res.destroyed || res.closed) {
|
390
|
-
|
391
|
-
log.error = "Connection already closed, can't send response for: " + data.endpoint;
|
392
|
-
if (this.options.onError)
|
393
|
-
this.options.onError("Connection already closed, can't send response: " + data.endpoint, data);
|
401
|
+
(0, LogService_1.logAPI)("Connection already closed, can't send response for: " + data.endpoint);
|
394
402
|
}
|
395
403
|
else {
|
396
404
|
try {
|
397
405
|
if (data.file) {
|
398
406
|
res.sendFile(data.file, err => {
|
399
407
|
if (err) {
|
400
|
-
|
401
|
-
log.error = "Can't send file: " + data.file;
|
408
|
+
(0, LogService_1.logError)("Can't send file: " + data.file);
|
402
409
|
this.sendResponse(ref, res, {
|
403
410
|
error: DefaultErrors_1.default.CANT_SEND_FILE,
|
404
411
|
data: null,
|
405
412
|
httpStatus: 500
|
406
|
-
}, requestTime, data.endpoint);
|
413
|
+
}, requestTime, data.endpoint, req);
|
407
414
|
}
|
408
415
|
});
|
409
416
|
return;
|
410
417
|
}
|
411
418
|
if (data.redirect) {
|
412
419
|
res.redirect(data.redirect);
|
413
|
-
|
414
|
-
log.response = { redirect: data.redirect };
|
420
|
+
(0, LogService_1.logAPI)("redirect: " + data.redirect);
|
415
421
|
}
|
416
422
|
else {
|
417
423
|
if (data.headers) {
|
@@ -424,34 +430,20 @@ class APIService extends BaseService_1.BaseService {
|
|
424
430
|
res.statusCode = data.httpStatus ?? 200;
|
425
431
|
if (data.rawResponse) {
|
426
432
|
res.send(data.data);
|
427
|
-
|
428
|
-
log.response = this.checkDataLength(data);
|
433
|
+
(0, LogService_1.logAPI)(this.checkDataLength(data));
|
429
434
|
}
|
430
435
|
else {
|
431
436
|
res.send(data);
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
if (log)
|
436
|
-
log.error = data.error.message;
|
437
|
-
}
|
437
|
+
(0, LogService_1.logAPI)(this.checkDataLength(data));
|
438
|
+
if (data.error)
|
439
|
+
(0, LogService_1.logError)(data.error.message);
|
438
440
|
}
|
439
441
|
}
|
440
442
|
}
|
441
443
|
catch (e) {
|
442
|
-
|
443
|
-
this.options.onError("Can't send response", e);
|
444
|
-
if (log)
|
445
|
-
log.error = "Can't send response";
|
444
|
+
console.error(e);
|
446
445
|
}
|
447
446
|
}
|
448
|
-
if (log && log.error && this.options.onError) {
|
449
|
-
this.options.onError(log.error);
|
450
|
-
}
|
451
|
-
else {
|
452
|
-
if (this.options.onNetworkLog && log)
|
453
|
-
this.options.onNetworkLog(log);
|
454
|
-
}
|
455
447
|
}
|
456
448
|
checkDataLength(data, result, lvl) {
|
457
449
|
if (!lvl)
|
@@ -26,9 +26,7 @@ export interface HTTPRequestVO<T = any, TInterceport = any> {
|
|
26
26
|
params: {
|
27
27
|
[key: string]: string;
|
28
28
|
};
|
29
|
-
headers:
|
30
|
-
[key: string]: string;
|
31
|
-
};
|
29
|
+
headers: Record<string, string>;
|
32
30
|
endpoint: string;
|
33
31
|
interceptorResult?: any;
|
34
32
|
preproducerResult?: any;
|