godprotocol 2.3.53 → 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 +159 -290
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) {
|
|
@@ -1,46 +1,30 @@
|
|
|
1
1
|
import parseMultipart from "./parse_multipart_data.js";
|
|
2
2
|
import serveStaticFile from "./serve_static_file.js";
|
|
3
|
-
import { debug } from "./utils.js";
|
|
4
3
|
|
|
5
4
|
const getBody = (req) => {
|
|
6
|
-
console.log("[getBody] Starting body parser");
|
|
7
|
-
|
|
8
5
|
return new Promise((resolve, reject) => {
|
|
9
6
|
let data = "";
|
|
10
7
|
|
|
11
8
|
req.on("data", (chunk) => {
|
|
12
|
-
console.log("[getBody] Received chunk:", chunk.length);
|
|
13
9
|
data += chunk;
|
|
14
10
|
});
|
|
15
11
|
|
|
16
12
|
req.on("end", () => {
|
|
17
|
-
console.log("[getBody] Request body received");
|
|
18
|
-
console.log("[getBody] Raw body length:", data.length);
|
|
19
|
-
|
|
20
13
|
try {
|
|
21
14
|
const parsed = data ? JSON.parse(data) : {};
|
|
22
|
-
|
|
23
|
-
console.log("[getBody] Parsed body:", parsed);
|
|
24
|
-
|
|
25
15
|
resolve(parsed);
|
|
26
16
|
} catch (err) {
|
|
27
|
-
console.error("[getBody] JSON parse error:", err);
|
|
28
|
-
|
|
29
17
|
reject(new Error("Invalid JSON body"));
|
|
30
18
|
}
|
|
31
19
|
});
|
|
32
20
|
|
|
33
21
|
req.on("error", (err) => {
|
|
34
|
-
console.error("[getBody] Request stream error:", err);
|
|
35
|
-
|
|
36
22
|
reject(err);
|
|
37
23
|
});
|
|
38
24
|
});
|
|
39
25
|
};
|
|
40
26
|
|
|
41
27
|
const applyCors = (req, res) => {
|
|
42
|
-
console.log("[CORS] Applying CORS headers");
|
|
43
|
-
|
|
44
28
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
45
29
|
|
|
46
30
|
res.setHeader(
|
|
@@ -50,30 +34,154 @@ const applyCors = (req, res) => {
|
|
|
50
34
|
|
|
51
35
|
res.setHeader(
|
|
52
36
|
"Access-Control-Allow-Headers",
|
|
53
|
-
"Content-Type, Authorization, x-api-version, x-api-key, x-platform
|
|
37
|
+
"Content-Type, Authorization, x-api-version, x-api-key, x-platform",
|
|
38
|
+
"x-secret",
|
|
54
39
|
);
|
|
55
40
|
|
|
56
|
-
|
|
41
|
+
// IMPORTANT: do NOT enable credentials with "*"
|
|
42
|
+
// res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
57
43
|
};
|
|
58
44
|
|
|
59
45
|
const respond = (result, res) => {
|
|
60
|
-
|
|
46
|
+
/*
|
|
47
|
+
* ------------------------------------------------------------------------
|
|
48
|
+
* REDIRECT
|
|
49
|
+
* ------------------------------------------------------------------------
|
|
50
|
+
*/
|
|
61
51
|
|
|
62
52
|
if (result?.redirect) {
|
|
63
53
|
const status = result?.status || 302;
|
|
64
54
|
|
|
65
|
-
console.log("[RESPOND] Redirect:", result.redirect, "Status:", status);
|
|
66
|
-
|
|
67
55
|
res.statusCode = status;
|
|
56
|
+
|
|
68
57
|
res.setHeader("Location", result.redirect);
|
|
69
58
|
|
|
70
59
|
res.end();
|
|
71
60
|
|
|
72
|
-
|
|
61
|
+
res.gp?.resource?.compute_response?.(res);
|
|
73
62
|
|
|
74
63
|
return result;
|
|
75
64
|
}
|
|
76
65
|
|
|
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
|
+
*/
|
|
184
|
+
|
|
77
185
|
const response = {
|
|
78
186
|
ok: result?.ok ?? false,
|
|
79
187
|
};
|
|
@@ -102,18 +210,13 @@ const respond = (result, res) => {
|
|
|
102
210
|
|
|
103
211
|
const status = result?.status || (result?.ok ? 200 : 403);
|
|
104
212
|
|
|
105
|
-
console.log("[RESPOND] HTTP status:", status);
|
|
106
|
-
console.log("[RESPOND] Response:", response);
|
|
107
|
-
|
|
108
213
|
res.statusCode = status;
|
|
109
214
|
|
|
110
215
|
res.setHeader("Content-Type", "application/json");
|
|
111
216
|
|
|
112
217
|
res.end(JSON.stringify(response));
|
|
113
218
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
res.gp?.resource?.compute_response(res);
|
|
219
|
+
res.gp?.resource?.compute_response?.(res);
|
|
117
220
|
|
|
118
221
|
return response;
|
|
119
222
|
};
|
|
@@ -121,156 +224,57 @@ const respond = (result, res) => {
|
|
|
121
224
|
const version_middleware = async (req, res, routers) => {
|
|
122
225
|
let error_stage = "Version Middleware";
|
|
123
226
|
|
|
124
|
-
console.log("==================================================");
|
|
125
|
-
console.log("[MIDDLEWARE] REQUEST START");
|
|
126
|
-
console.log("==================================================");
|
|
127
|
-
|
|
128
|
-
console.log("[MIDDLEWARE] Method:", req.method);
|
|
129
|
-
console.log("[MIDDLEWARE] URL:", req.url);
|
|
130
|
-
console.log("[MIDDLEWARE] Headers:", req.headers);
|
|
131
|
-
|
|
132
227
|
try {
|
|
133
|
-
// --------------------------------------------------
|
|
134
|
-
// CORS
|
|
135
|
-
// --------------------------------------------------
|
|
136
|
-
|
|
137
|
-
error_stage = "CORS";
|
|
138
|
-
|
|
139
|
-
console.log("[MIDDLEWARE] Applying CORS");
|
|
140
|
-
|
|
141
228
|
applyCors(req, res);
|
|
142
229
|
|
|
143
|
-
console.log("[MIDDLEWARE] CORS applied");
|
|
144
|
-
|
|
145
|
-
// --------------------------------------------------
|
|
146
|
-
// OPTIONS
|
|
147
|
-
// --------------------------------------------------
|
|
148
|
-
|
|
149
230
|
if (req.method === "OPTIONS") {
|
|
150
|
-
console.log("[MIDDLEWARE] OPTIONS request");
|
|
151
|
-
|
|
152
231
|
res.statusCode = 204;
|
|
153
|
-
|
|
154
|
-
console.log("[MIDDLEWARE] Returning 204");
|
|
155
|
-
|
|
156
232
|
return res.end();
|
|
157
233
|
}
|
|
158
234
|
|
|
159
|
-
// --------------------------------------------------
|
|
160
|
-
// URL
|
|
161
|
-
// --------------------------------------------------
|
|
162
|
-
|
|
163
|
-
error_stage = "URL Parsing";
|
|
164
|
-
|
|
165
|
-
console.log("[MIDDLEWARE] Parsing URL");
|
|
166
|
-
|
|
167
235
|
const parsed_url = new URL(req.url, `http://${req.headers.host}`);
|
|
168
|
-
|
|
169
236
|
const pathname = parsed_url.pathname;
|
|
170
237
|
|
|
171
|
-
|
|
172
|
-
|
|
238
|
+
// ⬇️ query params captured for every method now
|
|
173
239
|
const query = Object.fromEntries(parsed_url.searchParams.entries());
|
|
174
|
-
|
|
175
240
|
req.query = query;
|
|
176
241
|
|
|
177
|
-
console.log("[MIDDLEWARE] Query:", query);
|
|
178
|
-
|
|
179
|
-
// --------------------------------------------------
|
|
180
|
-
// REQUEST ID
|
|
181
|
-
// --------------------------------------------------
|
|
182
|
-
|
|
183
242
|
req.request_id = crypto.randomUUID();
|
|
184
|
-
|
|
185
|
-
console.log("[MIDDLEWARE] Request ID:", req.request_id);
|
|
186
|
-
|
|
187
|
-
console.log("[MIDDLEWARE] Sending incoming_request hook");
|
|
188
|
-
|
|
189
243
|
routers.gp?.resource?.incoming_request(req);
|
|
190
|
-
|
|
191
244
|
res.gp = routers.gp;
|
|
192
245
|
res.request_id = req.request_id;
|
|
193
246
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
// --------------------------------------------------
|
|
197
|
-
// STATIC / API VERSION
|
|
198
|
-
// --------------------------------------------------
|
|
199
|
-
|
|
200
|
-
error_stage = "Version Resolution";
|
|
201
|
-
|
|
247
|
+
// STATIC ROUTE DETECTION
|
|
202
248
|
let version;
|
|
203
249
|
|
|
204
250
|
const versionMatch = pathname.match(/^\/api\/([^\/]+)(\/|$)/i);
|
|
205
|
-
|
|
206
|
-
console.log("[MIDDLEWARE] Version match:", versionMatch);
|
|
207
|
-
|
|
208
251
|
if (req.method === "GET") {
|
|
209
|
-
console.log("[MIDDLEWARE] GET request");
|
|
210
|
-
|
|
211
252
|
if (routers.static_path && pathname.startsWith(routers.static_path)) {
|
|
212
|
-
console.log("[MIDDLEWARE] Static route detected:", pathname);
|
|
213
|
-
|
|
214
253
|
res.gp = routers.gp;
|
|
215
254
|
|
|
216
255
|
return serveStaticFile(req, res);
|
|
217
256
|
}
|
|
218
257
|
|
|
219
258
|
version = "__GET__";
|
|
220
|
-
|
|
221
|
-
console.log("[MIDDLEWARE] GET version:", version);
|
|
222
259
|
} else if (versionMatch) {
|
|
223
260
|
version = versionMatch[1];
|
|
224
|
-
|
|
225
|
-
console.log("[MIDDLEWARE] Version extracted from URL:", version);
|
|
226
261
|
} else {
|
|
227
262
|
version = req.headers["x-api-version"] || "v1";
|
|
228
|
-
|
|
229
|
-
console.log("[MIDDLEWARE] Version from header/default:", version);
|
|
230
263
|
}
|
|
231
264
|
|
|
232
|
-
|
|
233
|
-
// PLATFORM
|
|
234
|
-
// --------------------------------------------------
|
|
235
|
-
|
|
236
|
-
if (req.headers["x-platform"]) {
|
|
237
|
-
console.log(
|
|
238
|
-
"[MIDDLEWARE] Original x-platform:",
|
|
239
|
-
req.headers["x-platform"],
|
|
240
|
-
);
|
|
241
|
-
|
|
265
|
+
if (req.headers["x-platform"])
|
|
242
266
|
req.headers["x-platform"] = routers.gp.uri_default_domain(
|
|
243
267
|
req.headers["x-platform"],
|
|
244
268
|
);
|
|
245
269
|
|
|
246
|
-
console.log(
|
|
247
|
-
"[MIDDLEWARE] Normalized x-platform:",
|
|
248
|
-
req.headers["x-platform"],
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// --------------------------------------------------
|
|
253
|
-
// VERSION ROUTER
|
|
254
|
-
// --------------------------------------------------
|
|
255
|
-
|
|
256
|
-
console.log("[MIDDLEWARE] Getting version router:", version);
|
|
257
|
-
|
|
258
270
|
let versionRouter = await routers.get_version(version);
|
|
259
271
|
|
|
260
|
-
console.log("[MIDDLEWARE] Version router found:", !!versionRouter);
|
|
261
|
-
|
|
262
272
|
if (!versionRouter) {
|
|
263
|
-
console.log("[MIDDLEWARE] Falling back to wildcard version");
|
|
264
|
-
|
|
265
273
|
version = "*";
|
|
266
274
|
|
|
267
275
|
versionRouter = await routers.get_version(version);
|
|
268
276
|
|
|
269
|
-
console.log("[MIDDLEWARE] Wildcard router found:", !!versionRouter);
|
|
270
|
-
|
|
271
277
|
if (!versionRouter) {
|
|
272
|
-
console.log("[MIDDLEWARE] No valid version router");
|
|
273
|
-
|
|
274
278
|
return respond(
|
|
275
279
|
{
|
|
276
280
|
ok: false,
|
|
@@ -282,70 +286,38 @@ const version_middleware = async (req, res, routers) => {
|
|
|
282
286
|
}
|
|
283
287
|
}
|
|
284
288
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
// --------------------------------------------------
|
|
288
|
-
// BODY
|
|
289
|
-
// --------------------------------------------------
|
|
290
|
-
|
|
291
|
-
error_stage = "Body Parser";
|
|
289
|
+
version = versionRouter.version;
|
|
292
290
|
|
|
293
291
|
let body = {};
|
|
294
292
|
|
|
295
293
|
if (req.method === "GET") {
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
// GET keeps existing behavior: query params double as body
|
|
298
295
|
body = query;
|
|
299
296
|
} else {
|
|
300
297
|
const contentType = req.headers["content-type"] || "";
|
|
301
298
|
|
|
302
|
-
console.log("[BODY] Content-Type:", contentType);
|
|
303
|
-
|
|
304
299
|
if (contentType.includes("multipart/form-data")) {
|
|
305
|
-
console.log("[BODY] Multipart request detected");
|
|
306
|
-
|
|
307
300
|
body = await parseMultipart(req, routers.gp);
|
|
308
|
-
|
|
309
|
-
console.log("[BODY] Multipart body:", body);
|
|
310
301
|
} else {
|
|
311
|
-
|
|
312
|
-
|
|
302
|
+
error_stage = "Body Parser";
|
|
313
303
|
body = await getBody(req);
|
|
314
|
-
|
|
315
|
-
console.log("[BODY] Parsed body:", body);
|
|
316
304
|
}
|
|
317
305
|
}
|
|
318
306
|
|
|
319
|
-
// --------------------------------------------------
|
|
320
|
-
// OLD ROUTER
|
|
321
|
-
// --------------------------------------------------
|
|
322
|
-
|
|
323
307
|
if (versionRouter.config?.is_old) {
|
|
324
|
-
console.log("[ROUTER] Old router detected");
|
|
325
|
-
|
|
326
308
|
req.body = body;
|
|
327
|
-
|
|
328
|
-
console.log("[ROUTER] Passing directly to old routes");
|
|
329
|
-
|
|
330
309
|
return versionRouter.routes(req, res);
|
|
331
310
|
}
|
|
332
311
|
|
|
333
312
|
const router = routers;
|
|
334
313
|
|
|
335
|
-
//
|
|
336
|
-
// ROUTE NORMALIZATION
|
|
337
|
-
// --------------------------------------------------
|
|
338
|
-
|
|
339
|
-
error_stage = "Route Resolution";
|
|
340
|
-
|
|
314
|
+
// remove query string from route
|
|
341
315
|
let routePath = pathname;
|
|
342
316
|
|
|
343
|
-
|
|
344
|
-
|
|
317
|
+
// Remove /api/<version>
|
|
345
318
|
routePath = routePath.replace(/^\/api\/[^\/]+(?=\/|$)/i, "");
|
|
346
319
|
|
|
347
|
-
|
|
348
|
-
|
|
320
|
+
// Ensure leading slash exists
|
|
349
321
|
if (!routePath.startsWith("/")) {
|
|
350
322
|
routePath = "/" + routePath;
|
|
351
323
|
}
|
|
@@ -354,57 +326,24 @@ const version_middleware = async (req, res, routers) => {
|
|
|
354
326
|
|
|
355
327
|
let name = routePath.replace(/^\//, "");
|
|
356
328
|
|
|
357
|
-
console.log("[ROUTE] Final route path:", routePath);
|
|
358
|
-
console.log("[ROUTE] Route name:", name);
|
|
359
|
-
|
|
360
|
-
// --------------------------------------------------
|
|
361
|
-
// WEBHOOK
|
|
362
|
-
// --------------------------------------------------
|
|
363
|
-
|
|
364
329
|
const isWebhook = req.headers["is-webhook"];
|
|
365
330
|
|
|
366
|
-
console.log("[WEBHOOK] Is webhook:", isWebhook);
|
|
367
|
-
|
|
368
|
-
// --------------------------------------------------
|
|
369
331
|
// SECURITY
|
|
370
|
-
// --------------------------------------------------
|
|
371
|
-
|
|
372
332
|
error_stage = "Header";
|
|
373
|
-
|
|
374
|
-
console.log("[SECURITY] Running security handler");
|
|
375
|
-
|
|
376
|
-
const securityResult = await router.handle_security(name, req);
|
|
377
|
-
|
|
378
|
-
console.log("[SECURITY] Result:", securityResult);
|
|
333
|
+
const securityResult = await router.handle_security(name, req, version);
|
|
379
334
|
|
|
380
335
|
if (securityResult !== true) {
|
|
381
|
-
console.log("[SECURITY] Request rejected");
|
|
382
|
-
|
|
383
336
|
return respond(securityResult, res);
|
|
384
337
|
}
|
|
385
338
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
error_stage = "Database";
|
|
393
|
-
|
|
394
|
-
console.log("[DB] Resolving database");
|
|
395
|
-
|
|
396
|
-
const db = await router.resolve_db(req);
|
|
397
|
-
|
|
398
|
-
console.log("[DB] Database resolved:", !!db?.db);
|
|
399
|
-
|
|
400
|
-
// --------------------------------------------------
|
|
401
|
-
// BEFORE HOOK
|
|
402
|
-
// --------------------------------------------------
|
|
403
|
-
|
|
404
|
-
error_stage = "Before Hook";
|
|
405
|
-
|
|
406
|
-
console.log("[BEFORE] Calling handle_before");
|
|
339
|
+
// DB
|
|
340
|
+
const db = await router.resolve_db(req, {
|
|
341
|
+
version,
|
|
342
|
+
db_name: versionRouter.db_name,
|
|
343
|
+
db_prefix: versionRouter.db_prefix,
|
|
344
|
+
});
|
|
407
345
|
|
|
346
|
+
// WEBHOOK PRIOR
|
|
408
347
|
const callback = await router.handle_before(
|
|
409
348
|
{
|
|
410
349
|
req,
|
|
@@ -416,57 +355,20 @@ const version_middleware = async (req, res, routers) => {
|
|
|
416
355
|
router.gp,
|
|
417
356
|
);
|
|
418
357
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
if (callback?.response) {
|
|
422
|
-
console.log("[BEFORE] Callback supplied response");
|
|
423
|
-
|
|
424
|
-
return respond(callback.response, res);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (callback?.body) {
|
|
428
|
-
console.log("[BEFORE] Replacing body");
|
|
429
|
-
|
|
430
|
-
body = callback.body;
|
|
431
|
-
|
|
432
|
-
console.log("[BEFORE] New body:", body);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (callback?.query) {
|
|
436
|
-
console.log("[BEFORE] Replacing query");
|
|
437
|
-
|
|
438
|
-
// query must be let if this is enabled
|
|
439
|
-
// query = callback.query;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (callback?.headers) {
|
|
443
|
-
console.log("[BEFORE] Replacing headers");
|
|
444
|
-
|
|
445
|
-
req.headers = callback.headers;
|
|
358
|
+
if (callback?.response) return respond(callback.response, res);
|
|
446
359
|
|
|
447
|
-
|
|
448
|
-
}
|
|
360
|
+
if (callback?.body) body = callback.body;
|
|
449
361
|
|
|
450
|
-
if (callback?.
|
|
451
|
-
console.log("[BEFORE] Replacing database");
|
|
362
|
+
if (callback?.query) query = callback.query; // only if you make `query` a `let` — see note below
|
|
452
363
|
|
|
453
|
-
|
|
454
|
-
}
|
|
364
|
+
if (callback?.headers) req.headers = callback.headers;
|
|
455
365
|
|
|
456
|
-
if (callback?.
|
|
457
|
-
|
|
366
|
+
if (callback?.db) db.db = callback.db;
|
|
367
|
+
if (callback?.route) name = callback.route;
|
|
458
368
|
|
|
459
|
-
name = callback.route;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// --------------------------------------------------
|
|
463
369
|
// EXECUTE
|
|
464
|
-
// --------------------------------------------------
|
|
465
370
|
|
|
466
371
|
error_stage = "Handler";
|
|
467
|
-
|
|
468
|
-
console.log("[EXECUTE] Preparing handler payload");
|
|
469
|
-
|
|
470
372
|
let payload = {
|
|
471
373
|
body,
|
|
472
374
|
query,
|
|
@@ -480,27 +382,15 @@ const version_middleware = async (req, res, routers) => {
|
|
|
480
382
|
params: {},
|
|
481
383
|
memory: router.gp.memory,
|
|
482
384
|
};
|
|
385
|
+
const result = await router.execute(name, payload, version);
|
|
483
386
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
console.log("[EXECUTE] Executing route:", name);
|
|
487
|
-
|
|
488
|
-
const result = await router.execute(name, payload);
|
|
489
|
-
|
|
490
|
-
console.log("[EXECUTE] Handler result:", result);
|
|
491
|
-
|
|
492
|
-
// --------------------------------------------------
|
|
493
|
-
// AFTER HOOK
|
|
494
|
-
// --------------------------------------------------
|
|
495
|
-
|
|
387
|
+
// WEBHOOK AFTER
|
|
496
388
|
if (!isWebhook && version !== "*") {
|
|
497
389
|
error_stage = "Webhook";
|
|
498
390
|
|
|
499
|
-
console.log("[AFTER] Calling handle_after");
|
|
500
|
-
|
|
501
391
|
await router.handle_after(
|
|
502
392
|
{
|
|
503
|
-
req,
|
|
393
|
+
req: payload,
|
|
504
394
|
result,
|
|
505
395
|
headers: req.headers,
|
|
506
396
|
version,
|
|
@@ -509,32 +399,11 @@ const version_middleware = async (req, res, routers) => {
|
|
|
509
399
|
},
|
|
510
400
|
router.gp,
|
|
511
401
|
);
|
|
512
|
-
|
|
513
|
-
console.log("[AFTER] handle_after completed");
|
|
514
|
-
} else {
|
|
515
|
-
console.log("[AFTER] Skipping handle_after", {
|
|
516
|
-
isWebhook,
|
|
517
|
-
version,
|
|
518
|
-
});
|
|
519
402
|
}
|
|
520
403
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const response = respond(result, res);
|
|
524
|
-
|
|
525
|
-
console.log("[MIDDLEWARE] Final response:", response);
|
|
526
|
-
|
|
527
|
-
console.log("==================================================");
|
|
528
|
-
console.log("[MIDDLEWARE] REQUEST END");
|
|
529
|
-
console.log("==================================================");
|
|
530
|
-
|
|
531
|
-
return response;
|
|
404
|
+
return respond(result, res);
|
|
532
405
|
} catch (err) {
|
|
533
|
-
console.error(
|
|
534
|
-
console.error(`[MIDDLEWARE] ${error_stage} Error:`, err);
|
|
535
|
-
console.error("[MIDDLEWARE] Error message:", err?.message);
|
|
536
|
-
console.error("[MIDDLEWARE] Error stack:", err?.stack);
|
|
537
|
-
console.error("==================================================");
|
|
406
|
+
console.error(`${error_stage} Error:`, err);
|
|
538
407
|
|
|
539
408
|
return respond(
|
|
540
409
|
{
|