badmfck-api-server 4.0.78 → 4.0.79
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/dist/apiServer/APIService.js +1 -1
- package/dist/apiServer/external/MicroserviceClient.js +44 -24
- package/dist/apiServer/external/MicroserviceHost.d.ts +8 -0
- package/dist/apiServer/external/MicroserviceHost.js +61 -2
- package/dist/apiServer/structures/DefaultErrors.d.ts +2 -0
- package/dist/apiServer/structures/DefaultErrors.js +2 -0
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ const BaseService_1 = require("../BaseService");
|
|
|
9
9
|
const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
|
|
10
10
|
const Http_1 = require("../http/Http");
|
|
11
11
|
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
const TimeframeService_1 = require("../TimeframeService");
|
|
12
13
|
exports.REQ_MICROSERVICE_CALL = new badmfck_signal_1.Req(undefined, "REQ_MICROSERVICE_CALL");
|
|
13
14
|
class MicroserviceClient extends BaseService_1.BaseService {
|
|
14
15
|
static #clients = new Map();
|
|
@@ -37,30 +38,49 @@ class MicroserviceClient extends BaseService_1.BaseService {
|
|
|
37
38
|
const url = this.options.host + "/__ms_host_control/receiver";
|
|
38
39
|
const ts = Date.now().toString();
|
|
39
40
|
const nonce = crypto_1.default.randomBytes(12).toString("hex");
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
41
|
+
const maxAttempts = 5;
|
|
42
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
43
|
+
const rawSecret = Buffer.from(this.options.securityKey, "base64");
|
|
44
|
+
const key = crypto_1.default.createHash("sha256").update(rawSecret).digest();
|
|
45
|
+
const hash = crypto_1.default.createHash("sha256").update(nonce + ts + this.options.securityKey).digest();
|
|
46
|
+
const iv = hash.subarray(0, 12);
|
|
47
|
+
const aad = Buffer.from(`${ts}.${nonce}.${this.options.id}`, "utf8");
|
|
48
|
+
const data = Buffer.from(JSON.stringify(req), "utf8");
|
|
49
|
+
const cipher = crypto_1.default.createCipheriv("aes-256-gcm", key, iv);
|
|
50
|
+
cipher.setAAD(aad);
|
|
51
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
52
|
+
const tag = cipher.getAuthTag();
|
|
53
|
+
const headers = {
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
"x-microservice-id": this.options.id,
|
|
56
|
+
"x-microservice-ts": ts,
|
|
57
|
+
"x-microservice-nonce": nonce
|
|
58
|
+
};
|
|
59
|
+
const resp = await Http_1.Http.post(url, {
|
|
60
|
+
tag: tag.toString("base64"),
|
|
61
|
+
enc: encrypted.toString("base64")
|
|
62
|
+
}, { headers });
|
|
63
|
+
if (!resp.ok && resp.details?.network) {
|
|
64
|
+
if (attempt < maxAttempts) {
|
|
65
|
+
TimeframeService_1.TimeframeService.wait(500);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
return { ...DefaultErrors_1.default.EXTERNAL_SERVICE_ERROR, details: "Network connection lost after multiple retries" };
|
|
69
|
+
}
|
|
70
|
+
if (!resp.ok)
|
|
71
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: resp.details };
|
|
72
|
+
const body = resp.data;
|
|
73
|
+
const isAccepted = body?.error?.code === DefaultErrors_1.default.ACCEPTED.code || body?.code === DefaultErrors_1.default.ACCEPTED.code;
|
|
74
|
+
if (isAccepted) {
|
|
75
|
+
if (attempt < maxAttempts) {
|
|
76
|
+
TimeframeService_1.TimeframeService.wait(500);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
return { ...DefaultErrors_1.default.EXTERNAL_SERVICE_ERROR, details: "Microservice processing timeout" };
|
|
80
|
+
}
|
|
81
|
+
return (body && typeof body === "object" && "error" in body) ? body.error : (body.data ?? null);
|
|
82
|
+
}
|
|
83
|
+
return { ...DefaultErrors_1.default.EXTERNAL_SERVICE_ERROR, details: "Unknown polling error" };
|
|
64
84
|
}
|
|
65
85
|
}
|
|
66
86
|
exports.MicroserviceClient = MicroserviceClient;
|
|
@@ -7,11 +7,19 @@ export interface IMicroserviceHostOptions {
|
|
|
7
7
|
password: string;
|
|
8
8
|
requests: Req<any, any>[];
|
|
9
9
|
}
|
|
10
|
+
type TJobStatus = "processing" | "completed";
|
|
11
|
+
type TJob = {
|
|
12
|
+
status: TJobStatus;
|
|
13
|
+
result?: any | IError;
|
|
14
|
+
expires: number;
|
|
15
|
+
};
|
|
10
16
|
export declare class MicroserviceHost extends BaseService {
|
|
11
17
|
#private;
|
|
12
18
|
options: IMicroserviceHostOptions;
|
|
19
|
+
jobs: Map<string, TJob>;
|
|
13
20
|
constructor(opt: IMicroserviceHostOptions);
|
|
14
21
|
init(): Promise<void>;
|
|
15
22
|
static getMicroservice(id: string): MicroserviceHost | null;
|
|
16
23
|
handleIncomingRequest(req: HTTPRequestVO): Promise<any | IError>;
|
|
17
24
|
}
|
|
25
|
+
export {};
|
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
29
|
exports.MicroserviceHost = void 0;
|
|
7
30
|
const BaseService_1 = require("../BaseService");
|
|
8
|
-
const DefaultErrors_1 =
|
|
31
|
+
const DefaultErrors_1 = __importStar(require("../structures/DefaultErrors"));
|
|
9
32
|
const crypto_1 = __importDefault(require("crypto"));
|
|
10
33
|
class MicroserviceHost extends BaseService_1.BaseService {
|
|
11
34
|
static #calls = new Set();
|
|
12
35
|
static #instances = new Map();
|
|
13
36
|
options;
|
|
37
|
+
jobs = new Map();
|
|
14
38
|
constructor(opt) {
|
|
15
39
|
super("Microservice-host-" + opt.id);
|
|
16
40
|
this.options = opt;
|
|
@@ -18,6 +42,13 @@ class MicroserviceHost extends BaseService_1.BaseService {
|
|
|
18
42
|
}
|
|
19
43
|
async init() {
|
|
20
44
|
super.init();
|
|
45
|
+
setInterval(() => {
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
for (const [key, job] of this.jobs) {
|
|
48
|
+
if (job.expires < now)
|
|
49
|
+
this.jobs.delete(key);
|
|
50
|
+
}
|
|
51
|
+
}, 1000 * 60 * 5);
|
|
21
52
|
}
|
|
22
53
|
static getMicroservice(id) {
|
|
23
54
|
return MicroserviceHost.#instances.get(id) || null;
|
|
@@ -27,6 +58,18 @@ class MicroserviceHost extends BaseService_1.BaseService {
|
|
|
27
58
|
const ts = req.headers["x-microservice-ts"];
|
|
28
59
|
if (!nonce || !ts)
|
|
29
60
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "missing headers" };
|
|
61
|
+
const jobKey = `${nonce}|${ts}`;
|
|
62
|
+
const job = this.jobs.get(jobKey);
|
|
63
|
+
if (job) {
|
|
64
|
+
if (job.expires < Date.now()) {
|
|
65
|
+
this.jobs.delete(jobKey);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (job.status === "processing")
|
|
69
|
+
return { ...DefaultErrors_1.default.ACCEPTED, details: "request is being processed" };
|
|
70
|
+
return job.result;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
30
73
|
const requestTime = parseInt(ts);
|
|
31
74
|
const now = Date.now();
|
|
32
75
|
if (isNaN(requestTime) || Math.abs(now - requestTime) > 1000 * 60 * 2) {
|
|
@@ -61,7 +104,23 @@ class MicroserviceHost extends BaseService_1.BaseService {
|
|
|
61
104
|
const reqCall = this.options.requests.find(r => r.name === request?.requestName);
|
|
62
105
|
if (!reqCall)
|
|
63
106
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "method not found" };
|
|
64
|
-
|
|
107
|
+
const job = {
|
|
108
|
+
status: "processing",
|
|
109
|
+
expires: Date.now() + 1000 * 60 * 5
|
|
110
|
+
};
|
|
111
|
+
this.jobs.set(jobKey, job);
|
|
112
|
+
try {
|
|
113
|
+
const result = await reqCall.request(request.requestData);
|
|
114
|
+
job.status = "completed";
|
|
115
|
+
job.result = result;
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
const err = DefaultErrors_1.ErrorUtils.isError(e) ? e : { ...DefaultErrors_1.default.INTERNAL_ERROR, details: "unknown error" };
|
|
120
|
+
job.status = "completed";
|
|
121
|
+
job.result = err;
|
|
122
|
+
return job.result;
|
|
123
|
+
}
|
|
65
124
|
}
|
|
66
125
|
catch (e) {
|
|
67
126
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "decryption error" };
|
|
@@ -25,6 +25,8 @@ declare class DefaultErrors {
|
|
|
25
25
|
static WRONG_DATA_TYPE: IError;
|
|
26
26
|
static UPROCESSIABLE_CONTENT: IError;
|
|
27
27
|
static WRONG_PARAMS: IError;
|
|
28
|
+
static ACCEPTED: IError;
|
|
29
|
+
static INTERNAL_ERROR: IError;
|
|
28
30
|
}
|
|
29
31
|
export declare class ErrorUtils {
|
|
30
32
|
static isError(obj: any): obj is IError;
|
|
@@ -28,6 +28,8 @@ class DefaultErrors {
|
|
|
28
28
|
static WRONG_DATA_TYPE = { code: 23, message: "Wrong data type", httpStatus: 422 };
|
|
29
29
|
static UPROCESSIABLE_CONTENT = { code: 24, message: "Unprocessable content", httpStatus: 422 };
|
|
30
30
|
static WRONG_PARAMS = { code: 25, message: "Wrong params", httpStatus: 400 };
|
|
31
|
+
static ACCEPTED = { code: 26, message: "Accepted", httpStatus: 202 };
|
|
32
|
+
static INTERNAL_ERROR = { code: 27, message: "Internal error", httpStatus: 500 };
|
|
31
33
|
}
|
|
32
34
|
class ErrorUtils {
|
|
33
35
|
static isError(obj) {
|