te.js 2.1.4 → 2.1.5
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/handler.js +46 -10
package/package.json
CHANGED
package/server/handler.js
CHANGED
|
@@ -12,7 +12,13 @@ const logger = new TejLogger('Tejas');
|
|
|
12
12
|
const warnedPaths = new Set();
|
|
13
13
|
|
|
14
14
|
const DEFAULT_ALLOWED_METHODS = [
|
|
15
|
-
'GET',
|
|
15
|
+
'GET',
|
|
16
|
+
'POST',
|
|
17
|
+
'PUT',
|
|
18
|
+
'DELETE',
|
|
19
|
+
'PATCH',
|
|
20
|
+
'HEAD',
|
|
21
|
+
'OPTIONS',
|
|
16
22
|
];
|
|
17
23
|
|
|
18
24
|
/**
|
|
@@ -24,9 +30,13 @@ const getAllowedMethods = () => {
|
|
|
24
30
|
if (raw == null) return new Set(DEFAULT_ALLOWED_METHODS);
|
|
25
31
|
const arr = Array.isArray(raw)
|
|
26
32
|
? raw
|
|
27
|
-
:
|
|
33
|
+
: typeof raw === 'string'
|
|
34
|
+
? raw.split(',').map((s) => s.trim())
|
|
35
|
+
: [];
|
|
28
36
|
const normalized = arr.map((m) => String(m).toUpperCase()).filter(Boolean);
|
|
29
|
-
return normalized.length > 0
|
|
37
|
+
return normalized.length > 0
|
|
38
|
+
? new Set(normalized)
|
|
39
|
+
: new Set(DEFAULT_ALLOWED_METHODS);
|
|
30
40
|
};
|
|
31
41
|
|
|
32
42
|
/**
|
|
@@ -58,23 +68,31 @@ const executeChain = async (target, ammo) => {
|
|
|
58
68
|
|
|
59
69
|
try {
|
|
60
70
|
const result = await middleware(...args);
|
|
61
|
-
|
|
71
|
+
|
|
62
72
|
// Check again after middleware execution (passport might have redirected)
|
|
63
73
|
if (ammo.res.headersSent || ammo.res.writableEnded || ammo.res.finished) {
|
|
64
74
|
return;
|
|
65
75
|
}
|
|
66
|
-
|
|
76
|
+
|
|
67
77
|
// If middleware returned a promise that resolved, continue chain
|
|
68
78
|
if (result && typeof result.then === 'function') {
|
|
69
79
|
await result;
|
|
70
80
|
// Check one more time after promise resolution
|
|
71
|
-
if (
|
|
81
|
+
if (
|
|
82
|
+
ammo.res.headersSent ||
|
|
83
|
+
ammo.res.writableEnded ||
|
|
84
|
+
ammo.res.finished
|
|
85
|
+
) {
|
|
72
86
|
return;
|
|
73
87
|
}
|
|
74
88
|
}
|
|
75
89
|
} catch (err) {
|
|
76
90
|
// Only handle error if response hasn't been sent
|
|
77
|
-
if (
|
|
91
|
+
if (
|
|
92
|
+
!ammo.res.headersSent &&
|
|
93
|
+
!ammo.res.writableEnded &&
|
|
94
|
+
!ammo.res.finished
|
|
95
|
+
) {
|
|
78
96
|
await errorHandler(ammo, err);
|
|
79
97
|
}
|
|
80
98
|
}
|
|
@@ -126,9 +144,11 @@ const handler = async (req, res) => {
|
|
|
126
144
|
const ammo = new Ammo(req, res);
|
|
127
145
|
|
|
128
146
|
try {
|
|
129
|
-
|
|
130
|
-
|
|
147
|
+
// Enhance ammo for all requests (matched or not) so global middlewares
|
|
148
|
+
// always receive a fully-populated ammo (method flags, headers, payload, etc.).
|
|
149
|
+
await ammo.enhance();
|
|
131
150
|
|
|
151
|
+
if (match && match.target) {
|
|
132
152
|
const allowedMethods = match.target.getMethods();
|
|
133
153
|
if (allowedMethods != null && allowedMethods.length > 0) {
|
|
134
154
|
const method = ammo.method && String(ammo.method).toUpperCase();
|
|
@@ -156,7 +176,23 @@ const handler = async (req, res) => {
|
|
|
156
176
|
if (req.url === '/') {
|
|
157
177
|
ammo.defaultEntry();
|
|
158
178
|
} else {
|
|
159
|
-
|
|
179
|
+
// Run global middlewares (CORS preflight, auth, logging, etc.) even for
|
|
180
|
+
// unmatched routes. A pseudo-target with no route-specific middlewares
|
|
181
|
+
// is used so the 404 response is sent at the end of the global chain.
|
|
182
|
+
await executeChain(
|
|
183
|
+
{
|
|
184
|
+
getMiddlewares: () => [],
|
|
185
|
+
getHandler: () => async () => {
|
|
186
|
+
if (!ammo.res.headersSent) {
|
|
187
|
+
await errorHandler(
|
|
188
|
+
ammo,
|
|
189
|
+
new TejError(404, `URL not found: ${url}`),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
ammo,
|
|
195
|
+
);
|
|
160
196
|
}
|
|
161
197
|
}
|
|
162
198
|
} catch (err) {
|