badmfck-api-server 2.1.1 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/apiServer/APIService.d.ts +2 -1
- package/dist/apiServer/APIService.js +35 -14
- package/dist/apiServer/MysqlService.d.ts +9 -2
- package/dist/apiServer/MysqlService.js +65 -49
- package/dist/apiServer/structures/DefaultErrors.d.ts +2 -0
- package/dist/apiServer/structures/DefaultErrors.js +2 -0
- package/dist/apiServer/structures/Interfaces.d.ts +2 -0
- package/package.json +1 -1
@@ -9,6 +9,7 @@ export interface APIServiceNetworkLogItem {
|
|
9
9
|
id: number;
|
10
10
|
created: number;
|
11
11
|
time: number;
|
12
|
+
referer?: string;
|
12
13
|
request: {
|
13
14
|
[key: string]: any;
|
14
15
|
};
|
@@ -59,6 +60,6 @@ export declare class APIService extends BaseService {
|
|
59
60
|
netLog: APIServiceNetworkLogItem[];
|
60
61
|
constructor(options?: APIServiceOptions | null);
|
61
62
|
init(): Promise<void>;
|
62
|
-
sendResponse(res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null, req?: HTTPRequestVO): Promise<void>;
|
63
|
+
sendResponse(ref: string, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null, req?: HTTPRequestVO): Promise<void>;
|
63
64
|
checkDataLength(data: any, result?: any, lvl?: number): any;
|
64
65
|
}
|
@@ -83,7 +83,7 @@ async function Initializer(services) {
|
|
83
83
|
exports.Initializer = Initializer;
|
84
84
|
class APIService extends BaseService_1.BaseService {
|
85
85
|
static nextLogID = 0;
|
86
|
-
version = "2.1.
|
86
|
+
version = "2.1.3";
|
87
87
|
options;
|
88
88
|
monitor;
|
89
89
|
monitorIndexFile;
|
@@ -154,10 +154,10 @@ class APIService extends BaseService_1.BaseService {
|
|
154
154
|
app.use(express_1.default.urlencoded({ limit: '10mb', extended: true }));
|
155
155
|
app.use((0, express_fileupload_1.default)({
|
156
156
|
limitHandler: (req, res, next) => {
|
157
|
-
this.sendResponse(res, {
|
157
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
158
158
|
error: DefaultErrors_1.default.FILE_TOO_LARGE,
|
159
159
|
data: null,
|
160
|
-
httpStatus: 413
|
160
|
+
httpStatus: 413,
|
161
161
|
}, +new Date(), req.path);
|
162
162
|
},
|
163
163
|
limits: { fileSize: this.options.fileLimit },
|
@@ -182,7 +182,7 @@ class APIService extends BaseService_1.BaseService {
|
|
182
182
|
if (typeof err === "object" && err.status === 400 && 'body' in err && err.type === 'entity.parse.failed') {
|
183
183
|
responseError = DefaultErrors_1.default.JSON_MALFORMED;
|
184
184
|
}
|
185
|
-
this.sendResponse(resp, {
|
185
|
+
this.sendResponse(req.get("Referer") ?? "", resp, {
|
186
186
|
error: responseError,
|
187
187
|
data: null,
|
188
188
|
httpStatus: 400
|
@@ -231,7 +231,8 @@ class APIService extends BaseService_1.BaseService {
|
|
231
231
|
params: req.params,
|
232
232
|
headers: req.headers,
|
233
233
|
endpoint: ep,
|
234
|
-
files: req.files ?? null
|
234
|
+
files: req.files ?? null,
|
235
|
+
referer: req.get("Referer"),
|
235
236
|
};
|
236
237
|
if (this.options.preproducer) {
|
237
238
|
try {
|
@@ -240,7 +241,7 @@ class APIService extends BaseService_1.BaseService {
|
|
240
241
|
httpRequest.preproducerResult = preproducerResult;
|
241
242
|
}
|
242
243
|
catch (e) {
|
243
|
-
this.sendResponse(res, { error: { code: 10002, message: "Internal server error", details: `${e}` }, data: null, httpStatus: 500 }, tme, ep, log, httpRequest);
|
244
|
+
this.sendResponse(req.get("Referer") ?? "", res, { error: { code: 10002, message: "Internal server error", details: `${e}` }, data: null, httpStatus: 500 }, tme, ep, log, httpRequest);
|
244
245
|
return;
|
245
246
|
}
|
246
247
|
}
|
@@ -251,7 +252,7 @@ class APIService extends BaseService_1.BaseService {
|
|
251
252
|
if (this.options.interceptor) {
|
252
253
|
interceptorResult = await this.options.interceptor.execute(httpRequest);
|
253
254
|
if (interceptorResult.error && !j.allowInterceptorError) {
|
254
|
-
this.sendResponse(res, interceptorResult, tme, ep, log, httpRequest);
|
255
|
+
this.sendResponse(req.get("Referer") ?? "", res, interceptorResult, tme, ep, log, httpRequest);
|
255
256
|
return;
|
256
257
|
}
|
257
258
|
httpRequest.interceptorResult = interceptorResult;
|
@@ -261,7 +262,7 @@ class APIService extends BaseService_1.BaseService {
|
|
261
262
|
httpRequest.precheck = { data: this.options.monitor };
|
262
263
|
const precheck = await i.precheck(httpRequest);
|
263
264
|
if (precheck && precheck.error) {
|
264
|
-
this.sendResponse(res, precheck, tme, ep, log, httpRequest);
|
265
|
+
this.sendResponse(req.get("Referer") ?? "", res, precheck, tme, ep, log, httpRequest);
|
265
266
|
return;
|
266
267
|
}
|
267
268
|
httpRequest.precheck = precheck;
|
@@ -273,7 +274,7 @@ class APIService extends BaseService_1.BaseService {
|
|
273
274
|
this.options.onError(e);
|
274
275
|
if (this.monitor)
|
275
276
|
this.monitor.registrateFatalError(ep);
|
276
|
-
this.sendResponse(res, {
|
277
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
277
278
|
httpStatus: 500,
|
278
279
|
error: {
|
279
280
|
code: 10002,
|
@@ -283,7 +284,7 @@ class APIService extends BaseService_1.BaseService {
|
|
283
284
|
}, tme, ep, log, httpRequest);
|
284
285
|
return;
|
285
286
|
}
|
286
|
-
this.sendResponse(res, result, tme, ep, log, httpRequest);
|
287
|
+
this.sendResponse(req.get("Referer") ?? "", res, result, tme, ep, log, httpRequest);
|
287
288
|
};
|
288
289
|
execute();
|
289
290
|
});
|
@@ -311,7 +312,7 @@ class APIService extends BaseService_1.BaseService {
|
|
311
312
|
res.status(200).send(this.monitorIndexFile);
|
312
313
|
}
|
313
314
|
catch (e) {
|
314
|
-
this.sendResponse(res, {
|
315
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
315
316
|
error: {
|
316
317
|
code: 10002,
|
317
318
|
message: "Internal server error",
|
@@ -325,7 +326,7 @@ class APIService extends BaseService_1.BaseService {
|
|
325
326
|
}
|
326
327
|
}
|
327
328
|
}
|
328
|
-
this.sendResponse(res, {
|
329
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
329
330
|
error: DefaultErrors_1.default.UNKNOWN_REQUEST,
|
330
331
|
data: null,
|
331
332
|
httpStatus: 404
|
@@ -335,7 +336,7 @@ class APIService extends BaseService_1.BaseService {
|
|
335
336
|
(0, LogService_1.logCrit)('${APIService.js}', 'API Service started at: ' + this.options.port + ", with base endpoint:" + this.options.baseEndPoint + ", ver.: " + this.version);
|
336
337
|
});
|
337
338
|
}
|
338
|
-
async sendResponse(res, data, requestTime, endpoint, log, req) {
|
339
|
+
async sendResponse(ref, res, data, requestTime, endpoint, log, req) {
|
339
340
|
if (this.options.postproducer) {
|
340
341
|
try {
|
341
342
|
data = await this.options.postproducer(req, res, data, requestTime, endpoint, log);
|
@@ -351,8 +352,10 @@ class APIService extends BaseService_1.BaseService {
|
|
351
352
|
data.endpoint = endpoint ?? "no_endpoint";
|
352
353
|
if (this.options.appVersion)
|
353
354
|
data.version = this.options.appVersion;
|
354
|
-
if (log)
|
355
|
+
if (log) {
|
355
356
|
log.time = data.responseTime;
|
357
|
+
log.referer = ref;
|
358
|
+
}
|
356
359
|
if (this.monitor)
|
357
360
|
this.monitor.registrateResponse(data.endpoint, data.responseTime);
|
358
361
|
if (res.destroyed || res.closed) {
|
@@ -365,6 +368,24 @@ class APIService extends BaseService_1.BaseService {
|
|
365
368
|
}
|
366
369
|
else {
|
367
370
|
try {
|
371
|
+
if (data.file) {
|
372
|
+
res.sendFile(data.file, err => {
|
373
|
+
if (err) {
|
374
|
+
if (log)
|
375
|
+
log.error = "Can't send file: " + data.file;
|
376
|
+
if (this.options.onError)
|
377
|
+
this.options.onError("Can't send file: " + data.file, err);
|
378
|
+
if (this.monitor && data.endpoint)
|
379
|
+
this.monitor.registrateAPIError(data.endpoint);
|
380
|
+
this.sendResponse(ref, res, {
|
381
|
+
error: DefaultErrors_1.default.CANT_SEND_FILE,
|
382
|
+
data: null,
|
383
|
+
httpStatus: 500
|
384
|
+
}, requestTime, data.endpoint);
|
385
|
+
}
|
386
|
+
});
|
387
|
+
return;
|
388
|
+
}
|
368
389
|
if (data.redirect) {
|
369
390
|
res.redirect(data.redirect);
|
370
391
|
if (log)
|
@@ -18,6 +18,7 @@ export interface MysqlServiceOptions {
|
|
18
18
|
}
|
19
19
|
export interface MysqlResult {
|
20
20
|
error?: MysqlError | null;
|
21
|
+
rollbackError?: MysqlError | null;
|
21
22
|
isDuplicateError?: boolean;
|
22
23
|
fields?: FieldInfo[] | null;
|
23
24
|
data: any;
|
@@ -25,6 +26,7 @@ export interface MysqlResult {
|
|
25
26
|
export interface MySqlQuery {
|
26
27
|
query: string;
|
27
28
|
fields: MysqlQueryField[] | MysqlQueryFieldObject;
|
29
|
+
rollbackQuery?: string | null;
|
28
30
|
}
|
29
31
|
export interface MysqlQueryField {
|
30
32
|
name: string;
|
@@ -60,8 +62,13 @@ export declare class MysqlService extends BaseService {
|
|
60
62
|
static objectToFields(obj: MysqlQueryFieldObject | MysqlQueryField[]): MysqlQueryField[];
|
61
63
|
static prepareQuery(query: string, fields: MysqlQueryField[] | MysqlQueryFieldObject): string;
|
62
64
|
static prepareQueryFieldValue(value: string | number | boolean | null | undefined, system?: boolean): string | number | boolean | null | undefined;
|
63
|
-
execute(query: string): Promise<MysqlResult>;
|
64
|
-
sendQuery(conn: PoolConnection, query: string, resolve: (data: MysqlResult) => void): void
|
65
|
+
execute(query: string, rollbackQuery: string | null): Promise<MysqlResult>;
|
66
|
+
sendQuery(conn: PoolConnection, query: string, resolve: (data: MysqlResult) => void, rollback: string | null): Promise<void>;
|
67
|
+
queryAsync(conn: PoolConnection, query: string): Promise<{
|
68
|
+
err: MysqlError | null;
|
69
|
+
results?: any;
|
70
|
+
fields?: FieldInfo[];
|
71
|
+
}>;
|
65
72
|
createPool(): Promise<boolean>;
|
66
73
|
}
|
67
74
|
export default MysqlService;
|
@@ -66,7 +66,7 @@ class MysqlService extends BaseService_1.BaseService {
|
|
66
66
|
const promises = [];
|
67
67
|
for (let i of data) {
|
68
68
|
const query = MysqlService.prepareQuery(i.query, i.fields);
|
69
|
-
promises.push(this.execute(query));
|
69
|
+
promises.push(this.execute(query, i.rollbackQuery ?? null));
|
70
70
|
}
|
71
71
|
return await Promise.all(promises);
|
72
72
|
};
|
@@ -206,7 +206,7 @@ class MysqlService extends BaseService_1.BaseService {
|
|
206
206
|
return "NULL";
|
207
207
|
return value;
|
208
208
|
}
|
209
|
-
async execute(query) {
|
209
|
+
async execute(query, rollbackQuery) {
|
210
210
|
return new Promise((resolve, reject) => {
|
211
211
|
if (!this.pool) {
|
212
212
|
(0, LogService_1.logError)("${MysqlService.js}", "No pool");
|
@@ -252,40 +252,23 @@ class MysqlService extends BaseService_1.BaseService {
|
|
252
252
|
fields: null
|
253
253
|
});
|
254
254
|
}
|
255
|
-
|
256
|
-
this.sendQuery(conn, query, resolve);
|
257
|
-
}
|
258
|
-
catch (e) {
|
259
|
-
try {
|
260
|
-
conn.removeAllListeners();
|
261
|
-
conn.release();
|
262
|
-
}
|
263
|
-
catch (e) { }
|
264
|
-
(0, LogService_1.logError)("${MysqlService.js}", "QUERY_ERR: " + e);
|
265
|
-
resolve({
|
266
|
-
error: {
|
267
|
-
code: "QUERY_ERR",
|
268
|
-
errno: 100002,
|
269
|
-
fatal: true,
|
270
|
-
sql: query,
|
271
|
-
name: "QUERY_ERR",
|
272
|
-
message: "Error: " + e
|
273
|
-
},
|
274
|
-
data: null,
|
275
|
-
fields: null
|
276
|
-
});
|
277
|
-
}
|
255
|
+
this.sendQuery(conn, query, resolve, rollbackQuery);
|
278
256
|
});
|
279
257
|
});
|
280
258
|
}
|
281
|
-
sendQuery(conn, query, resolve) {
|
259
|
+
async sendQuery(conn, query, resolve, rollback) {
|
282
260
|
let errCatched = false;
|
283
|
-
conn.on("error", err => {
|
261
|
+
conn.on("error", async (err) => {
|
284
262
|
errCatched = true;
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
conn.
|
263
|
+
let rollbackError = null;
|
264
|
+
if (rollback)
|
265
|
+
rollbackError = (await this.queryAsync(conn, rollback)).err;
|
266
|
+
(0, LogService_1.logError)("${MysqlService.js}->conn.on('error')", err);
|
267
|
+
try {
|
268
|
+
conn.release();
|
269
|
+
conn.removeAllListeners();
|
270
|
+
}
|
271
|
+
catch (e) { }
|
289
272
|
resolve({
|
290
273
|
error: {
|
291
274
|
code: "CONN_ERR",
|
@@ -296,32 +279,65 @@ class MysqlService extends BaseService_1.BaseService {
|
|
296
279
|
message: "Error: " + err
|
297
280
|
},
|
298
281
|
data: null,
|
299
|
-
fields: null
|
282
|
+
fields: null,
|
283
|
+
rollbackError: rollbackError
|
300
284
|
});
|
301
285
|
});
|
302
286
|
(0, LogService_1.logInfo)("${MysqlService.js}", query);
|
303
|
-
|
287
|
+
const queryResult = await this.queryAsync(conn, query);
|
288
|
+
if (queryResult.err) {
|
289
|
+
let rollbackError = null;
|
290
|
+
if (rollback)
|
291
|
+
rollbackError = (await this.queryAsync(conn, rollback)).err;
|
292
|
+
try {
|
293
|
+
conn.release();
|
294
|
+
conn.removeAllListeners();
|
295
|
+
}
|
296
|
+
catch (e) { }
|
297
|
+
const dup = `${queryResult.err}`.toLowerCase().indexOf("er_dup_entry") !== -1;
|
298
|
+
(0, LogService_1.logError)("${MysqlService.js}->query error", queryResult.err);
|
299
|
+
resolve({
|
300
|
+
error: queryResult.err,
|
301
|
+
data: null,
|
302
|
+
fields: null,
|
303
|
+
rollbackError: rollbackError,
|
304
|
+
isDuplicateError: dup
|
305
|
+
});
|
306
|
+
}
|
307
|
+
try {
|
304
308
|
conn.release();
|
305
309
|
conn.removeAllListeners();
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
310
|
+
}
|
311
|
+
catch (e) { }
|
312
|
+
resolve({
|
313
|
+
error: queryResult.err,
|
314
|
+
data: queryResult.results,
|
315
|
+
fields: queryResult.fields
|
316
|
+
});
|
317
|
+
}
|
318
|
+
async queryAsync(conn, query) {
|
319
|
+
return new Promise((resolve, reject) => {
|
320
|
+
try {
|
321
|
+
conn.query(query, (err, results, fields) => {
|
322
|
+
resolve({
|
323
|
+
err: err,
|
324
|
+
results: results,
|
325
|
+
fields: fields
|
326
|
+
});
|
327
|
+
});
|
328
|
+
}
|
329
|
+
catch (e) {
|
311
330
|
resolve({
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
331
|
+
err: {
|
332
|
+
code: "QUERY_ERR",
|
333
|
+
errno: 100002,
|
334
|
+
fatal: true,
|
335
|
+
sql: query,
|
336
|
+
name: "QUERY_ERR",
|
337
|
+
message: "Error: " + e
|
338
|
+
}
|
316
339
|
});
|
317
|
-
return;
|
318
340
|
}
|
319
|
-
resolve({
|
320
|
-
error: err,
|
321
|
-
data: results,
|
322
|
-
fields: fields
|
323
|
-
});
|
324
|
-
return;
|
325
341
|
});
|
326
342
|
}
|
327
343
|
async createPool() {
|
@@ -4,6 +4,8 @@ declare class DefaultErrors {
|
|
4
4
|
static UNKNOWN_REQUEST: IError;
|
5
5
|
static JSON_MALFORMED: IError;
|
6
6
|
static FILE_TOO_LARGE: IError;
|
7
|
+
static CANT_SEND_FILE: IError;
|
8
|
+
static FILE_NOT_EXISTS: IError;
|
7
9
|
}
|
8
10
|
export declare class ErrorUtils {
|
9
11
|
static isError(obj: any): boolean;
|
@@ -7,6 +7,8 @@ class DefaultErrors {
|
|
7
7
|
static UNKNOWN_REQUEST = { code: 2, message: "Unknown request" };
|
8
8
|
static JSON_MALFORMED = { code: 3, message: "JSON malformed" };
|
9
9
|
static FILE_TOO_LARGE = { code: 4, message: "File is too large" };
|
10
|
+
static CANT_SEND_FILE = { code: 5, message: "Can't send file" };
|
11
|
+
static FILE_NOT_EXISTS = { code: 5, message: "File not exists" };
|
10
12
|
}
|
11
13
|
class ErrorUtils {
|
12
14
|
static isError(obj) {
|
@@ -12,6 +12,7 @@ export interface TransferPacketVO<T = any> {
|
|
12
12
|
headers?: {
|
13
13
|
[key: string]: string;
|
14
14
|
};
|
15
|
+
file?: string;
|
15
16
|
}
|
16
17
|
export interface HTTPRequestVO<T = any> {
|
17
18
|
raw: any;
|
@@ -28,6 +29,7 @@ export interface HTTPRequestVO<T = any> {
|
|
28
29
|
preproducerResult?: any;
|
29
30
|
precheck?: TransferPacketVO<any> | null;
|
30
31
|
files: FileArray | null | undefined;
|
32
|
+
referer?: string;
|
31
33
|
unlocked?: boolean;
|
32
34
|
}
|
33
35
|
export interface IError {
|