jerkjs 2.1.2 → 2.1.3
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 +3 -1
- package/README.md +1 -1
- package/lib/middleware/compressor.js +257 -9
- package/package.json +1 -1
- package/standard/CompressionTestController.js +18 -0
- package/standard/routes.json +7 -0
- package/standard/server.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## v2.1.
|
|
3
|
+
## v2.1.3 - 17 de enero de 2026
|
|
4
4
|
|
|
5
5
|
### Nuevas características
|
|
6
6
|
|
|
7
|
+
- **Sistema de hooks/filters en middleware de compresión**: Se ha integrado completamente el sistema de hooks y filters en el middleware de compresión, permitiendo extender y personalizar el comportamiento de compresión en múltiples puntos del proceso (antes/después de la compresión, modificación de chunks, manejo de encabezados, etc.)
|
|
8
|
+
|
|
7
9
|
- **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
10
|
|
|
9
11
|
- **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).
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Middleware de compresión para el framework JERK
|
|
3
3
|
* Implementación del componente middleware/compressor.js
|
|
4
|
-
* JERK Framework v2.1.
|
|
4
|
+
* JERK Framework v2.1.3 - Con optimizaciones de eficiencia, corrección de errores y sistema de hooks/filters
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const zlib = require('zlib');
|
|
@@ -14,12 +14,14 @@ class Compressor {
|
|
|
14
14
|
* @param {number} options.threshold - Tamaño mínimo en bytes para comprimir
|
|
15
15
|
* @param {Object} options.gzipOptions - Opciones para compresión gzip
|
|
16
16
|
* @param {Object} options.deflateOptions - Opciones para compresión deflate
|
|
17
|
+
* @param {Object} options.hooks - Sistema de hooks para extensibilidad
|
|
17
18
|
*/
|
|
18
19
|
constructor(options = {}) {
|
|
19
20
|
this.encodings = options.encodings || ['gzip', 'deflate'];
|
|
20
21
|
this.threshold = options.threshold || 1024; // 1KB por defecto
|
|
21
22
|
this.gzipOptions = options.gzipOptions || {};
|
|
22
23
|
this.deflateOptions = options.deflateOptions || {};
|
|
24
|
+
this.hooks = options.hooks || null; // Sistema de hooks opcional para extensibilidad
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -37,7 +39,7 @@ class Compressor {
|
|
|
37
39
|
|
|
38
40
|
// Determinar el método de compresión preferido
|
|
39
41
|
let compressionMethod = null;
|
|
40
|
-
|
|
42
|
+
|
|
41
43
|
if (acceptEncoding.includes('gzip')) {
|
|
42
44
|
compressionMethod = 'gzip';
|
|
43
45
|
} else if (acceptEncoding.includes('deflate')) {
|
|
@@ -50,6 +52,11 @@ class Compressor {
|
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
// Permitir a los hooks modificar el método de compresión
|
|
56
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
57
|
+
compressionMethod = this.hooks.applyFilters('compressor_method', compressionMethod, req, res);
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
// Guardar el método original de res.end
|
|
54
61
|
const originalEnd = res.end;
|
|
55
62
|
const originalWriteHead = res.writeHead;
|
|
@@ -59,6 +66,10 @@ class Compressor {
|
|
|
59
66
|
|
|
60
67
|
// Sobrescribir res.write para capturar los chunks
|
|
61
68
|
res.write = (chunk, encoding) => {
|
|
69
|
+
// Permitir a los hooks interceptar los chunks antes de almacenarlos
|
|
70
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
71
|
+
chunk = this.hooks.applyFilters('compressor_chunk_before_store', chunk, req, res, encoding);
|
|
72
|
+
}
|
|
62
73
|
responseChunks.push(chunk);
|
|
63
74
|
};
|
|
64
75
|
|
|
@@ -66,16 +77,40 @@ class Compressor {
|
|
|
66
77
|
res.end = (chunk, encoding) => {
|
|
67
78
|
// Añadir el chunk final a los chunks si existe
|
|
68
79
|
if (chunk) {
|
|
80
|
+
// Permitir a los hooks interceptar el chunk final antes de almacenarlo
|
|
81
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
82
|
+
chunk = this.hooks.applyFilters('compressor_final_chunk_before_store', chunk, req, res, encoding);
|
|
83
|
+
}
|
|
69
84
|
responseChunks.push(chunk);
|
|
70
85
|
}
|
|
71
86
|
|
|
72
87
|
// Concatenar todos los chunks una sola vez
|
|
73
|
-
|
|
88
|
+
let responseBody = Buffer.concat(responseChunks.map(c =>
|
|
74
89
|
typeof c === 'string' ? Buffer.from(c, encoding) : c
|
|
75
90
|
)).toString();
|
|
76
91
|
|
|
92
|
+
// Permitir a los hooks modificar el cuerpo de la respuesta antes de evaluar el umbral
|
|
93
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
94
|
+
responseBody = this.hooks.applyFilters('compressor_response_body_before_threshold_check', responseBody, req, res);
|
|
95
|
+
}
|
|
96
|
+
|
|
77
97
|
// Si el cuerpo es menor que el umbral, enviar sin comprimir
|
|
78
98
|
if (Buffer.byteLength(responseBody) < this.threshold) {
|
|
99
|
+
// Permitir a los hooks modificar el comportamiento cuando no se comprime
|
|
100
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
101
|
+
const shouldCompress = this.hooks.applyFilters('compressor_should_compress', false, responseBody, req, res, this.threshold);
|
|
102
|
+
if (shouldCompress) {
|
|
103
|
+
// Si un hook determina que debería comprimirse, proseguir con la compresión
|
|
104
|
+
this._performCompression(req, res, originalEnd, originalWriteHead, responseBody, compressionMethod);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Permitir a los hooks modificar el comportamiento cuando no se comprime
|
|
110
|
+
if (this.hooks && this.hooks.doAction) {
|
|
111
|
+
this.hooks.doAction('compressor_skip_compression', req, res, responseBody, this.threshold);
|
|
112
|
+
}
|
|
113
|
+
|
|
79
114
|
// Solo establecer encabezados si no se han enviado aún
|
|
80
115
|
if (!res.headersSent) {
|
|
81
116
|
res.removeHeader('Content-Encoding'); // Asegurar que no haya encabezado de codificación
|
|
@@ -85,6 +120,11 @@ class Compressor {
|
|
|
85
120
|
return;
|
|
86
121
|
}
|
|
87
122
|
|
|
123
|
+
// Permitir a los hooks modificar el comportamiento cuando se va a comprimir
|
|
124
|
+
if (this.hooks && this.hooks.doAction) {
|
|
125
|
+
this.hooks.doAction('compressor_before_compression', req, res, responseBody, compressionMethod);
|
|
126
|
+
}
|
|
127
|
+
|
|
88
128
|
// Aplicar compresión según el método seleccionado
|
|
89
129
|
let compressedBody;
|
|
90
130
|
let compressPromise;
|
|
@@ -95,6 +135,10 @@ class Compressor {
|
|
|
95
135
|
if (err) {
|
|
96
136
|
reject(err);
|
|
97
137
|
} else {
|
|
138
|
+
// Permitir a los hooks modificar el buffer comprimido
|
|
139
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
140
|
+
buffer = this.hooks.applyFilters('compressor_after_gzip', buffer, req, res, responseBody);
|
|
141
|
+
}
|
|
98
142
|
resolve(buffer);
|
|
99
143
|
}
|
|
100
144
|
});
|
|
@@ -105,6 +149,10 @@ class Compressor {
|
|
|
105
149
|
if (err) {
|
|
106
150
|
reject(err);
|
|
107
151
|
} else {
|
|
152
|
+
// Permitir a los hooks modificar el buffer comprimido
|
|
153
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
154
|
+
buffer = this.hooks.applyFilters('compressor_after_deflate', buffer, req, res, responseBody);
|
|
155
|
+
}
|
|
108
156
|
resolve(buffer);
|
|
109
157
|
}
|
|
110
158
|
});
|
|
@@ -114,21 +162,46 @@ class Compressor {
|
|
|
114
162
|
// Esperar a que se complete la compresión y enviar la respuesta
|
|
115
163
|
compressPromise
|
|
116
164
|
.then(compressed => {
|
|
165
|
+
// Permitir a los hooks modificar el cuerpo comprimido antes de enviar
|
|
166
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
167
|
+
compressed = this.hooks.applyFilters('compressor_before_send', compressed, req, res, compressionMethod);
|
|
168
|
+
}
|
|
169
|
+
|
|
117
170
|
// Solo establecer encabezados si no se han enviado aún
|
|
118
171
|
if (!res.headersSent) {
|
|
119
172
|
// Establecer encabezados apropiados
|
|
120
173
|
res.setHeader('Content-Encoding', compressionMethod);
|
|
121
174
|
res.removeHeader('Content-Length'); // Eliminar Content-Length original
|
|
122
175
|
|
|
176
|
+
// Permitir a los hooks modificar los encabezados
|
|
177
|
+
if (this.hooks && this.hooks.doAction) {
|
|
178
|
+
this.hooks.doAction('compressor_before_headers_sent', req, res, compressionMethod);
|
|
179
|
+
}
|
|
180
|
+
|
|
123
181
|
// Llamar al writeHead original
|
|
124
182
|
originalWriteHead.call(res);
|
|
125
183
|
}
|
|
126
184
|
|
|
185
|
+
// Permitir a los hooks modificar el comportamiento antes de enviar la respuesta
|
|
186
|
+
if (this.hooks && this.hooks.doAction) {
|
|
187
|
+
this.hooks.doAction('compressor_before_response_sent', req, res, compressed, compressionMethod);
|
|
188
|
+
}
|
|
189
|
+
|
|
127
190
|
// Enviar el cuerpo comprimido
|
|
128
191
|
originalEnd.call(res, compressed, encoding);
|
|
192
|
+
|
|
193
|
+
// Permitir a los hooks actuar después de enviar la respuesta
|
|
194
|
+
if (this.hooks && this.hooks.doAction) {
|
|
195
|
+
this.hooks.doAction('compressor_after_response_sent', req, res, compressed, compressionMethod);
|
|
196
|
+
}
|
|
129
197
|
})
|
|
130
198
|
.catch(err => {
|
|
131
199
|
console.error('Error comprimiendo la respuesta:', err);
|
|
200
|
+
// Permitir a los hooks manejar el error de compresión
|
|
201
|
+
if (this.hooks && this.hooks.doAction) {
|
|
202
|
+
this.hooks.doAction('compressor_error_during_compression', err, req, res, responseBody, compressionMethod);
|
|
203
|
+
}
|
|
204
|
+
|
|
132
205
|
// Si ocurre un error, enviar sin comprimir
|
|
133
206
|
if (!res.headersSent) {
|
|
134
207
|
res.removeHeader('Content-Encoding');
|
|
@@ -152,13 +225,18 @@ class Compressor {
|
|
|
152
225
|
jsonOnly() {
|
|
153
226
|
return (req, res, next) => {
|
|
154
227
|
const originalSend = res.send; // Suponiendo que hay un método send
|
|
155
|
-
|
|
228
|
+
|
|
156
229
|
res.send = (data) => {
|
|
157
230
|
// Verificar si el tipo de contenido es JSON
|
|
158
231
|
const contentType = res.getHeader('Content-Type');
|
|
159
232
|
if (contentType && contentType.includes('application/json')) {
|
|
160
233
|
// Convertir a string si no lo es
|
|
161
|
-
|
|
234
|
+
let jsonString = typeof data === 'string' ? data : JSON.stringify(data);
|
|
235
|
+
|
|
236
|
+
// Permitir a los hooks modificar el JSON antes de la compresión
|
|
237
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
238
|
+
jsonString = this.hooks.applyFilters('compressor_json_before_compression', jsonString, req, res, data);
|
|
239
|
+
}
|
|
162
240
|
|
|
163
241
|
// Continuar con la lógica de compresión
|
|
164
242
|
// (similar a la implementación en middleware())
|
|
@@ -176,6 +254,11 @@ class Compressor {
|
|
|
176
254
|
compressionMethod = 'deflate';
|
|
177
255
|
}
|
|
178
256
|
|
|
257
|
+
// Permitir a los hooks modificar el método de compresión para JSON
|
|
258
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
259
|
+
compressionMethod = this.hooks.applyFilters('compressor_json_method', compressionMethod, req, res);
|
|
260
|
+
}
|
|
261
|
+
|
|
179
262
|
if (!compressionMethod || !this.encodings.includes(compressionMethod)) {
|
|
180
263
|
res.setHeader('Content-Type', 'application/json');
|
|
181
264
|
originalSend.call(res, jsonString);
|
|
@@ -183,44 +266,112 @@ class Compressor {
|
|
|
183
266
|
}
|
|
184
267
|
|
|
185
268
|
if (Buffer.byteLength(jsonString) < this.threshold) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
269
|
+
// Permitir a los hooks modificar el comportamiento cuando no se comprime JSON
|
|
270
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
271
|
+
const shouldCompressJSON = this.hooks.applyFilters('compressor_json_should_compress', false, jsonString, req, res, this.threshold);
|
|
272
|
+
if (!shouldCompressJSON) {
|
|
273
|
+
res.setHeader('Content-Type', 'application/json');
|
|
274
|
+
res.removeHeader('Content-Encoding');
|
|
275
|
+
originalSend.call(res, jsonString);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
res.setHeader('Content-Type', 'application/json');
|
|
280
|
+
res.removeHeader('Content-Encoding');
|
|
281
|
+
originalSend.call(res, jsonString);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Permitir a los hooks modificar el comportamiento antes de comprimir JSON
|
|
287
|
+
if (this.hooks && this.hooks.doAction) {
|
|
288
|
+
this.hooks.doAction('compressor_json_before_compression', req, res, jsonString, compressionMethod);
|
|
190
289
|
}
|
|
191
290
|
|
|
192
291
|
if (compressionMethod === 'gzip') {
|
|
193
292
|
zlib.gzip(jsonString, this.gzipOptions, (err, compressed) => {
|
|
194
293
|
if (err) {
|
|
195
294
|
console.error('Error comprimiendo JSON:', err);
|
|
295
|
+
// Permitir a los hooks manejar el error de compresión JSON
|
|
296
|
+
if (this.hooks && this.hooks.doAction) {
|
|
297
|
+
this.hooks.doAction('compressor_json_error_during_compression', err, req, res, jsonString, compressionMethod);
|
|
298
|
+
}
|
|
299
|
+
|
|
196
300
|
if (!res.headersSent) {
|
|
197
301
|
res.setHeader('Content-Type', 'application/json');
|
|
198
302
|
}
|
|
199
303
|
originalSend.call(res, jsonString);
|
|
200
304
|
} else {
|
|
305
|
+
// Permitir a los hooks modificar el JSON comprimido
|
|
306
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
307
|
+
compressed = this.hooks.applyFilters('compressor_json_after_gzip', compressed, req, res, jsonString);
|
|
308
|
+
}
|
|
309
|
+
|
|
201
310
|
if (!res.headersSent) {
|
|
202
311
|
res.setHeader('Content-Encoding', compressionMethod);
|
|
203
312
|
res.removeHeader('Content-Length');
|
|
204
313
|
res.setHeader('Content-Type', 'application/json');
|
|
314
|
+
|
|
315
|
+
// Permitir a los hooks modificar los encabezados antes de enviar JSON
|
|
316
|
+
if (this.hooks && this.hooks.doAction) {
|
|
317
|
+
this.hooks.doAction('compressor_json_before_headers_sent', req, res, compressionMethod);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Permitir a los hooks modificar el comportamiento antes de enviar JSON comprimido
|
|
322
|
+
if (this.hooks && this.hooks.doAction) {
|
|
323
|
+
this.hooks.doAction('compressor_json_before_send', req, res, compressed, compressionMethod);
|
|
205
324
|
}
|
|
325
|
+
|
|
206
326
|
originalSend.call(res, compressed);
|
|
327
|
+
|
|
328
|
+
// Permitir a los hooks actuar después de enviar JSON comprimido
|
|
329
|
+
if (this.hooks && this.hooks.doAction) {
|
|
330
|
+
this.hooks.doAction('compressor_json_after_send', req, res, compressed, compressionMethod);
|
|
331
|
+
}
|
|
207
332
|
}
|
|
208
333
|
});
|
|
209
334
|
} else if (compressionMethod === 'deflate') {
|
|
210
335
|
zlib.deflate(jsonString, this.deflateOptions, (err, compressed) => {
|
|
211
336
|
if (err) {
|
|
212
337
|
console.error('Error comprimiendo JSON:', err);
|
|
338
|
+
// Permitir a los hooks manejar el error de compresión JSON
|
|
339
|
+
if (this.hooks && this.hooks.doAction) {
|
|
340
|
+
this.hooks.doAction('compressor_json_error_during_compression', err, req, res, jsonString, compressionMethod);
|
|
341
|
+
}
|
|
342
|
+
|
|
213
343
|
if (!res.headersSent) {
|
|
214
344
|
res.setHeader('Content-Type', 'application/json');
|
|
215
345
|
}
|
|
216
346
|
originalSend.call(res, jsonString);
|
|
217
347
|
} else {
|
|
348
|
+
// Permitir a los hooks modificar el JSON comprimido
|
|
349
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
350
|
+
compressed = this.hooks.applyFilters('compressor_json_after_deflate', compressed, req, res, jsonString);
|
|
351
|
+
}
|
|
352
|
+
|
|
218
353
|
if (!res.headersSent) {
|
|
219
354
|
res.setHeader('Content-Encoding', compressionMethod);
|
|
220
355
|
res.removeHeader('Content-Length');
|
|
221
356
|
res.setHeader('Content-Type', 'application/json');
|
|
357
|
+
|
|
358
|
+
// Permitir a los hooks modificar los encabezados antes de enviar JSON
|
|
359
|
+
if (this.hooks && this.hooks.doAction) {
|
|
360
|
+
this.hooks.doAction('compressor_json_before_headers_sent', req, res, compressionMethod);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Permitir a los hooks modificar el comportamiento antes de enviar JSON comprimido
|
|
365
|
+
if (this.hooks && this.hooks.doAction) {
|
|
366
|
+
this.hooks.doAction('compressor_json_before_send', req, res, compressed, compressionMethod);
|
|
222
367
|
}
|
|
368
|
+
|
|
223
369
|
originalSend.call(res, compressed);
|
|
370
|
+
|
|
371
|
+
// Permitir a los hooks actuar después de enviar JSON comprimido
|
|
372
|
+
if (this.hooks && this.hooks.doAction) {
|
|
373
|
+
this.hooks.doAction('compressor_json_after_send', req, res, compressed, compressionMethod);
|
|
374
|
+
}
|
|
224
375
|
}
|
|
225
376
|
});
|
|
226
377
|
}
|
|
@@ -235,6 +386,103 @@ class Compressor {
|
|
|
235
386
|
}
|
|
236
387
|
};
|
|
237
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Método auxiliar para realizar la compresión
|
|
391
|
+
* @private
|
|
392
|
+
*/
|
|
393
|
+
_performCompression(req, res, originalEnd, originalWriteHead, responseBody, compressionMethod) {
|
|
394
|
+
const zlib = require('zlib');
|
|
395
|
+
|
|
396
|
+
// Permitir a los hooks modificar el comportamiento cuando se va a comprimir
|
|
397
|
+
if (this.hooks && this.hooks.doAction) {
|
|
398
|
+
this.hooks.doAction('compressor_before_compression', req, res, responseBody, compressionMethod);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Aplicar compresión según el método seleccionado
|
|
402
|
+
let compressedBody;
|
|
403
|
+
let compressPromise;
|
|
404
|
+
|
|
405
|
+
if (compressionMethod === 'gzip') {
|
|
406
|
+
compressPromise = new Promise((resolve, reject) => {
|
|
407
|
+
zlib.gzip(responseBody, this.gzipOptions, (err, buffer) => {
|
|
408
|
+
if (err) {
|
|
409
|
+
reject(err);
|
|
410
|
+
} else {
|
|
411
|
+
// Permitir a los hooks modificar el buffer comprimido
|
|
412
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
413
|
+
buffer = this.hooks.applyFilters('compressor_after_gzip', buffer, req, res, responseBody);
|
|
414
|
+
}
|
|
415
|
+
resolve(buffer);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
} else if (compressionMethod === 'deflate') {
|
|
420
|
+
compressPromise = new Promise((resolve, reject) => {
|
|
421
|
+
zlib.deflate(responseBody, this.deflateOptions, (err, buffer) => {
|
|
422
|
+
if (err) {
|
|
423
|
+
reject(err);
|
|
424
|
+
} else {
|
|
425
|
+
// Permitir a los hooks modificar el buffer comprimido
|
|
426
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
427
|
+
buffer = this.hooks.applyFilters('compressor_after_deflate', buffer, req, res, responseBody);
|
|
428
|
+
}
|
|
429
|
+
resolve(buffer);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Esperar a que se complete la compresión y enviar la respuesta
|
|
436
|
+
compressPromise
|
|
437
|
+
.then(compressed => {
|
|
438
|
+
// Permitir a los hooks modificar el cuerpo comprimido antes de enviar
|
|
439
|
+
if (this.hooks && this.hooks.applyFilters) {
|
|
440
|
+
compressed = this.hooks.applyFilters('compressor_before_send', compressed, req, res, compressionMethod);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Solo establecer encabezados si no se han enviado aún
|
|
444
|
+
if (!res.headersSent) {
|
|
445
|
+
// Establecer encabezados apropiados
|
|
446
|
+
res.setHeader('Content-Encoding', compressionMethod);
|
|
447
|
+
res.removeHeader('Content-Length'); // Eliminar Content-Length original
|
|
448
|
+
|
|
449
|
+
// Permitir a los hooks modificar los encabezados
|
|
450
|
+
if (this.hooks && this.hooks.doAction) {
|
|
451
|
+
this.hooks.doAction('compressor_before_headers_sent', req, res, compressionMethod);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Llamar al writeHead original
|
|
455
|
+
originalWriteHead.call(res);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Permitir a los hooks modificar el comportamiento antes de enviar la respuesta
|
|
459
|
+
if (this.hooks && this.hooks.doAction) {
|
|
460
|
+
this.hooks.doAction('compressor_before_response_sent', req, res, compressed, compressionMethod);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Enviar el cuerpo comprimido
|
|
464
|
+
originalEnd.call(res, compressed);
|
|
465
|
+
|
|
466
|
+
// Permitir a los hooks actuar después de enviar la respuesta
|
|
467
|
+
if (this.hooks && this.hooks.doAction) {
|
|
468
|
+
this.hooks.doAction('compressor_after_response_sent', req, res, compressed, compressionMethod);
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
.catch(err => {
|
|
472
|
+
console.error('Error comprimiendo la respuesta:', err);
|
|
473
|
+
// Permitir a los hooks manejar el error de compresión
|
|
474
|
+
if (this.hooks && this.hooks.doAction) {
|
|
475
|
+
this.hooks.doAction('compressor_error_during_compression', err, req, res, responseBody, compressionMethod);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Si ocurre un error, enviar sin comprimir
|
|
479
|
+
if (!res.headersSent) {
|
|
480
|
+
res.removeHeader('Content-Encoding');
|
|
481
|
+
originalWriteHead.call(res);
|
|
482
|
+
}
|
|
483
|
+
originalEnd.call(res, responseBody);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
238
486
|
}
|
|
239
487
|
|
|
240
488
|
module.exports = Compressor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jerkjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "JERK Framework v2.1 - A comprehensive framework for building secure and scalable APIs with frontend support, sessions, and template engine with performance optimizations",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,6 +33,24 @@ class CompressionTestController {
|
|
|
33
33
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
34
34
|
res.end(JSON.stringify(largeData));
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
// Nuevo endpoint para probar hooks de compresión
|
|
38
|
+
testCompressionHooks(req, res) {
|
|
39
|
+
// Datos para probar los hooks
|
|
40
|
+
const testData = {
|
|
41
|
+
message: 'Prueba de hooks de compresión',
|
|
42
|
+
hooksTest: true,
|
|
43
|
+
timestamp: new Date().toISOString(),
|
|
44
|
+
data: Array.from({ length: 500 }, (_, i) => ({
|
|
45
|
+
id: i,
|
|
46
|
+
testValue: `Valor de prueba ${i}`,
|
|
47
|
+
description: `Este es un elemento de prueba para verificar que los hooks de compresión funcionan correctamente`
|
|
48
|
+
}))
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
52
|
+
res.end(JSON.stringify(testData));
|
|
53
|
+
}
|
|
36
54
|
}
|
|
37
55
|
|
|
38
56
|
module.exports = new CompressionTestController();
|
package/standard/routes.json
CHANGED
|
@@ -54,5 +54,12 @@
|
|
|
54
54
|
"controller": "CompressionTestController",
|
|
55
55
|
"handler": "getLargeData",
|
|
56
56
|
"contentType": "application/json"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "/test-compression-hooks",
|
|
60
|
+
"method": "GET",
|
|
61
|
+
"controller": "CompressionTestController",
|
|
62
|
+
"handler": "testCompressionHooks",
|
|
63
|
+
"contentType": "application/json"
|
|
57
64
|
}
|
|
58
65
|
]
|
package/standard/server.js
CHANGED
|
@@ -44,7 +44,7 @@ class StandardServer {
|
|
|
44
44
|
this.authenticator = new Authenticator({ logger: this.logger });
|
|
45
45
|
this.cors = new Cors();
|
|
46
46
|
this.rateLimiter = new RateLimiter();
|
|
47
|
-
this.compressor = new Compressor();
|
|
47
|
+
this.compressor = new Compressor({ hooks: hooks });
|
|
48
48
|
this.firewall = new Firewall({ logger: this.logger });
|
|
49
49
|
this.sessionManager = new SessionManager();
|
|
50
50
|
|