jerkjs 2.0.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/LICENSE +200 -0
- package/README.md +171 -0
- package/doc/EXTENSION_MANUAL.md +958 -0
- package/doc/FIREWALL_MANUAL.md +419 -0
- package/doc/HOOKS_REFERENCE_IMPROVED.md +599 -0
- package/doc/MANUAL_API_SDK.md +539 -0
- package/doc/MANUAL_MVC.md +397 -0
- package/doc/MARIADB_TOKENS_IMPLEMENTATION.md +113 -0
- package/doc/MIDDLEWARE_MANUAL.md +521 -0
- package/doc/OAUTH2_GOOGLE_MANUAL.md +408 -0
- package/doc/frontend-and-sessions.md +356 -0
- package/examples/advanced/controllers/productController.js +64 -0
- package/examples/advanced/controllers/userController.js +85 -0
- package/examples/advanced/routes.json +51 -0
- package/examples/advanced_example.js +93 -0
- package/examples/basic/controllers/userController.js +85 -0
- package/examples/basic_example.js +72 -0
- package/examples/frontend/README.md +71 -0
- package/examples/frontend/app.js +71 -0
- package/examples/frontend/controllers/apiController.js +39 -0
- package/examples/frontend/controllers/authController.js +220 -0
- package/examples/frontend/controllers/formController.js +47 -0
- package/examples/frontend/controllers/messageController.js +96 -0
- package/examples/frontend/controllers/pageController.js +178 -0
- package/examples/frontend/controllers/staticController.js +167 -0
- package/examples/frontend/routes.json +90 -0
- package/examples/mvc_example/app.js +138 -0
- package/examples/mvc_example/views/home/index.html +26 -0
- package/examples/mvc_example/views/home/simple.html +3 -0
- package/examples/mvc_example/views/layout.html +23 -0
- package/examples/mvc_example/views/test.html +3 -0
- package/examples/mvc_example/views/user/invalid.html +6 -0
- package/examples/mvc_example/views/user/list.html +36 -0
- package/examples/mvc_example/views/user/notfound.html +6 -0
- package/examples/mvc_example/views/user/profile.html +11 -0
- package/examples/mvc_routes_example/app.js +34 -0
- package/examples/mvc_routes_example/controllers/mainController.js +27 -0
- package/examples/mvc_routes_example/controllers/productController.js +47 -0
- package/examples/mvc_routes_example/controllers/userController.js +76 -0
- package/examples/mvc_routes_example/routes.json +30 -0
- package/examples/mvc_routes_example/views/layout.html +31 -0
- package/examples/mvc_routes_example/views/main/index.html +11 -0
- package/examples/mvc_routes_example/views/product/catalog.html +24 -0
- package/examples/mvc_routes_example/views/user/invalid.html +6 -0
- package/examples/mvc_routes_example/views/user/list.html +40 -0
- package/examples/mvc_routes_example/views/user/notfound.html +6 -0
- package/examples/mvc_routes_example/views/user/profile.html +18 -0
- package/examples/public/README.md +92 -0
- package/examples/public/app.js +72 -0
- package/examples/public/controllers/healthController.js +20 -0
- package/examples/public/controllers/mainController.js +22 -0
- package/examples/public/controllers/userController.js +139 -0
- package/examples/public/routes.json +51 -0
- package/examples/v2/README.md +72 -0
- package/examples/v2/app.js +74 -0
- package/examples/v2/app_fixed.js +74 -0
- package/examples/v2/controllers/authController.js +64 -0
- package/examples/v2/controllers/mainController.js +24 -0
- package/examples/v2/controllers/protectedController.js +12 -0
- package/examples/v2/controllers/userController.js +16 -0
- package/examples/v2/package.json +27 -0
- package/examples/v2/routes.json +30 -0
- package/examples/v2/test_api.sh +47 -0
- package/examples/v2/tokens_example.sqlite +0 -0
- package/examples/v2.1_firewall_demo/README.md +113 -0
- package/examples/v2.1_firewall_demo/app.js +182 -0
- package/examples/v2.1_firewall_demo/package.json +27 -0
- package/examples/v2.1_hooks_demo/README.md +85 -0
- package/examples/v2.1_hooks_demo/app.js +101 -0
- package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
- package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
- package/examples/v2.1_hooks_demo/package.json +27 -0
- package/examples/v2.1_hooks_demo/routes.json +16 -0
- package/examples/v2.1_openapi_demo/README.md +82 -0
- package/examples/v2.1_openapi_demo/app.js +296 -0
- package/examples/v2.1_openapi_demo/package.json +26 -0
- package/examples/v2_cors/README.md +82 -0
- package/examples/v2_cors/app.js +108 -0
- package/examples/v2_cors/package.json +23 -0
- package/examples/v2_json_auth/README.md +83 -0
- package/examples/v2_json_auth/app.js +72 -0
- package/examples/v2_json_auth/controllers/authController.js +67 -0
- package/examples/v2_json_auth/controllers/mainController.js +16 -0
- package/examples/v2_json_auth/controllers/protectedController.js +12 -0
- package/examples/v2_json_auth/controllers/tokenController.js +28 -0
- package/examples/v2_json_auth/controllers/userController.js +15 -0
- package/examples/v2_json_auth/package.json +26 -0
- package/examples/v2_json_auth/routes.json +37 -0
- package/examples/v2_json_auth/tokens.json +20 -0
- package/examples/v2_mariadb_auth/README.md +94 -0
- package/examples/v2_mariadb_auth/app.js +81 -0
- package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
- package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
- package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
- package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
- package/examples/v2_mariadb_auth/package.json +27 -0
- package/examples/v2_mariadb_auth/routes.json +37 -0
- package/examples/v2_no_auth/README.md +75 -0
- package/examples/v2_no_auth/app.js +72 -0
- package/examples/v2_no_auth/controllers/healthController.js +14 -0
- package/examples/v2_no_auth/controllers/mainController.js +19 -0
- package/examples/v2_no_auth/controllers/productController.js +31 -0
- package/examples/v2_no_auth/controllers/publicController.js +16 -0
- package/examples/v2_no_auth/package.json +22 -0
- package/examples/v2_no_auth/routes.json +37 -0
- package/examples/v2_oauth/README.md +70 -0
- package/examples/v2_oauth/app.js +90 -0
- package/examples/v2_oauth/controllers/mainController.js +45 -0
- package/examples/v2_oauth/controllers/oauthController.js +247 -0
- package/examples/v2_oauth/controllers/protectedController.js +13 -0
- package/examples/v2_oauth/controllers/userController.js +17 -0
- package/examples/v2_oauth/package.json +26 -0
- package/examples/v2_oauth/routes.json +44 -0
- package/examples/v2_openapi/README.md +77 -0
- package/examples/v2_openapi/app.js +222 -0
- package/examples/v2_openapi/controllers/authController.js +52 -0
- package/examples/v2_openapi/controllers/mainController.js +26 -0
- package/examples/v2_openapi/controllers/productController.js +17 -0
- package/examples/v2_openapi/controllers/userController.js +27 -0
- package/examples/v2_openapi/package.json +26 -0
- package/examples/v2_openapi/routes.json +37 -0
- package/generate_token.js +10 -0
- package/index.js +85 -0
- package/jerk.jpg +0 -0
- package/lib/core/handler.js +86 -0
- package/lib/core/hooks.js +224 -0
- package/lib/core/router.js +204 -0
- package/lib/core/securityEnhancedServer.js +752 -0
- package/lib/core/server.js +369 -0
- package/lib/loader/controllerLoader.js +175 -0
- package/lib/loader/routeLoader.js +341 -0
- package/lib/middleware/auditLogger.js +208 -0
- package/lib/middleware/authenticator.js +565 -0
- package/lib/middleware/compressor.js +218 -0
- package/lib/middleware/cors.js +135 -0
- package/lib/middleware/firewall.js +443 -0
- package/lib/middleware/rateLimiter.js +210 -0
- package/lib/middleware/session.js +301 -0
- package/lib/middleware/validator.js +193 -0
- package/lib/mvc/controllerBase.js +207 -0
- package/lib/mvc/viewEngine.js +752 -0
- package/lib/utils/configParser.js +223 -0
- package/lib/utils/logger.js +145 -0
- package/lib/utils/mariadbTokenAdapter.js +226 -0
- package/lib/utils/openapiGenerator.js +140 -0
- package/lib/utils/sqliteTokenAdapter.js +224 -0
- package/lib/utils/tokenManager.js +254 -0
- package/package.json +47 -0
- package/v2examplle/v2_json_auth/README.md +83 -0
- package/v2examplle/v2_json_auth/app.js +72 -0
- package/v2examplle/v2_json_auth/controllers/authController.js +67 -0
- package/v2examplle/v2_json_auth/controllers/mainController.js +16 -0
- package/v2examplle/v2_json_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_json_auth/controllers/tokenController.js +28 -0
- package/v2examplle/v2_json_auth/controllers/userController.js +15 -0
- package/v2examplle/v2_json_auth/package.json +26 -0
- package/v2examplle/v2_json_auth/routes.json +37 -0
- package/v2examplle/v2_json_auth/tokens.json +20 -0
- package/v2examplle/v2_mariadb_auth/README.md +94 -0
- package/v2examplle/v2_mariadb_auth/app.js +81 -0
- package/v2examplle/v2_mariadb_auth/controllers/authController.js +95 -0
- package/v2examplle/v2_mariadb_auth/controllers/mainController.js +31 -0
- package/v2examplle/v2_mariadb_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_mariadb_auth/controllers/userController.js +17 -0
- package/v2examplle/v2_mariadb_auth/package.json +27 -0
- package/v2examplle/v2_mariadb_auth/routes.json +37 -0
- package/v2examplle/v2_sqlite_auth/README.md +72 -0
- package/v2examplle/v2_sqlite_auth/app.js +74 -0
- package/v2examplle/v2_sqlite_auth/app_fixed.js +74 -0
- package/v2examplle/v2_sqlite_auth/controllers/authController.js +64 -0
- package/v2examplle/v2_sqlite_auth/controllers/mainController.js +24 -0
- package/v2examplle/v2_sqlite_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_sqlite_auth/controllers/userController.js +16 -0
- package/v2examplle/v2_sqlite_auth/package.json +27 -0
- package/v2examplle/v2_sqlite_auth/routes.json +30 -0
- package/v2examplle/v2_sqlite_auth/test_api.sh +47 -0
- package/v2examplle/v2_sqlite_auth/tokens_example.sqlite +0 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# Manual de Creación de Middleware para API SDK Framework
|
|
2
|
+
|
|
3
|
+
Visita nuestra página web: https://jerk.page.gd/
|
|
4
|
+
Repositorio oficial: https://gitlab.com/bytedogssyndicate1/jerk/
|
|
5
|
+
|
|
6
|
+
## Tabla de Contenidos
|
|
7
|
+
|
|
8
|
+
1. [Introducción al Middleware](#introducción-al-middleware)
|
|
9
|
+
2. [Patrones de Middleware](#patrones-de-middleware)
|
|
10
|
+
3. [Guía de Implementación](#guía-de-implementación)
|
|
11
|
+
4. [Ejemplo Completo: Middleware de Auditoría](#ejemplo-completo-middleware-de-auditoría)
|
|
12
|
+
5. [Pruebas y Validación](#pruebas-y-validación)
|
|
13
|
+
6. [Integración con el Framework](#integración-con-el-framework)
|
|
14
|
+
|
|
15
|
+
## Introducción al Middleware
|
|
16
|
+
|
|
17
|
+
El middleware en el API SDK Framework es una función que se ejecuta en el pipeline de procesamiento de solicitudes HTTP. Actúa como intermediario entre la solicitud entrante y el handler final, permitiendo modificar la solicitud, la respuesta, o incluso detener el flujo de ejecución.
|
|
18
|
+
|
|
19
|
+
### Características del Middleware
|
|
20
|
+
|
|
21
|
+
- **Secuencial**: Se ejecutan en el orden en que se registran
|
|
22
|
+
- **Interceptable**: Pueden modificar `req` y `res` antes de pasar al siguiente
|
|
23
|
+
- **Terminable**: Pueden enviar respuesta y detener el flujo
|
|
24
|
+
- **Flexible**: Pueden aplicarse globalmente o a rutas específicas
|
|
25
|
+
|
|
26
|
+
### Firma del Middleware
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
function middleware(req, res, next) {
|
|
30
|
+
// Lógica del middleware
|
|
31
|
+
next(); // Continuar con el siguiente middleware
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Patrones de Middleware
|
|
36
|
+
|
|
37
|
+
### 1. Middleware de Logging
|
|
38
|
+
|
|
39
|
+
Registra información sobre las solicitudes entrantes.
|
|
40
|
+
|
|
41
|
+
### 2. Middleware de Autenticación
|
|
42
|
+
|
|
43
|
+
Verifica credenciales antes de permitir el acceso.
|
|
44
|
+
|
|
45
|
+
### 3. Middleware de Validación
|
|
46
|
+
|
|
47
|
+
Valida datos de entrada antes de procesarlos.
|
|
48
|
+
|
|
49
|
+
### 4. Middleware de Seguridad
|
|
50
|
+
|
|
51
|
+
Aplica medidas de seguridad como CORS, Rate Limiting, etc.
|
|
52
|
+
|
|
53
|
+
### 5. Middleware de Transformación
|
|
54
|
+
|
|
55
|
+
Modifica la solicitud o respuesta antes de procesarla.
|
|
56
|
+
|
|
57
|
+
## Guía de Implementación
|
|
58
|
+
|
|
59
|
+
### Paso 1: Definir el Propósito
|
|
60
|
+
|
|
61
|
+
Antes de crear cualquier middleware, define claramente:
|
|
62
|
+
|
|
63
|
+
1. **¿Qué problema resolverá?**
|
|
64
|
+
2. **¿En qué punto del pipeline se ejecutará?**
|
|
65
|
+
3. **¿Qué datos necesita procesar?**
|
|
66
|
+
4. **¿Qué efectos secundarios tendrá?**
|
|
67
|
+
|
|
68
|
+
### Paso 2: Implementar la Función Base
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
function miMiddleware(opciones = {}) {
|
|
72
|
+
return (req, res, next) => {
|
|
73
|
+
// Lógica del middleware
|
|
74
|
+
next();
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Paso 3: Manejar Casos Especiales
|
|
80
|
+
|
|
81
|
+
Considera casos como:
|
|
82
|
+
- Solicitudes que deben ser rechazadas
|
|
83
|
+
- Solicitudes que requieren transformación
|
|
84
|
+
- Solicitudes que deben ser registradas
|
|
85
|
+
- Errores durante el procesamiento
|
|
86
|
+
|
|
87
|
+
### Paso 4: Asegurar la Seguridad
|
|
88
|
+
|
|
89
|
+
- Validar entradas
|
|
90
|
+
- Sanitizar datos
|
|
91
|
+
- Aplicar límites de seguridad
|
|
92
|
+
- Registrar actividades sospechosas
|
|
93
|
+
|
|
94
|
+
## Ejemplo Completo: Middleware de Auditoría
|
|
95
|
+
|
|
96
|
+
Vamos a crear un middleware de auditoría que registre todas las actividades de los usuarios:
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
// lib/middleware/auditLogger.js
|
|
100
|
+
const fs = require('fs');
|
|
101
|
+
const path = require('path');
|
|
102
|
+
|
|
103
|
+
class AuditLogger {
|
|
104
|
+
/**
|
|
105
|
+
* Constructor del middleware de auditoría
|
|
106
|
+
* @param {Object} options - Opciones de configuración
|
|
107
|
+
* @param {string} options.logFile - Ruta al archivo de logs
|
|
108
|
+
* @param {Array} options.events - Eventos a auditar
|
|
109
|
+
* @param {Function} options.filter - Función para filtrar solicitudes
|
|
110
|
+
* @param {boolean} options.includeBody - Incluir cuerpo de la solicitud
|
|
111
|
+
* @param {boolean} options.includeHeaders - Incluir headers
|
|
112
|
+
*/
|
|
113
|
+
constructor(options = {}) {
|
|
114
|
+
this.logFile = options.logFile || './audit.log';
|
|
115
|
+
this.events = options.events || ['request', 'response', 'error'];
|
|
116
|
+
this.filter = options.filter || (() => true);
|
|
117
|
+
this.includeBody = options.includeBody !== false;
|
|
118
|
+
this.includeHeaders = options.includeHeaders !== false;
|
|
119
|
+
this.logger = options.logger || console;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Middleware de auditoría
|
|
124
|
+
* @returns {Function} - Middleware de auditoría
|
|
125
|
+
*/
|
|
126
|
+
middleware() {
|
|
127
|
+
return (req, res, next) => {
|
|
128
|
+
// Verificar si la solicitud debe ser auditada
|
|
129
|
+
if (!this.filter(req)) {
|
|
130
|
+
next();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const startTime = Date.now();
|
|
135
|
+
const requestId = this.generateRequestId();
|
|
136
|
+
|
|
137
|
+
// Registrar la solicitud entrante
|
|
138
|
+
this.logRequest(req, requestId);
|
|
139
|
+
|
|
140
|
+
// Capturar la respuesta original para registrarla
|
|
141
|
+
const originalEnd = res.end;
|
|
142
|
+
res.end = (chunk, encoding) => {
|
|
143
|
+
const duration = Date.now() - startTime;
|
|
144
|
+
|
|
145
|
+
// Registrar la respuesta
|
|
146
|
+
this.logResponse(req, res, chunk, duration, requestId);
|
|
147
|
+
|
|
148
|
+
// Llamar al método original
|
|
149
|
+
originalEnd.call(res, chunk, encoding);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Capturar errores para auditarlos
|
|
153
|
+
const originalOnError = req.connection && req.connection.onerror;
|
|
154
|
+
req.connection.onerror = (err) => {
|
|
155
|
+
this.logError(req, err, requestId);
|
|
156
|
+
if (originalOnError) originalOnError.call(req.connection, err);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
next();
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Genera un ID único para la solicitud
|
|
165
|
+
* @returns {string} - ID único de solicitud
|
|
166
|
+
*/
|
|
167
|
+
generateRequestId() {
|
|
168
|
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Registra la solicitud entrante
|
|
173
|
+
* @param {Object} req - Objeto de solicitud
|
|
174
|
+
* @param {string} requestId - ID de la solicitud
|
|
175
|
+
*/
|
|
176
|
+
logRequest(req, requestId) {
|
|
177
|
+
if (!this.events.includes('request')) return;
|
|
178
|
+
|
|
179
|
+
const logEntry = {
|
|
180
|
+
timestamp: new Date().toISOString(),
|
|
181
|
+
event: 'request',
|
|
182
|
+
requestId,
|
|
183
|
+
method: req.method,
|
|
184
|
+
url: req.url,
|
|
185
|
+
ip: this.getClientIP(req),
|
|
186
|
+
userAgent: req.headers['user-agent'],
|
|
187
|
+
headers: this.includeHeaders ? req.headers : undefined,
|
|
188
|
+
body: this.includeBody ? req.body : undefined
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
this.writeLog(logEntry);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Registra la respuesta saliente
|
|
196
|
+
* @param {Object} req - Objeto de solicitud
|
|
197
|
+
* @param {Object} res - Objeto de respuesta
|
|
198
|
+
* @param {any} chunk - Cuerpo de la respuesta
|
|
199
|
+
* @param {number} duration - Duración de la solicitud
|
|
200
|
+
* @param {string} requestId - ID de la solicitud
|
|
201
|
+
*/
|
|
202
|
+
logResponse(req, res, chunk, duration, requestId) {
|
|
203
|
+
if (!this.events.includes('response')) return;
|
|
204
|
+
|
|
205
|
+
const logEntry = {
|
|
206
|
+
timestamp: new Date().toISOString(),
|
|
207
|
+
event: 'response',
|
|
208
|
+
requestId,
|
|
209
|
+
method: req.method,
|
|
210
|
+
url: req.url,
|
|
211
|
+
statusCode: res.statusCode,
|
|
212
|
+
duration,
|
|
213
|
+
ip: this.getClientIP(req),
|
|
214
|
+
responseSize: chunk ? Buffer.byteLength(chunk) : 0
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
this.writeLog(logEntry);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Registra un error
|
|
222
|
+
* @param {Object} req - Objeto de solicitud
|
|
223
|
+
* @param {Error} error - Error ocurrido
|
|
224
|
+
* @param {string} requestId - ID de la solicitud
|
|
225
|
+
*/
|
|
226
|
+
logError(req, error, requestId) {
|
|
227
|
+
if (!this.events.includes('error')) return;
|
|
228
|
+
|
|
229
|
+
const logEntry = {
|
|
230
|
+
timestamp: new Date().toISOString(),
|
|
231
|
+
event: 'error',
|
|
232
|
+
requestId,
|
|
233
|
+
method: req.method,
|
|
234
|
+
url: req.url,
|
|
235
|
+
ip: this.getClientIP(req),
|
|
236
|
+
errorMessage: error.message,
|
|
237
|
+
stack: error.stack
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
this.writeLog(logEntry);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Obtiene la IP del cliente
|
|
245
|
+
* @param {Object} req - Objeto de solicitud
|
|
246
|
+
* @returns {string} - IP del cliente
|
|
247
|
+
*/
|
|
248
|
+
getClientIP(req) {
|
|
249
|
+
return req.headers['x-forwarded-for'] ||
|
|
250
|
+
req.connection.remoteAddress ||
|
|
251
|
+
req.socket.remoteAddress ||
|
|
252
|
+
(req.connection.socket ? req.connection.socket.remoteAddress : null);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Escribe una entrada de log
|
|
257
|
+
* @param {Object} entry - Entrada de log
|
|
258
|
+
*/
|
|
259
|
+
writeLog(entry) {
|
|
260
|
+
const logLine = JSON.stringify(entry) + '\n';
|
|
261
|
+
|
|
262
|
+
// Escribir al archivo de log
|
|
263
|
+
fs.appendFileSync(this.logFile, logLine);
|
|
264
|
+
|
|
265
|
+
// También escribir al logger si está disponible
|
|
266
|
+
if (this.logger) {
|
|
267
|
+
this.logger.info(`AUDIT: ${entry.event} - ${entry.method} ${entry.url} - ${entry.ip}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Limpia logs antiguos
|
|
273
|
+
* @param {number} days - Días a mantener
|
|
274
|
+
*/
|
|
275
|
+
cleanupOldLogs(days = 30) {
|
|
276
|
+
// Esta es una implementación básica
|
|
277
|
+
// En una implementación real, usarías librerías como 'winston' con transporte de archivos
|
|
278
|
+
console.log(`Limpiando logs anteriores a ${days} días...`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
module.exports = AuditLogger;
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Uso del Middleware de Auditoría
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
// examples/v2/audit_middleware_example.js
|
|
289
|
+
const { JERK, Logger } = require('../../index');
|
|
290
|
+
const AuditLogger = require('../../lib/middleware/auditLogger');
|
|
291
|
+
|
|
292
|
+
// Crear instancia del logger
|
|
293
|
+
const logger = new Logger({ level: 'info', timestamp: true });
|
|
294
|
+
|
|
295
|
+
logger.info('🔐 Iniciando ejemplo con middleware de auditoría');
|
|
296
|
+
|
|
297
|
+
// Crear instancia del servidor
|
|
298
|
+
const server = new JERK({
|
|
299
|
+
port: 8084,
|
|
300
|
+
host: 'localhost'
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Crear instancia del middleware de auditoría
|
|
304
|
+
const auditLogger = new AuditLogger({
|
|
305
|
+
logFile: './audit.log',
|
|
306
|
+
events: ['request', 'response', 'error'],
|
|
307
|
+
includeBody: true,
|
|
308
|
+
includeHeaders: false,
|
|
309
|
+
filter: (req) => {
|
|
310
|
+
// No auditar solicitudes a /health
|
|
311
|
+
return req.url !== '/health';
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Aplicar middleware de auditoría
|
|
316
|
+
server.use(auditLogger.middleware());
|
|
317
|
+
|
|
318
|
+
// Middleware de logging normal
|
|
319
|
+
server.use((req, res, next) => {
|
|
320
|
+
logger.info(`${req.method} ${req.url} - IP: ${req.connection.remoteAddress}`);
|
|
321
|
+
next();
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Rutas de ejemplo
|
|
325
|
+
server.addRoute('GET', '/', (req, res) => {
|
|
326
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
327
|
+
res.end(JSON.stringify({
|
|
328
|
+
message: 'API con middleware de auditoría',
|
|
329
|
+
timestamp: new Date().toISOString()
|
|
330
|
+
}));
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
server.addRoute('POST', '/api/users', (req, res) => {
|
|
334
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
335
|
+
res.end(JSON.stringify({
|
|
336
|
+
success: true,
|
|
337
|
+
message: 'Usuario creado',
|
|
338
|
+
data: req.body
|
|
339
|
+
}));
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
server.addRoute('GET', '/health', (req, res) => {
|
|
343
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
344
|
+
res.end(JSON.stringify({ status: 'healthy' }));
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
logger.info('✅ Rutas configuradas con middleware de auditoría');
|
|
348
|
+
|
|
349
|
+
// Iniciar el servidor
|
|
350
|
+
const httpServer = server.start();
|
|
351
|
+
|
|
352
|
+
logger.info('✅ Servidor iniciado en http://localhost:8084');
|
|
353
|
+
logger.info('📋 Endpoints disponibles:');
|
|
354
|
+
logger.info(' GET / - Página principal (auditable)');
|
|
355
|
+
logger.info(' POST /api/users - Crear usuario (auditable)');
|
|
356
|
+
logger.info(' GET /health - Salud del sistema (no auditado)');
|
|
357
|
+
|
|
358
|
+
logger.info('\n🔧 Comandos de prueba con curl:');
|
|
359
|
+
logger.info(' # Probar endpoint principal (será auditado):');
|
|
360
|
+
logger.info(' curl http://localhost:8084/');
|
|
361
|
+
logger.info('');
|
|
362
|
+
logger.info(' # Crear usuario (será auditado):');
|
|
363
|
+
logger.info(' curl -X POST http://localhost:8084/api/users \\');
|
|
364
|
+
logger.info(' -H "Content-Type: application/json" \\');
|
|
365
|
+
logger.info(' -d \'{"name":"Test User", "email":"test@example.com"}\'');
|
|
366
|
+
logger.info('');
|
|
367
|
+
logger.info(' # Verificar salud (no será auditado):');
|
|
368
|
+
logger.info(' curl http://localhost:8084/health');
|
|
369
|
+
|
|
370
|
+
logger.info('\n📊 Los eventos se registrarán en ./audit.log');
|
|
371
|
+
|
|
372
|
+
// Manejo de cierre
|
|
373
|
+
const gracefulShutdown = () => {
|
|
374
|
+
logger.info('🛑 Cerrando servidor...');
|
|
375
|
+
httpServer.close(() => {
|
|
376
|
+
logger.info('🔌 Servidor detenido');
|
|
377
|
+
process.exit(0);
|
|
378
|
+
});
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
382
|
+
process.on('SIGINT', gracefulShutdown);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Pruebas y Validación
|
|
386
|
+
|
|
387
|
+
### Prueba del Middleware de Auditoría
|
|
388
|
+
|
|
389
|
+
```javascript
|
|
390
|
+
// test_audit_middleware.js
|
|
391
|
+
const { JERK } = require('../index');
|
|
392
|
+
const AuditLogger = require('../lib/middleware/auditLogger');
|
|
393
|
+
const fs = require('fs');
|
|
394
|
+
const path = require('path');
|
|
395
|
+
|
|
396
|
+
async function testAuditMiddleware() {
|
|
397
|
+
console.log('🧪 Probando middleware de auditoría...\n');
|
|
398
|
+
|
|
399
|
+
// Crear servidor de prueba
|
|
400
|
+
const server = new JERK({ port: 9998 });
|
|
401
|
+
|
|
402
|
+
// Crear middleware de auditoría para pruebas
|
|
403
|
+
const auditLogger = new AuditLogger({
|
|
404
|
+
logFile: './test_audit.log',
|
|
405
|
+
events: ['request', 'response'],
|
|
406
|
+
includeBody: true
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Aplicar middleware
|
|
410
|
+
server.use(auditLogger.middleware());
|
|
411
|
+
|
|
412
|
+
// Agregar ruta de prueba
|
|
413
|
+
server.addRoute('GET', '/test', (req, res) => {
|
|
414
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
415
|
+
res.end(JSON.stringify({ message: 'OK' }));
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
server.addRoute('POST', '/test-post', (req, res) => {
|
|
419
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
420
|
+
res.end(JSON.stringify({ received: req.body }));
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
console.log('✅ Middleware de auditoría aplicado');
|
|
424
|
+
console.log('✅ Rutas de prueba configuradas');
|
|
425
|
+
|
|
426
|
+
// Iniciar servidor (en una implementación real, aquí haríamos solicitudes de prueba)
|
|
427
|
+
const httpServer = server.start();
|
|
428
|
+
|
|
429
|
+
console.log('✅ Servidor de prueba iniciado');
|
|
430
|
+
console.log('✅ El middleware de auditoría está funcionando');
|
|
431
|
+
console.log('✅ Las solicitudes se registrarán en test_audit.log');
|
|
432
|
+
|
|
433
|
+
// Detener servidor después de un tiempo
|
|
434
|
+
setTimeout(() => {
|
|
435
|
+
httpServer.close();
|
|
436
|
+
console.log('\n✅ Prueba completada');
|
|
437
|
+
console.log('📊 Revisa el archivo test_audit.log para ver los registros');
|
|
438
|
+
}, 2000);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Ejecutar prueba
|
|
442
|
+
testAuditMiddleware().catch(console.error);
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Integración con el Framework
|
|
446
|
+
|
|
447
|
+
### 1. Registro en el Punto de Entrada
|
|
448
|
+
|
|
449
|
+
```javascript
|
|
450
|
+
// Actualizar index.js para exportar el nuevo middleware
|
|
451
|
+
const AuditLogger = require('./lib/middleware/auditLogger');
|
|
452
|
+
|
|
453
|
+
module.exports = {
|
|
454
|
+
// ... otros componentes ...
|
|
455
|
+
AuditLogger // Exportar el nuevo middleware
|
|
456
|
+
};
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### 2. Ejemplos de Uso en Aplicaciones Reales
|
|
460
|
+
|
|
461
|
+
```javascript
|
|
462
|
+
// Ejemplo de uso en una aplicación real
|
|
463
|
+
const { APISDK, AuditLogger } = require('jerk');
|
|
464
|
+
|
|
465
|
+
const server = new JERK({ port: 3000 });
|
|
466
|
+
|
|
467
|
+
// Middleware de auditoría para eventos de seguridad
|
|
468
|
+
const securityAudit = new AuditLogger({
|
|
469
|
+
logFile: './security_audit.log',
|
|
470
|
+
events: ['request', 'error'],
|
|
471
|
+
filter: (req) => {
|
|
472
|
+
// Solo auditar endpoints sensibles
|
|
473
|
+
return req.url.startsWith('/api/admin') || req.url.startsWith('/api/users');
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
server.use(securityAudit.middleware());
|
|
478
|
+
|
|
479
|
+
// Middleware de auditoría general
|
|
480
|
+
const generalAudit = new AuditLogger({
|
|
481
|
+
logFile: './general_audit.log',
|
|
482
|
+
events: ['request', 'response']
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
server.use(generalAudit.middleware());
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Buenas Prácticas para Middleware
|
|
489
|
+
|
|
490
|
+
### 1. Rendimiento
|
|
491
|
+
- Minimizar operaciones costosas
|
|
492
|
+
- Usar caché cuando sea posible
|
|
493
|
+
- Evitar operaciones de bloqueo
|
|
494
|
+
|
|
495
|
+
### 2. Seguridad
|
|
496
|
+
- Validar entradas
|
|
497
|
+
- Sanitizar datos
|
|
498
|
+
- Aplicar límites de seguridad
|
|
499
|
+
- Registrar actividades sospechosas
|
|
500
|
+
|
|
501
|
+
### 3. Observabilidad
|
|
502
|
+
- Registrar adecuadamente
|
|
503
|
+
- Medir tiempos de ejecución
|
|
504
|
+
- Detectar anomalías
|
|
505
|
+
|
|
506
|
+
### 4. Mantenibilidad
|
|
507
|
+
- Código limpio y bien documentado
|
|
508
|
+
- Opciones configurables
|
|
509
|
+
- Manejo adecuado de errores
|
|
510
|
+
|
|
511
|
+
## Conclusión
|
|
512
|
+
|
|
513
|
+
El sistema de middleware del API SDK Framework es potente y flexible, permitiendo extender la funcionalidad del servidor de múltiples maneras. El ejemplo del middleware de auditoría demuestra cómo crear middleware complejo que puede:
|
|
514
|
+
|
|
515
|
+
- Registrar eventos de solicitud, respuesta y error
|
|
516
|
+
- Filtrar solicitudes según criterios personalizados
|
|
517
|
+
- Incluir o excluir información sensible
|
|
518
|
+
- Integrarse completamente con el sistema de logging del framework
|
|
519
|
+
- Ser configurado y reutilizado en diferentes aplicaciones
|
|
520
|
+
|
|
521
|
+
Este patrón puede aplicarse para crear cualquier tipo de middleware que necesites: autenticación, autorización, validación, transformación de datos, logging, métricas, etc.
|