godprotocol 2.3.55 → 2.3.56
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/package.json +1 -1
- package/server/Routable/Header.js +4 -4
- package/server/Routable/Route_table.js +32 -24
- package/server/version_control.js +139 -11
package/package.json
CHANGED
|
@@ -247,15 +247,15 @@ class Headers extends Services {
|
|
|
247
247
|
return requirements.every((r) => checks[r]?.());
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
-
handle_security = async (name, request) => {
|
|
250
|
+
handle_security = async (name, request, version = this.active_version) => {
|
|
251
251
|
let config;
|
|
252
|
-
if (
|
|
253
|
-
let version = this.versions[
|
|
252
|
+
if (version === "*") {
|
|
253
|
+
let version = this.versions[version];
|
|
254
254
|
|
|
255
255
|
config = version.config;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
let route = await this.get_route(name);
|
|
258
|
+
let route = await this.get_route(name, version);
|
|
259
259
|
|
|
260
260
|
if (!route) {
|
|
261
261
|
route = await this.get_route("*");
|
|
@@ -75,30 +75,38 @@ class Route_table extends Headers {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
get_version = async (version = this.active_version) => {
|
|
78
|
-
let
|
|
78
|
+
let resolved_version = version;
|
|
79
|
+
|
|
80
|
+
let ver = this.versions[resolved_version];
|
|
79
81
|
|
|
80
82
|
if (!ver) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
const versions = Object.keys(this.versions);
|
|
84
|
+
|
|
85
|
+
const verr = versions.find((v) => v.startsWith(`${version}:`));
|
|
83
86
|
|
|
84
87
|
if (verr) {
|
|
85
|
-
|
|
88
|
+
const serv = await this.get_service(version);
|
|
89
|
+
|
|
86
90
|
if (serv) {
|
|
87
|
-
|
|
88
|
-
ver = this.versions[
|
|
91
|
+
resolved_version = `${version}:${serv.api_version}`;
|
|
92
|
+
ver = this.versions[resolved_version];
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
|
-
if (!ver) return;
|
|
93
|
-
|
|
94
|
-
this.active_version = version;
|
|
95
|
-
|
|
96
|
-
this.db_name = ver.config?.db_name === true ? version : ver.config?.db_name;
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
ver.config?.db_prefix === true ? version : ver.config?.db_prefix;
|
|
97
|
+
if (!ver) return;
|
|
100
98
|
|
|
101
|
-
return
|
|
99
|
+
return {
|
|
100
|
+
...ver,
|
|
101
|
+
version: resolved_version,
|
|
102
|
+
db_name:
|
|
103
|
+
ver.config?.db_name === true ? resolved_version : ver.config?.db_name,
|
|
104
|
+
|
|
105
|
+
db_prefix:
|
|
106
|
+
ver.config?.db_prefix === true
|
|
107
|
+
? resolved_version
|
|
108
|
+
: ver.config?.db_prefix,
|
|
109
|
+
};
|
|
102
110
|
};
|
|
103
111
|
|
|
104
112
|
init_version = async (version, config) => {
|
|
@@ -209,8 +217,8 @@ class Route_table extends Headers {
|
|
|
209
217
|
// 🔎 ROUTE RESOLUTION
|
|
210
218
|
// Precedence: exact -> named param -> regex -> wildcard
|
|
211
219
|
// =========================
|
|
212
|
-
get_route = async (name) => {
|
|
213
|
-
const version = this.versions[
|
|
220
|
+
get_route = async (name, version_name = this.active_version) => {
|
|
221
|
+
const version = this.versions[version_name];
|
|
214
222
|
|
|
215
223
|
if (!version) return null;
|
|
216
224
|
|
|
@@ -587,30 +595,29 @@ class Route_table extends Headers {
|
|
|
587
595
|
return { ok: true };
|
|
588
596
|
};
|
|
589
597
|
|
|
590
|
-
get_route_config = async (name) => {
|
|
591
|
-
|
|
592
|
-
|
|
598
|
+
get_route_config = async (name, version_name = this.active_version) => {
|
|
599
|
+
const route = await this.get_route(name, version_name);
|
|
593
600
|
return route?.config;
|
|
594
601
|
};
|
|
595
602
|
|
|
596
603
|
// =========================
|
|
597
604
|
// 🚀 EXECUTION PIPELINE
|
|
598
605
|
// =========================
|
|
599
|
-
execute = async (name, payload) => {
|
|
600
|
-
if (
|
|
601
|
-
let version = this.versions[
|
|
606
|
+
execute = async (name, payload, version_name = this.active_version) => {
|
|
607
|
+
if (version_name === "*") {
|
|
608
|
+
let version = this.versions[version_name];
|
|
602
609
|
|
|
603
610
|
return await version.handler(payload);
|
|
604
611
|
}
|
|
605
612
|
|
|
606
|
-
let route = await this.get_route(name);
|
|
613
|
+
let route = await this.get_route(name, version_name);
|
|
607
614
|
|
|
608
615
|
if (!route) {
|
|
609
616
|
return {
|
|
610
617
|
ok: false,
|
|
611
618
|
status: 404,
|
|
612
619
|
message: "Route not found",
|
|
613
|
-
data: { path: `/${name}`, name },
|
|
620
|
+
data: { path: `/${name}`, name, version: version_name },
|
|
614
621
|
};
|
|
615
622
|
}
|
|
616
623
|
|
|
@@ -621,6 +628,7 @@ class Route_table extends Headers {
|
|
|
621
628
|
|
|
622
629
|
if (payload.req) {
|
|
623
630
|
payload.req.params = params;
|
|
631
|
+
payload.req.api_version = version_name;
|
|
624
632
|
}
|
|
625
633
|
|
|
626
634
|
if (config.schema) {
|
|
@@ -43,24 +43,144 @@ const applyCors = (req, res) => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const respond = (result, res) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
/*
|
|
47
|
+
* ------------------------------------------------------------------------
|
|
48
|
+
* REDIRECT
|
|
49
|
+
* ------------------------------------------------------------------------
|
|
50
|
+
*/
|
|
49
51
|
|
|
50
52
|
if (result?.redirect) {
|
|
51
53
|
const status = result?.status || 302;
|
|
52
54
|
|
|
53
55
|
res.statusCode = status;
|
|
56
|
+
|
|
54
57
|
res.setHeader("Location", result.redirect);
|
|
55
58
|
|
|
56
59
|
res.end();
|
|
57
60
|
|
|
61
|
+
res.gp?.resource?.compute_response?.(res);
|
|
62
|
+
|
|
58
63
|
return result;
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
/*
|
|
67
|
+
* ------------------------------------------------------------------------
|
|
68
|
+
* STREAM
|
|
69
|
+
* ------------------------------------------------------------------------
|
|
70
|
+
*
|
|
71
|
+
* A stream response bypasses JSON serialization completely.
|
|
72
|
+
*
|
|
73
|
+
* Expected:
|
|
74
|
+
*
|
|
75
|
+
* {
|
|
76
|
+
* ok: true,
|
|
77
|
+
* type: "stream",
|
|
78
|
+
* data: {
|
|
79
|
+
* stream,
|
|
80
|
+
* content_type,
|
|
81
|
+
* content_length,
|
|
82
|
+
* etag
|
|
83
|
+
* }
|
|
84
|
+
* }
|
|
85
|
+
*
|
|
86
|
+
* ------------------------------------------------------------------------
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
if (result?.status === 206 && result?.data?.stream) {
|
|
90
|
+
const { stream, content_type, content_length, etag, filename } =
|
|
91
|
+
result.data;
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* Status
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
res.statusCode = result?.status || 206;
|
|
98
|
+
|
|
99
|
+
/*
|
|
100
|
+
* Content type
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
res.setHeader("Content-Type", content_type || "application/octet-stream");
|
|
104
|
+
|
|
105
|
+
/*
|
|
106
|
+
* Content length
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
if (content_length !== undefined && content_length !== null) {
|
|
110
|
+
res.setHeader("Content-Length", content_length);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* ETag
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
if (etag) {
|
|
118
|
+
res.setHeader("ETag", etag);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
* Optional filename
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
if (filename) {
|
|
126
|
+
res.setHeader("Content-Disposition", `inline; filename="${filename}"`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* Stream errors
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
stream.on("error", (error) => {
|
|
134
|
+
console.error("Response stream error:", error);
|
|
135
|
+
|
|
136
|
+
if (!res.headersSent) {
|
|
137
|
+
res.statusCode = 500;
|
|
138
|
+
|
|
139
|
+
res.setHeader("Content-Type", "application/json");
|
|
140
|
+
|
|
141
|
+
return res.end(
|
|
142
|
+
JSON.stringify({
|
|
143
|
+
ok: false,
|
|
144
|
+
message: "Failed to stream file",
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* Headers have already been sent.
|
|
151
|
+
*
|
|
152
|
+
* At this point the response cannot safely
|
|
153
|
+
* be converted into a JSON error response.
|
|
154
|
+
*
|
|
155
|
+
* Destroy the response.
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
res.destroy(error);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
/*
|
|
162
|
+
* Complete response metrics only after
|
|
163
|
+
* the stream has finished.
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
res.on("finish", () => {
|
|
167
|
+
res.gp?.resource?.compute_response?.(res);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
/*
|
|
171
|
+
* Pipe file into HTTP response.
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
stream.pipe(res);
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* ------------------------------------------------------------------------
|
|
181
|
+
* NORMAL JSON RESPONSE
|
|
182
|
+
* ------------------------------------------------------------------------
|
|
183
|
+
*/
|
|
64
184
|
|
|
65
185
|
const response = {
|
|
66
186
|
ok: result?.ok ?? false,
|
|
@@ -96,7 +216,7 @@ const respond = (result, res) => {
|
|
|
96
216
|
|
|
97
217
|
res.end(JSON.stringify(response));
|
|
98
218
|
|
|
99
|
-
res.gp?.resource?.compute_response(res);
|
|
219
|
+
res.gp?.resource?.compute_response?.(res);
|
|
100
220
|
|
|
101
221
|
return response;
|
|
102
222
|
};
|
|
@@ -151,9 +271,10 @@ const version_middleware = async (req, res, routers) => {
|
|
|
151
271
|
|
|
152
272
|
if (!versionRouter) {
|
|
153
273
|
version = "*";
|
|
274
|
+
|
|
154
275
|
versionRouter = await routers.get_version(version);
|
|
155
276
|
|
|
156
|
-
if (!versionRouter)
|
|
277
|
+
if (!versionRouter) {
|
|
157
278
|
return respond(
|
|
158
279
|
{
|
|
159
280
|
ok: false,
|
|
@@ -162,8 +283,11 @@ const version_middleware = async (req, res, routers) => {
|
|
|
162
283
|
},
|
|
163
284
|
res,
|
|
164
285
|
);
|
|
286
|
+
}
|
|
165
287
|
}
|
|
166
288
|
|
|
289
|
+
version = versionRouter.version;
|
|
290
|
+
|
|
167
291
|
let body = {};
|
|
168
292
|
|
|
169
293
|
if (req.method === "GET") {
|
|
@@ -206,14 +330,18 @@ const version_middleware = async (req, res, routers) => {
|
|
|
206
330
|
|
|
207
331
|
// SECURITY
|
|
208
332
|
error_stage = "Header";
|
|
209
|
-
const securityResult = await router.handle_security(name, req);
|
|
333
|
+
const securityResult = await router.handle_security(name, req, version);
|
|
210
334
|
|
|
211
335
|
if (securityResult !== true) {
|
|
212
336
|
return respond(securityResult, res);
|
|
213
337
|
}
|
|
214
338
|
|
|
215
339
|
// DB
|
|
216
|
-
const db = await router.resolve_db(req
|
|
340
|
+
const db = await router.resolve_db(req, {
|
|
341
|
+
version,
|
|
342
|
+
db_name: versionRouter.db_name,
|
|
343
|
+
db_prefix: versionRouter.db_prefix,
|
|
344
|
+
});
|
|
217
345
|
|
|
218
346
|
// WEBHOOK PRIOR
|
|
219
347
|
const callback = await router.handle_before(
|
|
@@ -254,7 +382,7 @@ const version_middleware = async (req, res, routers) => {
|
|
|
254
382
|
params: {},
|
|
255
383
|
memory: router.gp.memory,
|
|
256
384
|
};
|
|
257
|
-
const result = await router.execute(name, payload);
|
|
385
|
+
const result = await router.execute(name, payload, version);
|
|
258
386
|
|
|
259
387
|
// WEBHOOK AFTER
|
|
260
388
|
if (!isWebhook && version !== "*") {
|