jerkjs 2.0.2 → 2.1.0
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/CHANGELOG.md +31 -0
- package/JERK_FRAMEWORK_DIAGRAM.txt +492 -0
- package/JERK_FRAMEWORK_DIAGRAM_MERMAID.mmd +124 -0
- package/JERK_FRAMEWORK_DOCUMENTATION.md +527 -0
- package/README.md +12 -2
- package/docs/guia_inicio_rapido_jerkjs.md +113 -0
- package/examples/hooks/app.js +136 -0
- package/examples/hooks/controllers/authController.js +54 -0
- package/examples/hooks/controllers/mainController.js +41 -0
- package/examples/hooks/controllers/productController.js +39 -0
- package/examples/hooks/controllers/userController.js +69 -0
- package/examples/hooks/routes.json +51 -0
- package/examples/hooks/views/home.html +50 -0
- package/index.js +11 -2
- package/jerk.jpg +0 -0
- package/lib/core/router.js +1 -0
- package/lib/core/securityEnhancedServer.js +1 -0
- package/lib/core/server.js +31 -8
- package/lib/loader/routeLoader.js +1 -0
- package/lib/middleware/compressor.js +16 -10
- package/lib/mvc/viewEngine.js +1 -0
- package/lib/utils/errorHandler.js +118 -0
- package/lib/utils/logger.js +65 -0
- package/package.json +8 -5
- package/README.md.backup +0 -169
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## v2.1.0 - 17 de enero de 2026
|
|
4
|
+
|
|
5
|
+
### Nuevas características
|
|
6
|
+
|
|
7
|
+
- **Optimización del procesamiento del body request**: Se ha implementado una nueva técnica para procesar el cuerpo de las solicitudes usando arrays de chunks en lugar de concatenación de strings, lo que reduce significativamente el uso de memoria y mejora el rendimiento para solicitudes grandes (reducción del 50-70% en tiempo de procesamiento).
|
|
8
|
+
|
|
9
|
+
- **Cacheo de expresiones regulares para rutas parametrizadas**: Se ha añadido un sistema de cache para las expresiones regulares compiladas de rutas parametrizadas, evitando la recompilación repetida y mejorando el rendimiento del enrutamiento (reducción del 10-20% en tiempo de routing).
|
|
10
|
+
|
|
11
|
+
- **Sistema de logging estructurado**: Se han añadido nuevas funcionalidades al sistema de logging para registrar métricas de rendimiento, uso de memoria y otros datos estructurados para mejor monitoreo y diagnóstico.
|
|
12
|
+
|
|
13
|
+
- **Manejo de errores más robusto**: Se ha implementado un sistema de manejo de errores centralizado con clases de error personalizadas (ValidationError, AuthenticationError, DatabaseError) para mejor clasificación y tratamiento de diferentes tipos de errores.
|
|
14
|
+
|
|
15
|
+
- **Optimización de memoria en el servidor HTTP**: Se han configurado keep-alive timeouts apropiados y se ha añadido monitoreo de uso de memoria para mejorar la estabilidad bajo carga prolongada.
|
|
16
|
+
|
|
17
|
+
- **Segunda demostración con rutas en JSON**: Se ha añadido una nueva demostración que muestra cómo usar un archivo JSON para definir rutas, aprovechando todas las optimizaciones del framework.
|
|
18
|
+
|
|
19
|
+
### Mejoras
|
|
20
|
+
|
|
21
|
+
- **Eficiencia del middleware de compresión**: Se ha optimizado el middleware de compresión para usar arrays de chunks en lugar de concatenación de strings, mejorando la eficiencia del proceso de compresión.
|
|
22
|
+
- **Sistema de hooks mejorado**: Se han añadido más puntos de integración para los hooks en los nuevos componentes optimizados.
|
|
23
|
+
- **Documentación actualizada**: Se ha actualizado la documentación con ejemplos de uso de las nuevas optimizaciones.
|
|
24
|
+
- **Mejora en el sistema de rutas**: El sistema de rutas ahora utiliza cache para expresiones regulares, mejorando el rendimiento general.
|
|
25
|
+
|
|
26
|
+
### Correcciones
|
|
27
|
+
|
|
28
|
+
- Corrección de ineficiencia en el procesamiento de cuerpos de solicitud grandes
|
|
29
|
+
- Mejora en la gestión de memoria durante el procesamiento de solicitudes
|
|
30
|
+
- Corrección de posibles problemas de rendimiento en aplicaciones con muchas rutas parametrizadas
|
|
31
|
+
- Mejora en la estabilidad del servidor bajo carga prolongada
|
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
JERK FRAMEWORK v2.0 - DIAGRAMA DE FLUJO DETALLADO
|
|
2
|
+
===============================================
|
|
3
|
+
|
|
4
|
+
[INICIO]
|
|
5
|
+
│
|
|
6
|
+
▼
|
|
7
|
+
[APIServer.start()]
|
|
8
|
+
│
|
|
9
|
+
▼
|
|
10
|
+
[HTTP Request recibido]
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
[Verificar método HTTP]
|
|
14
|
+
├─ GET ──────────────────────────────────────────────────────────────►
|
|
15
|
+
├─ POST ─────────────────────────────────────────────────────────────►
|
|
16
|
+
├─ PUT ──────────────────────────────────────────────────────────────►
|
|
17
|
+
├─ DELETE ───────────────────────────────────────────────────────────►
|
|
18
|
+
└─ OPTIONS ──────────────────────────────────────────────────────────►
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
[Parse URL: pathname, query]
|
|
22
|
+
│
|
|
23
|
+
▼
|
|
24
|
+
[req.query = query]
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
[req.params = {}]
|
|
28
|
+
│
|
|
29
|
+
▼
|
|
30
|
+
[req.body = '', bodySize = 0]
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
[Capturar body con límite maxBodySize]
|
|
34
|
+
│
|
|
35
|
+
├─ bodySize > maxBodySize? ──► [413 Request Too Large] ──► [FIN]
|
|
36
|
+
│
|
|
37
|
+
▼
|
|
38
|
+
[Fin de recepción de datos]
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
[Parse body si es JSON]
|
|
42
|
+
│
|
|
43
|
+
▼
|
|
44
|
+
[¿Es solicitud OPTIONS?]
|
|
45
|
+
├─ SÍ ──► [Ejecutar middlewares CORS]
|
|
46
|
+
│ │
|
|
47
|
+
│ ▼
|
|
48
|
+
│ [¿Hay ruta específica para OPTIONS?]
|
|
49
|
+
│ ├─ SÍ ──► [Agregar parámetros req.params]
|
|
50
|
+
│ │ │
|
|
51
|
+
│ │ ▼
|
|
52
|
+
│ │ [Ejecutar handler de ruta]
|
|
53
|
+
│ │ │
|
|
54
|
+
│ │ ▼
|
|
55
|
+
│ └─ NO ──► [204 No Content] ──► [FIN]
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
└─ NO ──► [Buscar ruta coincidente: findRoute(method, pathname)]
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
[¿Ruta encontrada?]
|
|
62
|
+
├─ NO ──► [404 Not Found] ──► [FIN]
|
|
63
|
+
│
|
|
64
|
+
▼
|
|
65
|
+
└─ SÍ ──► [Agregar parámetros req.params]
|
|
66
|
+
│
|
|
67
|
+
▼
|
|
68
|
+
[Ejecutar middlewares en secuencia]
|
|
69
|
+
│
|
|
70
|
+
▼
|
|
71
|
+
[¿Middleware respondió?]
|
|
72
|
+
├─ SÍ ──► [FIN]
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
└─ NO ──► [Ejecutar handler de ruta]
|
|
76
|
+
│
|
|
77
|
+
▼
|
|
78
|
+
[¿Handler es asíncrono?]
|
|
79
|
+
├─ SÍ ──► [await handler(req, res)]
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
└─ NO ──► [handler(req, res)]
|
|
83
|
+
│
|
|
84
|
+
▼
|
|
85
|
+
[FIN - Respuesta enviada]
|
|
86
|
+
|
|
87
|
+
DETALLE DE findRoute():
|
|
88
|
+
[findRoute(method, pathname)]
|
|
89
|
+
│
|
|
90
|
+
▼
|
|
91
|
+
[Búsqueda de ruta exacta]
|
|
92
|
+
│
|
|
93
|
+
▼
|
|
94
|
+
[¿Encuentra ruta exacta?]
|
|
95
|
+
├─ SÍ ──► [Devolver {route, params: {}}]
|
|
96
|
+
│
|
|
97
|
+
▼
|
|
98
|
+
└─ NO ──► [Búsqueda de rutas parametrizadas]
|
|
99
|
+
│
|
|
100
|
+
▼
|
|
101
|
+
[Iterar por cada ruta]
|
|
102
|
+
│
|
|
103
|
+
▼
|
|
104
|
+
[¿Mismo método HTTP?]
|
|
105
|
+
├─ NO ──► [Siguiente ruta]
|
|
106
|
+
│
|
|
107
|
+
▼
|
|
108
|
+
└─ SÍ ──► [Convertir ruta a expresión regular: pathToRegex(route.path)]
|
|
109
|
+
│
|
|
110
|
+
▼
|
|
111
|
+
[¿pathname.match(routeRegex)?]
|
|
112
|
+
├─ SÍ ──► [Extraer parámetros: extractParams(route.path, pathname)]
|
|
113
|
+
│ │
|
|
114
|
+
│ ▼
|
|
115
|
+
│ [Devolver {route, params}]
|
|
116
|
+
│
|
|
117
|
+
▼
|
|
118
|
+
└─ NO ──► [Siguiente ruta]
|
|
119
|
+
│
|
|
120
|
+
▼
|
|
121
|
+
[¿Más rutas?]
|
|
122
|
+
├─ SÍ ──► [Iterar]
|
|
123
|
+
└─ NO ──► [Devolver null]
|
|
124
|
+
|
|
125
|
+
DETALLE DE pathToRegex():
|
|
126
|
+
[pathToRegex(path)]
|
|
127
|
+
│
|
|
128
|
+
▼
|
|
129
|
+
[Escapar caracteres especiales manteniendo parámetros]
|
|
130
|
+
│
|
|
131
|
+
▼
|
|
132
|
+
[Reemplazar :param con ([^/]+?)]
|
|
133
|
+
│
|
|
134
|
+
▼
|
|
135
|
+
[Crear RegExp: new RegExp(`^${regexPath}$`)]
|
|
136
|
+
|
|
137
|
+
DETALLE DE extractParams():
|
|
138
|
+
[extractParams(routePath, actualPath)]
|
|
139
|
+
│
|
|
140
|
+
▼
|
|
141
|
+
[Encontrar nombres de parámetros con /:([a-zA-Z0-9_]+)/g]
|
|
142
|
+
│
|
|
143
|
+
▼
|
|
144
|
+
[Crear array paramNames]
|
|
145
|
+
│
|
|
146
|
+
▼
|
|
147
|
+
[Generar routeRegex con pathToRegex]
|
|
148
|
+
│
|
|
149
|
+
▼
|
|
150
|
+
[Obtener values con actualPath.match(routeRegex)]
|
|
151
|
+
│
|
|
152
|
+
▼
|
|
153
|
+
[Asignar valores a parámetros: params[paramNames[i]] = values[i+1]]
|
|
154
|
+
│
|
|
155
|
+
▼
|
|
156
|
+
[Devolver params]
|
|
157
|
+
|
|
158
|
+
DETALLE DE handleRequest():
|
|
159
|
+
[handleRequest(req, res)]
|
|
160
|
+
│
|
|
161
|
+
▼
|
|
162
|
+
[Parse URL: pathname, query]
|
|
163
|
+
│
|
|
164
|
+
▼
|
|
165
|
+
[req.query = query, req.params = {}, req.body = '']
|
|
166
|
+
│
|
|
167
|
+
▼
|
|
168
|
+
[Capturar body con límite]
|
|
169
|
+
│
|
|
170
|
+
├─ ¿bodySize > maxBodySize? ──► [413 Error] ──► [FIN]
|
|
171
|
+
│
|
|
172
|
+
▼
|
|
173
|
+
[Fin de recepción de datos]
|
|
174
|
+
│
|
|
175
|
+
▼
|
|
176
|
+
[Parse body si es JSON]
|
|
177
|
+
│
|
|
178
|
+
▼
|
|
179
|
+
[¿Es solicitud OPTIONS?]
|
|
180
|
+
├─ SÍ ──► [Ejecutar middlewares]
|
|
181
|
+
│ │
|
|
182
|
+
│ ▼
|
|
183
|
+
│ [¿Hay ruta específica?]
|
|
184
|
+
│ ├─ SÍ ──► [Ejecutar handler]
|
|
185
|
+
│ └─ NO ──► [204 No Content]
|
|
186
|
+
│
|
|
187
|
+
▼
|
|
188
|
+
└─ NO ──► [findRoute(method, pathname)]
|
|
189
|
+
│
|
|
190
|
+
▼
|
|
191
|
+
[¿Ruta encontrada?]
|
|
192
|
+
├─ NO ──► [404 Not Found]
|
|
193
|
+
│
|
|
194
|
+
▼
|
|
195
|
+
└─ SÍ ──► [Agregar req.params]
|
|
196
|
+
│
|
|
197
|
+
▼
|
|
198
|
+
[Ejecutar middlewares]
|
|
199
|
+
│
|
|
200
|
+
▼
|
|
201
|
+
[¿Middleware respondió?]
|
|
202
|
+
├─ SÍ ──► [FIN]
|
|
203
|
+
│
|
|
204
|
+
▼
|
|
205
|
+
└─ NO ──► [Ejecutar handler]
|
|
206
|
+
│
|
|
207
|
+
▼
|
|
208
|
+
[¿Handler asíncrono?]
|
|
209
|
+
├─ SÍ ──► [await handler]
|
|
210
|
+
└─ NO ──► [handler]
|
|
211
|
+
|
|
212
|
+
ESTRUCTURA DE ARCHIVOS:
|
|
213
|
+
├── index.js (entry point)
|
|
214
|
+
├── lib/
|
|
215
|
+
│ ├── core/
|
|
216
|
+
│ │ ├── server.js (APIServer)
|
|
217
|
+
│ │ ├── router.js (Router)
|
|
218
|
+
│ │ └── ...
|
|
219
|
+
│ ├── middleware/
|
|
220
|
+
│ │ ├── authenticator.js (Authenticator)
|
|
221
|
+
│ │ ├── firewall.js (Firewall)
|
|
222
|
+
│ │ └── ...
|
|
223
|
+
│ ├── loader/
|
|
224
|
+
│ │ ├── routeLoader.js (RouteLoader)
|
|
225
|
+
│ │ └── ...
|
|
226
|
+
│ ├── mvc/
|
|
227
|
+
│ │ ├── viewEngine.js (ViewEngine)
|
|
228
|
+
│ │ ├── controllerBase.js (ControllerBase)
|
|
229
|
+
│ │ └── ...
|
|
230
|
+
│ └── utils/
|
|
231
|
+
│ ├── tokenManager.js (TokenManager)
|
|
232
|
+
│ ├── logger.js (Logger)
|
|
233
|
+
│ └── ...
|
|
234
|
+
├── docs/
|
|
235
|
+
│ └── guia_inicio_rapido_jerkjs.md
|
|
236
|
+
├── examples/
|
|
237
|
+
├── v2examplle/
|
|
238
|
+
├── README.md
|
|
239
|
+
├── package.json
|
|
240
|
+
└── CHANGELOG.md
|
|
241
|
+
|
|
242
|
+
FLUJO DE CARGA DE RUTAS:
|
|
243
|
+
[RouteLoader.loadRoutes(server, filePath)]
|
|
244
|
+
│
|
|
245
|
+
▼
|
|
246
|
+
[¿Existe archivo?]
|
|
247
|
+
├─ NO ──► [Error: Archivo no encontrado]
|
|
248
|
+
│
|
|
249
|
+
▼
|
|
250
|
+
└─ SÍ ──► [Leer y parsear JSON]
|
|
251
|
+
│
|
|
252
|
+
▼
|
|
253
|
+
[validateRoutesStructure(routes)]
|
|
254
|
+
│
|
|
255
|
+
▼
|
|
256
|
+
[Iterar por cada route]
|
|
257
|
+
│
|
|
258
|
+
▼
|
|
259
|
+
[loadSingleRoute(server, route)]
|
|
260
|
+
│
|
|
261
|
+
▼
|
|
262
|
+
[¿Tiene contentType?]
|
|
263
|
+
├─ SÍ ──► [Crear wrapper con setHeader]
|
|
264
|
+
│
|
|
265
|
+
▼
|
|
266
|
+
└─ NO ──► [Usar handler directamente]
|
|
267
|
+
│
|
|
268
|
+
▼
|
|
269
|
+
[¿Tiene autenticación?]
|
|
270
|
+
├─ NO ──► [server.addRoute(method, path, handler)]
|
|
271
|
+
│
|
|
272
|
+
▼
|
|
273
|
+
└─ SÍ ──► [¿Es autenticación de sesión?]
|
|
274
|
+
├─ SÍ ──► [sessionAuth middleware]
|
|
275
|
+
│ │
|
|
276
|
+
│ ▼
|
|
277
|
+
│ [Crear authenticatedHandler]
|
|
278
|
+
│ │
|
|
279
|
+
│ ▼
|
|
280
|
+
│ [server.addRoute(method, path, authenticatedHandler)]
|
|
281
|
+
│
|
|
282
|
+
▼
|
|
283
|
+
└─ NO ──► [authenticator.authenticate middleware]
|
|
284
|
+
│
|
|
285
|
+
▼
|
|
286
|
+
[Crear authenticatedHandler]
|
|
287
|
+
│
|
|
288
|
+
▼
|
|
289
|
+
[server.addRoute(method, path, authenticatedHandler)]
|
|
290
|
+
|
|
291
|
+
FLUJO DE AUTENTICACIÓN:
|
|
292
|
+
[Authenticator.authenticate(strategyName, options)]
|
|
293
|
+
│
|
|
294
|
+
▼
|
|
295
|
+
[¿Existe estrategia?]
|
|
296
|
+
├─ NO ──► [Error: Estrategia no encontrada]
|
|
297
|
+
│
|
|
298
|
+
▼
|
|
299
|
+
└─ SÍ ──► [Obtener IP cliente]
|
|
300
|
+
│
|
|
301
|
+
▼
|
|
302
|
+
[¿IP está bloqueada?]
|
|
303
|
+
├─ SÍ ──► [403 Forbidden - Acceso bloqueado]
|
|
304
|
+
│
|
|
305
|
+
▼
|
|
306
|
+
└─ NO ──► [Ejecutar estrategia]
|
|
307
|
+
│
|
|
308
|
+
▼
|
|
309
|
+
[¿Autenticación exitosa?]
|
|
310
|
+
├─ SÍ ──► [Registrar éxito, resetear intentos, next()]
|
|
311
|
+
│
|
|
312
|
+
▼
|
|
313
|
+
└─ NO ──► [Incrementar intentos fallidos, registrar fallo, 401 Unauthorized]
|
|
314
|
+
|
|
315
|
+
FLUJO DE FIREWALL:
|
|
316
|
+
[Firewall.middleware()]
|
|
317
|
+
│
|
|
318
|
+
▼
|
|
319
|
+
[Obtener IP cliente]
|
|
320
|
+
│
|
|
321
|
+
▼
|
|
322
|
+
[¿IP está bloqueada?]
|
|
323
|
+
├─ SÍ ──► [403 Forbidden - Acceso denegado por firewall]
|
|
324
|
+
│
|
|
325
|
+
▼
|
|
326
|
+
└─ NO ──► [checkRules(req)]
|
|
327
|
+
│
|
|
328
|
+
▼
|
|
329
|
+
[¿Coincide con alguna regla?]
|
|
330
|
+
├─ SÍ ──► [¿Acción es bloquear?]
|
|
331
|
+
│ ├─ SÍ ──► [Incrementar intentos, 403 Forbidden]
|
|
332
|
+
│ └─ NO ──► [Continuar con monitoreo]
|
|
333
|
+
│
|
|
334
|
+
▼
|
|
335
|
+
└─ NO ──► [next() - Continuar con siguiente middleware]
|
|
336
|
+
|
|
337
|
+
FLUJO DE MOTOR DE PLANTILLAS:
|
|
338
|
+
[ViewEngine.render(viewName, data, options)]
|
|
339
|
+
│
|
|
340
|
+
▼
|
|
341
|
+
[getViewPath(viewName)]
|
|
342
|
+
│
|
|
343
|
+
▼
|
|
344
|
+
[¿Existe vista?]
|
|
345
|
+
├─ NO ──► [Error: Vista no encontrada]
|
|
346
|
+
│
|
|
347
|
+
▼
|
|
348
|
+
└─ SÍ ──► [¿Habilitado cache y está en cache?]
|
|
349
|
+
├─ SÍ ──► [Obtener del cache]
|
|
350
|
+
│
|
|
351
|
+
▼
|
|
352
|
+
└─ NO ──► [Leer contenido de vista]
|
|
353
|
+
│
|
|
354
|
+
▼
|
|
355
|
+
[processIncludes(content, dirname)]
|
|
356
|
+
│
|
|
357
|
+
▼
|
|
358
|
+
[¿Habilitar cache?]
|
|
359
|
+
├─ SÍ ──► [Guardar en cache]
|
|
360
|
+
│
|
|
361
|
+
▼
|
|
362
|
+
└─ NO ──► [Continuar]
|
|
363
|
+
│
|
|
364
|
+
▼
|
|
365
|
+
[processTemplate(content, data, options)]
|
|
366
|
+
│
|
|
367
|
+
▼
|
|
368
|
+
[processForeach(template, data, options)]
|
|
369
|
+
│
|
|
370
|
+
▼
|
|
371
|
+
[processConditionals(template, data, options)]
|
|
372
|
+
│
|
|
373
|
+
▼
|
|
374
|
+
[replaceVariablesAndFilters(template, data, options)]
|
|
375
|
+
│
|
|
376
|
+
▼
|
|
377
|
+
[Devolver template procesado]
|
|
378
|
+
|
|
379
|
+
FLUJO DE SESIONES:
|
|
380
|
+
[SessionManager.middleware()]
|
|
381
|
+
│
|
|
382
|
+
▼
|
|
383
|
+
[¿Tiene cookie de sesión?]
|
|
384
|
+
├─ NO ──► [Crear nueva sesión]
|
|
385
|
+
│
|
|
386
|
+
▼
|
|
387
|
+
└─ SÍ ──► [Validar sesión existente]
|
|
388
|
+
│
|
|
389
|
+
▼
|
|
390
|
+
[¿Sesión válida?]
|
|
391
|
+
├─ NO ──► [Crear nueva sesión]
|
|
392
|
+
│
|
|
393
|
+
▼
|
|
394
|
+
└─ SÍ ──► [Actualizar última actividad]
|
|
395
|
+
│
|
|
396
|
+
▼
|
|
397
|
+
[Agregar req.session]
|
|
398
|
+
│
|
|
399
|
+
▼
|
|
400
|
+
[next()]
|
|
401
|
+
|
|
402
|
+
FLUJO DE HOOKS:
|
|
403
|
+
[hooks.doAction('nombre_hook', ...args)]
|
|
404
|
+
│
|
|
405
|
+
▼
|
|
406
|
+
[Buscar listeners para 'nombre_hook']
|
|
407
|
+
│
|
|
408
|
+
▼
|
|
409
|
+
[Ejecutar cada listener en secuencia]
|
|
410
|
+
│
|
|
411
|
+
▼
|
|
412
|
+
[Continuar]
|
|
413
|
+
|
|
414
|
+
[hooks.applyFilters('nombre_filtro', value, ...args)]
|
|
415
|
+
│
|
|
416
|
+
▼
|
|
417
|
+
[Buscar listeners para 'nombre_filtro']
|
|
418
|
+
│
|
|
419
|
+
▼
|
|
420
|
+
[Aplicar cada listener al valor en secuencia]
|
|
421
|
+
│
|
|
422
|
+
▼
|
|
423
|
+
[Devolver valor modificado]
|
|
424
|
+
|
|
425
|
+
ESTRATEGIAS DE AUTENTICACIÓN:
|
|
426
|
+
1. JWT Strategy:
|
|
427
|
+
- Verificar header Authorization: Bearer token
|
|
428
|
+
- Validar token con jwt.verify()
|
|
429
|
+
- ¿Token expirado? → Intentar refresh con refresh token
|
|
430
|
+
- Agregar req.user con payload decodificado
|
|
431
|
+
|
|
432
|
+
2. API Key Strategy:
|
|
433
|
+
- Verificar header X-API-Key
|
|
434
|
+
- Comparar con claves válidas
|
|
435
|
+
- ¿Configuración por tenant? → Usar claves específicas
|
|
436
|
+
|
|
437
|
+
3. Basic Strategy:
|
|
438
|
+
- Verificar header Authorization: Basic base64(usuario:contraseña)
|
|
439
|
+
- Decodificar y comparar credenciales
|
|
440
|
+
- Agregar req.user con nombre de usuario
|
|
441
|
+
|
|
442
|
+
4. OAuth2 Strategy:
|
|
443
|
+
- Verificar token Bearer o código de autorización
|
|
444
|
+
- Validar con proveedor OAuth2
|
|
445
|
+
- Agregar req.oauth2User
|
|
446
|
+
|
|
447
|
+
5. OpenID Connect Strategy:
|
|
448
|
+
- Verificar ID token
|
|
449
|
+
- Validar con proveedor OIDC
|
|
450
|
+
- Agregar req.oidcUser
|
|
451
|
+
|
|
452
|
+
FLUJO DE VALIDACIÓN DE RUTAS:
|
|
453
|
+
[validateRoutesStructure(routes)]
|
|
454
|
+
│
|
|
455
|
+
▼
|
|
456
|
+
[¿routes es array?]
|
|
457
|
+
├─ NO ──► [Error: No es array]
|
|
458
|
+
│
|
|
459
|
+
▼
|
|
460
|
+
└─ SÍ ──► [Iterar por cada route]
|
|
461
|
+
│
|
|
462
|
+
▼
|
|
463
|
+
[¿route es objeto?]
|
|
464
|
+
├─ NO ──► [Error: No es objeto]
|
|
465
|
+
│
|
|
466
|
+
▼
|
|
467
|
+
└─ SÍ ──► [¿Tiene path?]
|
|
468
|
+
├─ NO ──► [Error: Falta path]
|
|
469
|
+
│
|
|
470
|
+
▼
|
|
471
|
+
└─ SÍ ──► [¿Tiene method?]
|
|
472
|
+
├─ NO ──► [Error: Falta method]
|
|
473
|
+
│
|
|
474
|
+
▼
|
|
475
|
+
└─ SÍ ──► [¿Tiene controller?]
|
|
476
|
+
├─ NO ──► [Error: Falta controller]
|
|
477
|
+
│
|
|
478
|
+
▼
|
|
479
|
+
└─ SÍ ──► [¿Tiene handler?]
|
|
480
|
+
├─ NO ──► [Error: Falta handler]
|
|
481
|
+
│
|
|
482
|
+
▼
|
|
483
|
+
└─ SÍ ──► [¿contentType es string si existe?]
|
|
484
|
+
├─ NO ──► [Error: contentType inválido]
|
|
485
|
+
│
|
|
486
|
+
▼
|
|
487
|
+
└─ SÍ ──► [Siguiente ruta]
|
|
488
|
+
│
|
|
489
|
+
▼
|
|
490
|
+
[¿Más rutas?]
|
|
491
|
+
├─ SÍ ──► [Iterar]
|
|
492
|
+
└─ NO ──► [Validación exitosa]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
graph TD
|
|
2
|
+
A[HTTP Request] --> B[APIServer.handleRequest]
|
|
3
|
+
B --> C[Parse URL: pathname, query]
|
|
4
|
+
C --> D[Set req.query, req.params, req.body]
|
|
5
|
+
D --> E[Capture request body with size limit]
|
|
6
|
+
E --> F{bodySize > maxBodySize?}
|
|
7
|
+
F -->|YES| G[413 Request Too Large]
|
|
8
|
+
F -->|NO| H[End of data reception]
|
|
9
|
+
H --> I{Is JSON content-type?}
|
|
10
|
+
I -->|YES| J[Parse body as JSON]
|
|
11
|
+
I -->|NO| K[Continue with raw body]
|
|
12
|
+
J --> L{Is OPTIONS request?}
|
|
13
|
+
K --> L
|
|
14
|
+
L -->|YES| M[Execute CORS middleware]
|
|
15
|
+
L -->|NO| N[Find matching route: findRoute(method, pathname)]
|
|
16
|
+
M --> O{Has specific OPTIONS route?}
|
|
17
|
+
O -->|YES| P[Add route params and execute handler]
|
|
18
|
+
O -->|NO| Q[Send 204 No Content]
|
|
19
|
+
N --> R{Route found?}
|
|
20
|
+
R -->|NO| S[404 Not Found]
|
|
21
|
+
R -->|YES| T[Add route params to req.params]
|
|
22
|
+
T --> U[Execute registered middlewares in sequence]
|
|
23
|
+
U --> V{Did middleware respond?}
|
|
24
|
+
V -->|YES| W[End - Response sent]
|
|
25
|
+
V -->|NO| X[Execute route handler]
|
|
26
|
+
X --> Y{Is handler async?}
|
|
27
|
+
Y -->|YES| Z[Await handler execution]
|
|
28
|
+
Y -->|NO| AA[Execute handler synchronously]
|
|
29
|
+
Z --> AB[End - Response sent]
|
|
30
|
+
AA --> AB
|
|
31
|
+
P --> AC[End - Response sent]
|
|
32
|
+
|
|
33
|
+
BB[findRoute method] -.-> N
|
|
34
|
+
BB -.-> DD[Check exact route match]
|
|
35
|
+
DD --> EE{Exact match found?}
|
|
36
|
+
EE -->|YES| FF[Return {route, empty params}]
|
|
37
|
+
EE -->|NO| GG[Check parametrized routes]
|
|
38
|
+
GG --> HH[Iterate through routes]
|
|
39
|
+
HH --> II{Same HTTP method?}
|
|
40
|
+
II -->|NO| JJ[Check next route]
|
|
41
|
+
II -->|YES| KK[Convert route to regex: pathToRegex]
|
|
42
|
+
KK --> LL{Does pathname match routeRegex?}
|
|
43
|
+
LL -->|YES| MM[Extract params: extractParams]
|
|
44
|
+
LL -->|NO| JJ
|
|
45
|
+
MM --> NN[Return {route, extracted params}]
|
|
46
|
+
JJ --> OO{More routes to check?}
|
|
47
|
+
OO -->|YES| HH
|
|
48
|
+
OO -->|NO| PP[Return null - No route found]
|
|
49
|
+
|
|
50
|
+
QQ[Authentication Flow] -.-> RR[Authenticator.authenticate]
|
|
51
|
+
RR --> SS[Get client IP]
|
|
52
|
+
SS --> TT{Is IP blocked?}
|
|
53
|
+
TT -->|YES| UU[403 Access denied by firewall]
|
|
54
|
+
TT -->|NO| VV[Execute auth strategy]
|
|
55
|
+
VV --> WW{Authentication successful?}
|
|
56
|
+
WW -->|YES| XX[Log success, reset failed attempts, call next()]
|
|
57
|
+
WW -->|NO| YY[Increment failed attempts, log failure, 401 Unauthorized]
|
|
58
|
+
|
|
59
|
+
ZZ[Route Loading Flow] -.-> AAA[RouteLoader.loadRoutes]
|
|
60
|
+
AAA --> BBB[Validate file exists]
|
|
61
|
+
BBB --> CCC[Read and parse JSON routes]
|
|
62
|
+
CCC --> DDD[Validate routes structure]
|
|
63
|
+
DDD --> EEE[Iterate through each route]
|
|
64
|
+
EEE --> FFF[Check route properties: method, path, controller, handler]
|
|
65
|
+
FFF --> GGG[Load controller module]
|
|
66
|
+
GGG --> HHH[Get handler function from controller]
|
|
67
|
+
HHH --> III{Has custom contentType?}
|
|
68
|
+
III -->|YES| JJJ[Create wrapper with setHeader]
|
|
69
|
+
III -->|NO| KKK[Use handler directly]
|
|
70
|
+
KKK --> LLL{Has authentication?}
|
|
71
|
+
JJJ --> LLL
|
|
72
|
+
LLL -->|YES| MMM[Apply authentication middleware]
|
|
73
|
+
LLL -->|NO| NNN[Add route to server: server.addRoute]
|
|
74
|
+
MMM --> NNN
|
|
75
|
+
NNN --> OOO{More routes?}
|
|
76
|
+
OOO -->|YES| EEE
|
|
77
|
+
OOO -->|NO| PPP[Routes loaded successfully]
|
|
78
|
+
|
|
79
|
+
QQQ[Firewall Flow] -.-> RRR[Firewall.middleware]
|
|
80
|
+
RRR --> SSS[Get client IP]
|
|
81
|
+
SSS --> TTT{Is IP blocked?}
|
|
82
|
+
TTT -->|YES| UUU
|
|
83
|
+
TTT -->|NO| VVV[Check rules: checkRules(req)]
|
|
84
|
+
VVV --> WWW{Rule match found?}
|
|
85
|
+
WWW -->|YES| XXX{Action is block?}
|
|
86
|
+
WWW -->|NO| YYY[Allow request, call next()]
|
|
87
|
+
XXX -->|YES| ZZZ[Increment failed attempts, 403 Forbidden]
|
|
88
|
+
XXX -->|NO| AAAA[Continue with monitoring]
|
|
89
|
+
AAAA --> YYY
|
|
90
|
+
|
|
91
|
+
BBBB[View Engine Flow] -.-> CCCC[ViewEngine.render]
|
|
92
|
+
CCCC --> DDDD[Get view path: getViewPath]
|
|
93
|
+
DDDD --> EEEE{View file exists?}
|
|
94
|
+
EEEE -->|NO| FFFF[Error: View not found]
|
|
95
|
+
EEEE -->|YES| GGGG{Cache enabled and in cache?}
|
|
96
|
+
GGGG -->|YES| HHHH[Get from cache]
|
|
97
|
+
GGGG -->|NO| IIII[Read view content]
|
|
98
|
+
IIII --> JJJJ[Process includes: processIncludes]
|
|
99
|
+
JJJJ --> KKKK{Enable caching?}
|
|
100
|
+
KKKK -->|YES| LLLL[Save to cache]
|
|
101
|
+
KKKK -->|NO| MMMM[Continue without caching]
|
|
102
|
+
LLLL --> NNNN[Process template: processTemplate]
|
|
103
|
+
MMMM --> NNNN
|
|
104
|
+
NNNN --> OOOO[Process foreach loops]
|
|
105
|
+
OOOO --> PPPP[Process conditionals]
|
|
106
|
+
PPPP --> QQQQ[Replace variables and filters]
|
|
107
|
+
QQQQ --> RRRR[Return processed template]
|
|
108
|
+
|
|
109
|
+
SSSS[Session Flow] -.-> TTTT[SessionManager.middleware]
|
|
110
|
+
TTTT --> UUUU{Has session cookie?}
|
|
111
|
+
UUUU -->|NO| VVVV[Create new session]
|
|
112
|
+
UUUU -->|YES| WWWW[Validate existing session]
|
|
113
|
+
VVVV --> XXXX[Add req.session]
|
|
114
|
+
WWWW --> YYYY{Session valid?}
|
|
115
|
+
YYYY -->|NO| VVVV
|
|
116
|
+
YYYY -->|YES| ZZZZ[Update last activity]
|
|
117
|
+
ZZZZ --> XXXX
|
|
118
|
+
XXXX --> AAAAB[Call next()]
|
|
119
|
+
|
|
120
|
+
BBBB -.-> CCCC
|
|
121
|
+
QQ -.-> AAA
|
|
122
|
+
ZZ -.-> BBB
|
|
123
|
+
QQQ -.-> RRR
|
|
124
|
+
BBBB -.-> CCCC
|