@zintrust/core 2.5.6 → 2.5.8
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
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BodyParsingMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/http/middleware/BodyParsingMiddleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"BodyParsingMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/http/middleware/BodyParsingMiddleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAwV9D;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UA4CnC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -156,6 +156,29 @@ const parseJsonBody = (text, contentType, res) => {
|
|
|
156
156
|
return null;
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
|
+
/**
|
|
160
|
+
* Attempt to recover a JSON string that was stored as raw text or bytes
|
|
161
|
+
* due to a missing or incorrect Content-Type header.
|
|
162
|
+
*
|
|
163
|
+
* Only plain objects `{...}` are considered for recovery — arrays, strings,
|
|
164
|
+
* and primitives are left unchanged. This minimizes false positives for
|
|
165
|
+
* legitimate text or binary payloads that happen to start with `{`.
|
|
166
|
+
*/
|
|
167
|
+
const tryRecoverTextJsonBody = (body) => {
|
|
168
|
+
const trimmed = body.trim();
|
|
169
|
+
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
170
|
+
try {
|
|
171
|
+
const parsed = JSON.parse(trimmed);
|
|
172
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
173
|
+
return parsed;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Not valid JSON — leave original unchanged
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return body;
|
|
181
|
+
};
|
|
159
182
|
const setRequestBody = (req, rawResult, contentType) => {
|
|
160
183
|
const isUrlEncoded = contentType.includes('application/x-www-form-urlencoded');
|
|
161
184
|
const isText = contentType.startsWith('text/') || contentType.includes('application/xml');
|
|
@@ -164,9 +187,26 @@ const setRequestBody = (req, rawResult, contentType) => {
|
|
|
164
187
|
req.setBody(parseUrlEncodedBody(text));
|
|
165
188
|
}
|
|
166
189
|
else if (isText) {
|
|
167
|
-
|
|
190
|
+
// Recovery: JSON body sent with text Content-Type (e.g. text/plain)
|
|
191
|
+
// is stored as a raw string. Detect a JSON object and parse it.
|
|
192
|
+
req.setBody(tryRecoverTextJsonBody(text));
|
|
168
193
|
}
|
|
169
194
|
else if (contentType !== '') {
|
|
195
|
+
// Recovery: JSON body sent with an unknown Content-Type is stored as
|
|
196
|
+
// raw bytes. Try to decode as text and check for JSON.
|
|
197
|
+
const decoded = text.trim();
|
|
198
|
+
if (decoded.startsWith('{') && decoded.endsWith('}')) {
|
|
199
|
+
try {
|
|
200
|
+
const parsed = JSON.parse(decoded);
|
|
201
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
202
|
+
req.setBody(parsed);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// Not valid JSON — fall through to bytes
|
|
208
|
+
}
|
|
209
|
+
}
|
|
170
210
|
req.setBody(rawResult.bytes);
|
|
171
211
|
}
|
|
172
212
|
};
|
|
@@ -213,6 +253,25 @@ const parseUrlEncodedBody = (text) => {
|
|
|
213
253
|
}
|
|
214
254
|
out[key] = [existing, value];
|
|
215
255
|
}
|
|
256
|
+
// Recovery: if a JSON payload is sent with the wrong Content-Type header
|
|
257
|
+
// (e.g. application/x-www-form-urlencoded instead of application/json),
|
|
258
|
+
// URLSearchParams will treat the entire JSON string as a single key with
|
|
259
|
+
// an empty value. Detect this degenerate case and fall back to JSON.parse.
|
|
260
|
+
const keys = Object.keys(out);
|
|
261
|
+
if (keys.length === 1 && out[keys[0]] === '') {
|
|
262
|
+
const maybeJson = keys[0].trim();
|
|
263
|
+
if (maybeJson.startsWith('{') && maybeJson.endsWith('}')) {
|
|
264
|
+
try {
|
|
265
|
+
const parsed = JSON.parse(maybeJson);
|
|
266
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
267
|
+
return parsed;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// Not valid JSON — leave original result unchanged
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
216
275
|
return out;
|
|
217
276
|
};
|
|
218
277
|
const processBodyParsing = async (req, res, contentType, maxBytes) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BodyParsers.d.ts","sourceRoot":"","sources":["../../../../src/http/parsers/BodyParsers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,gBAAgB;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,OAAO,EAAE,CAAC;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC;CAChD;
|
|
1
|
+
{"version":3,"file":"BodyParsers.d.ts","sourceRoot":"","sources":["../../../../src/http/parsers/BodyParsers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,gBAAgB;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,OAAO,EAAE,CAAC;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC;CAChD;AAiLD,eAAO,MAAM,WAAW;;;;IAKtB;;OAEG;cACO,WAAW,EAAE;IAIvB;;OAEG;4BACqB,MAAM,GAAG,WAAW,GAAG,SAAS;IAIxD;;OAEG;uBACgB,MAAM,QAAQ,MAAM,GAAG,MAAM,GAAG,gBAAgB;EAQnE,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
* Body Parsers - Content-Type specific parsing
|
|
3
3
|
* Handles form-data, plain text, CSV, and other non-JSON formats
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Attempt to recover a JSON string that was parsed as a single form-urlencoded key.
|
|
7
|
+
* This handles cases where clients send JSON with the wrong Content-Type header.
|
|
8
|
+
*/
|
|
9
|
+
const tryRecoverJsonBody = (result) => {
|
|
10
|
+
const keys = Object.keys(result);
|
|
11
|
+
if (keys.length !== 1)
|
|
12
|
+
return undefined;
|
|
13
|
+
const singleValue = result[keys[0]];
|
|
14
|
+
if (singleValue !== '')
|
|
15
|
+
return undefined;
|
|
16
|
+
const maybeJson = keys[0].trim();
|
|
17
|
+
if (!maybeJson.startsWith('{') || !maybeJson.endsWith('}'))
|
|
18
|
+
return undefined;
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(maybeJson);
|
|
21
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Not valid JSON — leave original result unchanged
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
};
|
|
5
30
|
/**
|
|
6
31
|
* URL-encoded form data parser
|
|
7
32
|
* Content-Type: application/x-www-form-urlencoded
|
|
@@ -30,6 +55,13 @@ const FormDataParser = {
|
|
|
30
55
|
result[key] = value;
|
|
31
56
|
}
|
|
32
57
|
}
|
|
58
|
+
// Recovery: if a JSON payload is sent with the wrong Content-Type header,
|
|
59
|
+
// URLSearchParams will treat the entire JSON string as a single key with
|
|
60
|
+
// an empty value. Detect this degenerate case and fall back to JSON.parse.
|
|
61
|
+
const recovered = tryRecoverJsonBody(result);
|
|
62
|
+
if (recovered !== undefined) {
|
|
63
|
+
return { ok: true, data: recovered };
|
|
64
|
+
}
|
|
33
65
|
return { ok: true, data: result };
|
|
34
66
|
}
|
|
35
67
|
catch (error) {
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v2.5.
|
|
2
|
+
* @zintrust/core v2.5.8
|
|
3
3
|
*
|
|
4
4
|
* ZinTrust Framework - Production-Grade TypeScript Backend
|
|
5
5
|
* Built for performance, type safety, and exceptional developer experience
|
|
6
6
|
*
|
|
7
7
|
* Build Information:
|
|
8
|
-
* Built: 2026-06-
|
|
8
|
+
* Built: 2026-06-12T18:44:49.274Z
|
|
9
9
|
* Node: >=20.0.0
|
|
10
10
|
* License: MIT
|
|
11
11
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Available at runtime for debugging and health checks
|
|
22
22
|
*/
|
|
23
23
|
export const ZINTRUST_VERSION = '0.1.41';
|
|
24
|
-
export const ZINTRUST_BUILD_DATE = '2026-06-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-06-12T18:44:49.232Z'; // Replaced during build
|
|
25
25
|
export { Application } from './boot/Application.js';
|
|
26
26
|
export { AwsSigV4 } from './common/index.js';
|
|
27
27
|
export { SignedRequest } from './security/SignedRequest.js';
|