jerkjs 2.1.0 → 2.1.2
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 -2
- package/README.md +1 -1
- package/examples.arj +0 -0
- package/index.js +1 -1
- package/lib/middleware/compressor.js +34 -18
- package/package.json +1 -1
- package/standard/CompressionTestController.js +38 -0
- package/standard/HealthController.js +16 -0
- package/standard/HomeController.js +12 -0
- package/standard/ProductController.js +18 -0
- package/standard/README.md +47 -0
- package/standard/UserController.js +23 -0
- package/standard/package.json +22 -0
- package/standard/routes.json +58 -0
- package/standard/server.js +140 -0
- package/cookies.txt +0 -5
- package/examples/advanced/controllers/productController.js +0 -64
- package/examples/advanced/controllers/userController.js +0 -85
- package/examples/advanced/routes.json +0 -51
- package/examples/advanced_example.js +0 -93
- package/examples/basic/controllers/userController.js +0 -85
- package/examples/basic_example.js +0 -72
- package/examples/frontend/README.md +0 -71
- package/examples/frontend/app.js +0 -71
- package/examples/frontend/controllers/apiController.js +0 -39
- package/examples/frontend/controllers/authController.js +0 -220
- package/examples/frontend/controllers/formController.js +0 -47
- package/examples/frontend/controllers/messageController.js +0 -96
- package/examples/frontend/controllers/pageController.js +0 -178
- package/examples/frontend/controllers/staticController.js +0 -167
- package/examples/frontend/routes.json +0 -90
- package/examples/hooks/app.js +0 -136
- package/examples/hooks/controllers/authController.js +0 -54
- package/examples/hooks/controllers/mainController.js +0 -41
- package/examples/hooks/controllers/productController.js +0 -39
- package/examples/hooks/controllers/userController.js +0 -69
- package/examples/hooks/routes.json +0 -51
- package/examples/hooks/views/home.html +0 -50
- package/examples/mvc_example/app.js +0 -138
- package/examples/mvc_example/views/home/index.html +0 -26
- package/examples/mvc_example/views/home/simple.html +0 -3
- package/examples/mvc_example/views/layout.html +0 -23
- package/examples/mvc_example/views/test.html +0 -3
- package/examples/mvc_example/views/user/invalid.html +0 -6
- package/examples/mvc_example/views/user/list.html +0 -36
- package/examples/mvc_example/views/user/notfound.html +0 -6
- package/examples/mvc_example/views/user/profile.html +0 -11
- package/examples/mvc_routes_example/app.js +0 -34
- package/examples/mvc_routes_example/controllers/mainController.js +0 -27
- package/examples/mvc_routes_example/controllers/productController.js +0 -47
- package/examples/mvc_routes_example/controllers/userController.js +0 -76
- package/examples/mvc_routes_example/routes.json +0 -30
- package/examples/mvc_routes_example/views/layout.html +0 -31
- package/examples/mvc_routes_example/views/main/index.html +0 -11
- package/examples/mvc_routes_example/views/product/catalog.html +0 -24
- package/examples/mvc_routes_example/views/user/invalid.html +0 -6
- package/examples/mvc_routes_example/views/user/list.html +0 -40
- package/examples/mvc_routes_example/views/user/notfound.html +0 -6
- package/examples/mvc_routes_example/views/user/profile.html +0 -18
- package/examples/mvc_welcome/README.md +0 -34
- package/examples/mvc_welcome/app.js +0 -50
- package/examples/mvc_welcome/controllers/welcomeController.js +0 -41
- package/examples/mvc_welcome/package.json +0 -26
- package/examples/mvc_welcome/views/home/welcome.html +0 -82
- package/examples/public/README.md +0 -92
- package/examples/public/app.js +0 -72
- package/examples/public/controllers/healthController.js +0 -20
- package/examples/public/controllers/mainController.js +0 -22
- package/examples/public/controllers/userController.js +0 -139
- package/examples/public/routes.json +0 -51
- package/examples/v2/README.md +0 -72
- package/examples/v2/app.js +0 -74
- package/examples/v2/app_fixed.js +0 -74
- package/examples/v2/controllers/authController.js +0 -64
- package/examples/v2/controllers/mainController.js +0 -24
- package/examples/v2/controllers/protectedController.js +0 -12
- package/examples/v2/controllers/userController.js +0 -16
- package/examples/v2/package.json +0 -27
- package/examples/v2/routes.json +0 -30
- package/examples/v2/test_api.sh +0 -47
- package/examples/v2/tokens_example.sqlite +0 -0
- package/examples/v2.1_firewall_demo/README.md +0 -113
- package/examples/v2.1_firewall_demo/app.js +0 -182
- package/examples/v2.1_firewall_demo/package.json +0 -27
- package/examples/v2.1_hooks_demo/README.md +0 -85
- package/examples/v2.1_hooks_demo/app.js +0 -101
- package/examples/v2.1_hooks_demo/controllers/hooksController.js +0 -29
- package/examples/v2.1_hooks_demo/controllers/mainController.js +0 -18
- package/examples/v2.1_hooks_demo/package.json +0 -27
- package/examples/v2.1_hooks_demo/routes.json +0 -16
- package/examples/v2.1_openapi_demo/README.md +0 -82
- package/examples/v2.1_openapi_demo/app.js +0 -296
- package/examples/v2.1_openapi_demo/package.json +0 -26
- package/examples/v2_cors/README.md +0 -82
- package/examples/v2_cors/app.js +0 -108
- package/examples/v2_cors/package.json +0 -23
- package/examples/v2_json_auth/README.md +0 -83
- package/examples/v2_json_auth/app.js +0 -72
- package/examples/v2_json_auth/controllers/authController.js +0 -67
- package/examples/v2_json_auth/controllers/mainController.js +0 -16
- package/examples/v2_json_auth/controllers/protectedController.js +0 -12
- package/examples/v2_json_auth/controllers/tokenController.js +0 -28
- package/examples/v2_json_auth/controllers/userController.js +0 -15
- package/examples/v2_json_auth/package.json +0 -26
- package/examples/v2_json_auth/routes.json +0 -37
- package/examples/v2_json_auth/tokens.json +0 -20
- package/examples/v2_mariadb_auth/README.md +0 -94
- package/examples/v2_mariadb_auth/app.js +0 -81
- package/examples/v2_mariadb_auth/controllers/authController.js +0 -95
- package/examples/v2_mariadb_auth/controllers/mainController.js +0 -31
- package/examples/v2_mariadb_auth/controllers/protectedController.js +0 -12
- package/examples/v2_mariadb_auth/controllers/userController.js +0 -17
- package/examples/v2_mariadb_auth/package.json +0 -27
- package/examples/v2_mariadb_auth/routes.json +0 -37
- package/examples/v2_no_auth/README.md +0 -75
- package/examples/v2_no_auth/app.js +0 -72
- package/examples/v2_no_auth/controllers/healthController.js +0 -14
- package/examples/v2_no_auth/controllers/mainController.js +0 -19
- package/examples/v2_no_auth/controllers/productController.js +0 -31
- package/examples/v2_no_auth/controllers/publicController.js +0 -16
- package/examples/v2_no_auth/package.json +0 -22
- package/examples/v2_no_auth/routes.json +0 -37
- package/examples/v2_oauth/README.md +0 -70
- package/examples/v2_oauth/app.js +0 -90
- package/examples/v2_oauth/controllers/mainController.js +0 -45
- package/examples/v2_oauth/controllers/oauthController.js +0 -247
- package/examples/v2_oauth/controllers/protectedController.js +0 -13
- package/examples/v2_oauth/controllers/userController.js +0 -17
- package/examples/v2_oauth/package.json +0 -26
- package/examples/v2_oauth/routes.json +0 -44
- package/examples/v2_openapi/README.md +0 -77
- package/examples/v2_openapi/app.js +0 -222
- package/examples/v2_openapi/controllers/authController.js +0 -52
- package/examples/v2_openapi/controllers/mainController.js +0 -26
- package/examples/v2_openapi/controllers/productController.js +0 -17
- package/examples/v2_openapi/controllers/userController.js +0 -27
- package/examples/v2_openapi/package.json +0 -26
- package/examples/v2_openapi/routes.json +0 -37
- package/v2examplle/v2_json_auth/README.md +0 -83
- package/v2examplle/v2_json_auth/app.js +0 -72
- package/v2examplle/v2_json_auth/controllers/authController.js +0 -67
- package/v2examplle/v2_json_auth/controllers/mainController.js +0 -16
- package/v2examplle/v2_json_auth/controllers/protectedController.js +0 -12
- package/v2examplle/v2_json_auth/controllers/tokenController.js +0 -28
- package/v2examplle/v2_json_auth/controllers/userController.js +0 -15
- package/v2examplle/v2_json_auth/package.json +0 -26
- package/v2examplle/v2_json_auth/routes.json +0 -37
- package/v2examplle/v2_json_auth/tokens.json +0 -20
- package/v2examplle/v2_mariadb_auth/README.md +0 -94
- package/v2examplle/v2_mariadb_auth/app.js +0 -81
- package/v2examplle/v2_mariadb_auth/controllers/authController.js +0 -95
- package/v2examplle/v2_mariadb_auth/controllers/mainController.js +0 -31
- package/v2examplle/v2_mariadb_auth/controllers/protectedController.js +0 -12
- package/v2examplle/v2_mariadb_auth/controllers/userController.js +0 -17
- package/v2examplle/v2_mariadb_auth/package.json +0 -27
- package/v2examplle/v2_mariadb_auth/routes.json +0 -37
- package/v2examplle/v2_sqlite_auth/README.md +0 -72
- package/v2examplle/v2_sqlite_auth/app.js +0 -74
- package/v2examplle/v2_sqlite_auth/app_fixed.js +0 -74
- package/v2examplle/v2_sqlite_auth/controllers/authController.js +0 -64
- package/v2examplle/v2_sqlite_auth/controllers/mainController.js +0 -24
- package/v2examplle/v2_sqlite_auth/controllers/protectedController.js +0 -12
- package/v2examplle/v2_sqlite_auth/controllers/userController.js +0 -16
- package/v2examplle/v2_sqlite_auth/package.json +0 -27
- package/v2examplle/v2_sqlite_auth/routes.json +0 -30
- package/v2examplle/v2_sqlite_auth/test_api.sh +0 -47
- package/v2examplle/v2_sqlite_auth/tokens_example.sqlite +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## v2.1.
|
|
3
|
+
## v2.1.2 - 17 de enero de 2026
|
|
4
4
|
|
|
5
5
|
### Nuevas características
|
|
6
6
|
|
|
@@ -28,4 +28,5 @@
|
|
|
28
28
|
- Corrección de ineficiencia en el procesamiento de cuerpos de solicitud grandes
|
|
29
29
|
- Mejora en la gestión de memoria durante el procesamiento de solicitudes
|
|
30
30
|
- Corrección de posibles problemas de rendimiento en aplicaciones con muchas rutas parametrizadas
|
|
31
|
-
- Mejora en la estabilidad del servidor bajo carga prolongada
|
|
31
|
+
- Mejora en la estabilidad del servidor bajo carga prolongada
|
|
32
|
+
- **Corrección crítica del middleware de compresión**: Se resolvió el error "ERR_HTTP_HEADERS_SENT" que ocurría cuando el middleware intentaba modificar encabezados después de que ya habían sido enviados al cliente. Se añadió verificación de `res.headersSent` antes de manipular encabezados.
|
package/README.md
CHANGED
package/examples.arj
ADDED
|
Binary file
|
package/index.js
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 - Con optimizaciones de eficiencia
|
|
4
|
+
* JERK Framework v2.1.1 - Con optimizaciones de eficiencia y corrección de errores
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const zlib = require('zlib');
|
|
@@ -76,8 +76,11 @@ class Compressor {
|
|
|
76
76
|
|
|
77
77
|
// Si el cuerpo es menor que el umbral, enviar sin comprimir
|
|
78
78
|
if (Buffer.byteLength(responseBody) < this.threshold) {
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
// Solo establecer encabezados si no se han enviado aún
|
|
80
|
+
if (!res.headersSent) {
|
|
81
|
+
res.removeHeader('Content-Encoding'); // Asegurar que no haya encabezado de codificación
|
|
82
|
+
originalWriteHead.call(res);
|
|
83
|
+
}
|
|
81
84
|
originalEnd.call(res, responseBody, encoding);
|
|
82
85
|
return;
|
|
83
86
|
}
|
|
@@ -111,12 +114,15 @@ class Compressor {
|
|
|
111
114
|
// Esperar a que se complete la compresión y enviar la respuesta
|
|
112
115
|
compressPromise
|
|
113
116
|
.then(compressed => {
|
|
114
|
-
//
|
|
115
|
-
res.
|
|
116
|
-
|
|
117
|
+
// Solo establecer encabezados si no se han enviado aún
|
|
118
|
+
if (!res.headersSent) {
|
|
119
|
+
// Establecer encabezados apropiados
|
|
120
|
+
res.setHeader('Content-Encoding', compressionMethod);
|
|
121
|
+
res.removeHeader('Content-Length'); // Eliminar Content-Length original
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
// Llamar al writeHead original
|
|
124
|
+
originalWriteHead.call(res);
|
|
125
|
+
}
|
|
120
126
|
|
|
121
127
|
// Enviar el cuerpo comprimido
|
|
122
128
|
originalEnd.call(res, compressed, encoding);
|
|
@@ -124,8 +130,10 @@ class Compressor {
|
|
|
124
130
|
.catch(err => {
|
|
125
131
|
console.error('Error comprimiendo la respuesta:', err);
|
|
126
132
|
// Si ocurre un error, enviar sin comprimir
|
|
127
|
-
res.
|
|
128
|
-
|
|
133
|
+
if (!res.headersSent) {
|
|
134
|
+
res.removeHeader('Content-Encoding');
|
|
135
|
+
originalWriteHead.call(res);
|
|
136
|
+
}
|
|
129
137
|
originalEnd.call(res, responseBody, encoding);
|
|
130
138
|
});
|
|
131
139
|
};
|
|
@@ -185,12 +193,16 @@ class Compressor {
|
|
|
185
193
|
zlib.gzip(jsonString, this.gzipOptions, (err, compressed) => {
|
|
186
194
|
if (err) {
|
|
187
195
|
console.error('Error comprimiendo JSON:', err);
|
|
188
|
-
res.
|
|
196
|
+
if (!res.headersSent) {
|
|
197
|
+
res.setHeader('Content-Type', 'application/json');
|
|
198
|
+
}
|
|
189
199
|
originalSend.call(res, jsonString);
|
|
190
200
|
} else {
|
|
191
|
-
res.
|
|
192
|
-
|
|
193
|
-
|
|
201
|
+
if (!res.headersSent) {
|
|
202
|
+
res.setHeader('Content-Encoding', compressionMethod);
|
|
203
|
+
res.removeHeader('Content-Length');
|
|
204
|
+
res.setHeader('Content-Type', 'application/json');
|
|
205
|
+
}
|
|
194
206
|
originalSend.call(res, compressed);
|
|
195
207
|
}
|
|
196
208
|
});
|
|
@@ -198,12 +210,16 @@ class Compressor {
|
|
|
198
210
|
zlib.deflate(jsonString, this.deflateOptions, (err, compressed) => {
|
|
199
211
|
if (err) {
|
|
200
212
|
console.error('Error comprimiendo JSON:', err);
|
|
201
|
-
res.
|
|
213
|
+
if (!res.headersSent) {
|
|
214
|
+
res.setHeader('Content-Type', 'application/json');
|
|
215
|
+
}
|
|
202
216
|
originalSend.call(res, jsonString);
|
|
203
217
|
} else {
|
|
204
|
-
res.
|
|
205
|
-
|
|
206
|
-
|
|
218
|
+
if (!res.headersSent) {
|
|
219
|
+
res.setHeader('Content-Encoding', compressionMethod);
|
|
220
|
+
res.removeHeader('Content-Length');
|
|
221
|
+
res.setHeader('Content-Type', 'application/json');
|
|
222
|
+
}
|
|
207
223
|
originalSend.call(res, compressed);
|
|
208
224
|
}
|
|
209
225
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jerkjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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": {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlador para probar compresión
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class CompressionTestController {
|
|
6
|
+
// Endpoint que devuelve datos grandes para probar compresión
|
|
7
|
+
getLargeData(req, res) {
|
|
8
|
+
// Crear un objeto grande con datos repetidos
|
|
9
|
+
const largeData = {
|
|
10
|
+
message: 'Datos grandes para probar compresión',
|
|
11
|
+
timestamp: new Date().toISOString(),
|
|
12
|
+
data: []
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Agregar muchos elementos para aumentar el tamaño
|
|
16
|
+
for (let i = 0; i < 1000; i++) {
|
|
17
|
+
largeData.data.push({
|
|
18
|
+
id: i,
|
|
19
|
+
title: `Elemento ${i}`,
|
|
20
|
+
description: `Esta es una descripción larga para el elemento ${i} que ayuda a aumentar el tamaño de la respuesta`,
|
|
21
|
+
metadata: {
|
|
22
|
+
created: new Date().toISOString(),
|
|
23
|
+
tags: [`tag-${i % 10}`, `category-${i % 5}`],
|
|
24
|
+
properties: {
|
|
25
|
+
prop1: `value-${i}`,
|
|
26
|
+
prop2: `another-value-${i}`,
|
|
27
|
+
prop3: `third-value-${i}`
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
34
|
+
res.end(JSON.stringify(largeData));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = new CompressionTestController();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlador de salud del sistema
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class HealthController {
|
|
6
|
+
checkHealth(req, res) {
|
|
7
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
8
|
+
res.end(JSON.stringify({
|
|
9
|
+
status: 'healthy',
|
|
10
|
+
timestamp: new Date().toISOString(),
|
|
11
|
+
uptime: process.uptime()
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = new HealthController();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlador de ejemplo para la ruta raíz
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class HomeController {
|
|
6
|
+
index(req, res) {
|
|
7
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
8
|
+
res.end('<h1>Bienvenido al servidor estándar de JERK</h1>');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = new HomeController();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlador de productos
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class ProductController {
|
|
6
|
+
getAllProducts(req, res) {
|
|
7
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
8
|
+
res.end(JSON.stringify({ products: [] }));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getProductById(req, res) {
|
|
12
|
+
const productId = req.params.id;
|
|
13
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
14
|
+
res.end(JSON.stringify({ id: productId, name: `Producto ${productId}` }));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = new ProductController();
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Servidor Estándar JERK
|
|
2
|
+
|
|
3
|
+
Este es el servidor estándar para JERK Framework v2.1. Implementa todas las características del framework y carga rutas desde un archivo `routes.json`.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- Carga de rutas desde `routes.json`
|
|
8
|
+
- Puerto configurable mediante variable de entorno `PORT`
|
|
9
|
+
- Todas las características del framework habilitadas:
|
|
10
|
+
- Autenticación (JWT, API Key, Basic, OAuth2, OIDC)
|
|
11
|
+
- CORS
|
|
12
|
+
- Rate Limiting
|
|
13
|
+
- Compresión
|
|
14
|
+
- Firewall
|
|
15
|
+
- Sesiones
|
|
16
|
+
- Sistema de Hooks/Filters
|
|
17
|
+
- MVC (Modelo-Vista-Controlador)
|
|
18
|
+
- Motor de plantillas
|
|
19
|
+
- Manejo de errores
|
|
20
|
+
|
|
21
|
+
## Variables de Entorno
|
|
22
|
+
|
|
23
|
+
- `PORT`: Puerto en el que escuchará el servidor (por defecto: 3000)
|
|
24
|
+
- `HOST`: Host en el que escuchará el servidor (por defecto: localhost)
|
|
25
|
+
- `USE_HTTPS`: Habilitar HTTPS (por defecto: false)
|
|
26
|
+
- `HTTPS_KEY_PATH`: Ruta al archivo de clave privada para HTTPS
|
|
27
|
+
- `HTTPS_CERT_PATH`: Ruta al archivo de certificado para HTTPS
|
|
28
|
+
- `REQUEST_TIMEOUT`: Timeout para solicitudes en milisegundos (por defecto: 120000)
|
|
29
|
+
- `CONNECTION_TIMEOUT`: Timeout para conexiones en milisegundos (por defecto: 120000)
|
|
30
|
+
- `MAX_BODY_SIZE`: Tamaño máximo del cuerpo de la solicitud en bytes (por defecto: 10MB)
|
|
31
|
+
|
|
32
|
+
## Uso
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Instalar dependencias
|
|
36
|
+
npm install
|
|
37
|
+
|
|
38
|
+
# Iniciar el servidor
|
|
39
|
+
npm start
|
|
40
|
+
|
|
41
|
+
# Iniciar el servidor en modo desarrollo con puerto diferente
|
|
42
|
+
npm run dev
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Rutas
|
|
46
|
+
|
|
47
|
+
Las rutas se definen en el archivo `routes.json` y se cargan automáticamente al iniciar el servidor. El servidor mostrará las rutas y características cargadas al iniciar mediante el sistema de hooks.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlador de usuarios
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class UserController {
|
|
6
|
+
getAllUsers(req, res) {
|
|
7
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
8
|
+
res.end(JSON.stringify({ users: [] }));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getUserById(req, res) {
|
|
12
|
+
const userId = req.params.id;
|
|
13
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
14
|
+
res.end(JSON.stringify({ id: userId, name: `Usuario ${userId}` }));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
createUser(req, res) {
|
|
18
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
19
|
+
res.end(JSON.stringify({ message: 'Usuario creado', data: req.body }));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = new UserController();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jerk-standard-server",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Servidor estándar para JERK Framework v2.1",
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node server.js",
|
|
8
|
+
"dev": "PORT=3001 node server.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"jerk",
|
|
12
|
+
"framework",
|
|
13
|
+
"api",
|
|
14
|
+
"server",
|
|
15
|
+
"standard"
|
|
16
|
+
],
|
|
17
|
+
"author": "JERK Framework Team",
|
|
18
|
+
"license": "Apache-2.0",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"jerkjs": "file:.."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "/",
|
|
4
|
+
"method": "GET",
|
|
5
|
+
"controller": "HomeController",
|
|
6
|
+
"handler": "index",
|
|
7
|
+
"contentType": "text/html"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"path": "/api/users",
|
|
11
|
+
"method": "GET",
|
|
12
|
+
"controller": "UserController",
|
|
13
|
+
"handler": "getAllUsers",
|
|
14
|
+
"contentType": "application/json"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "/api/users/:id",
|
|
18
|
+
"method": "GET",
|
|
19
|
+
"controller": "UserController",
|
|
20
|
+
"handler": "getUserById",
|
|
21
|
+
"contentType": "application/json"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "/api/users",
|
|
25
|
+
"method": "POST",
|
|
26
|
+
"controller": "UserController",
|
|
27
|
+
"handler": "createUser",
|
|
28
|
+
"contentType": "application/json"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "/api/products",
|
|
32
|
+
"method": "GET",
|
|
33
|
+
"controller": "ProductController",
|
|
34
|
+
"handler": "getAllProducts",
|
|
35
|
+
"contentType": "application/json"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "/api/products/:id",
|
|
39
|
+
"method": "GET",
|
|
40
|
+
"controller": "ProductController",
|
|
41
|
+
"handler": "getProductById",
|
|
42
|
+
"contentType": "application/json"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "/health",
|
|
46
|
+
"method": "GET",
|
|
47
|
+
"controller": "HealthController",
|
|
48
|
+
"handler": "checkHealth",
|
|
49
|
+
"contentType": "application/json"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "/test-compression",
|
|
53
|
+
"method": "GET",
|
|
54
|
+
"controller": "CompressionTestController",
|
|
55
|
+
"handler": "getLargeData",
|
|
56
|
+
"contentType": "application/json"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Servidor estándar para JERK Framework v2.1
|
|
3
|
+
* Este servidor implementa todas las características del framework
|
|
4
|
+
* y carga rutas desde routes.json
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
APIServer,
|
|
9
|
+
ControllerLoader,
|
|
10
|
+
Logger,
|
|
11
|
+
Authenticator,
|
|
12
|
+
Cors,
|
|
13
|
+
RateLimiter,
|
|
14
|
+
Compressor,
|
|
15
|
+
Firewall,
|
|
16
|
+
SessionManager,
|
|
17
|
+
hooks
|
|
18
|
+
} = require('../index.js');
|
|
19
|
+
|
|
20
|
+
const RouteLoader = require('../lib/loader/routeLoader');
|
|
21
|
+
|
|
22
|
+
class StandardServer {
|
|
23
|
+
constructor() {
|
|
24
|
+
// Obtener puerto de variable de entorno, obligatorio
|
|
25
|
+
this.port = parseInt(process.env.PORT);
|
|
26
|
+
if (isNaN(this.port)) {
|
|
27
|
+
throw new Error('La variable de entorno PORT es obligatoria');
|
|
28
|
+
}
|
|
29
|
+
this.host = process.env.HOST || 'localhost';
|
|
30
|
+
|
|
31
|
+
// Inicializar componentes
|
|
32
|
+
this.server = new APIServer({
|
|
33
|
+
port: this.port,
|
|
34
|
+
host: this.host,
|
|
35
|
+
https: process.env.USE_HTTPS === 'true',
|
|
36
|
+
key: process.env.HTTPS_KEY_PATH,
|
|
37
|
+
cert: process.env.HTTPS_CERT_PATH,
|
|
38
|
+
requestTimeout: parseInt(process.env.REQUEST_TIMEOUT) || 120000,
|
|
39
|
+
connectionTimeout: parseInt(process.env.CONNECTION_TIMEOUT) || 120000,
|
|
40
|
+
maxBodySize: parseInt(process.env.MAX_BODY_SIZE) || 10 * 1024 * 1024
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.logger = new Logger();
|
|
44
|
+
this.authenticator = new Authenticator({ logger: this.logger });
|
|
45
|
+
this.cors = new Cors();
|
|
46
|
+
this.rateLimiter = new RateLimiter();
|
|
47
|
+
this.compressor = new Compressor();
|
|
48
|
+
this.firewall = new Firewall({ logger: this.logger });
|
|
49
|
+
this.sessionManager = new SessionManager();
|
|
50
|
+
|
|
51
|
+
// Registrar hooks para mostrar información al iniciar
|
|
52
|
+
this.setupHooks();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setupHooks() {
|
|
56
|
+
// Hook para mostrar información antes de iniciar el servidor
|
|
57
|
+
hooks.addAction('pre_server_start', (server) => {
|
|
58
|
+
this.logger.info('=== INICIANDO SERVIDOR ESTÁNDAR JERK ===');
|
|
59
|
+
this.logger.info(`Puerto: ${this.port}`);
|
|
60
|
+
this.logger.info('Características habilitadas:');
|
|
61
|
+
this.logger.info('- Autenticación (JWT, API Key, Basic, OAuth2, OIDC)');
|
|
62
|
+
this.logger.info('- CORS');
|
|
63
|
+
this.logger.info('- Rate Limiting');
|
|
64
|
+
this.logger.info('- Compresión');
|
|
65
|
+
this.logger.info('- Firewall');
|
|
66
|
+
this.logger.info('- Sesiones');
|
|
67
|
+
this.logger.info('- Sistema de Hooks/Filters');
|
|
68
|
+
this.logger.info('- MVC (Modelo-Vista-Controlador)');
|
|
69
|
+
this.logger.info('- Motor de plantillas');
|
|
70
|
+
this.logger.info('- Manejo de errores');
|
|
71
|
+
|
|
72
|
+
// Cargar rutas antes de iniciar el servidor
|
|
73
|
+
this.loadRoutes();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Hook para mostrar información después de iniciar el servidor
|
|
77
|
+
hooks.addAction('post_server_start', (server) => {
|
|
78
|
+
this.logger.info(`Servidor estándar JERK escuchando en http://${this.host}:${this.port}`);
|
|
79
|
+
this.displayLoadedRoutes();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
loadRoutes() {
|
|
84
|
+
try {
|
|
85
|
+
// Instanciar RouteLoader y cargar rutas desde routes.json
|
|
86
|
+
const routeLoader = new RouteLoader();
|
|
87
|
+
routeLoader.loadRoutes(this.server, './routes.json');
|
|
88
|
+
this.logger.info('Rutas cargadas desde routes.json');
|
|
89
|
+
} catch (error) {
|
|
90
|
+
this.logger.error('Error al cargar rutas:', error.message);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
displayLoadedRoutes() {
|
|
95
|
+
if (this.server.routes && this.server.routes.length > 0) {
|
|
96
|
+
this.logger.info('=== RUTAS CARGADAS ===');
|
|
97
|
+
this.server.routes.forEach((route, index) => {
|
|
98
|
+
this.logger.info(`${index + 1}. ${route.method} ${route.path}`);
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
this.logger.warn('No se encontraron rutas para mostrar');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Método para configurar middlewares estándar
|
|
106
|
+
configureStandardMiddlewares() {
|
|
107
|
+
// Middleware de firewall (debe ir primero)
|
|
108
|
+
this.server.use(this.firewall.middleware());
|
|
109
|
+
|
|
110
|
+
// Middleware de compresión
|
|
111
|
+
this.server.use(this.compressor.middleware());
|
|
112
|
+
|
|
113
|
+
// Middleware de CORS
|
|
114
|
+
this.server.use(this.cors.middleware());
|
|
115
|
+
|
|
116
|
+
// Middleware de limitación de tasa
|
|
117
|
+
this.server.use(this.rateLimiter.middleware());
|
|
118
|
+
|
|
119
|
+
// Middleware de sesión
|
|
120
|
+
this.server.use(this.sessionManager.middleware());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
start() {
|
|
124
|
+
// Configurar middlewares estándar
|
|
125
|
+
this.configureStandardMiddlewares();
|
|
126
|
+
|
|
127
|
+
// Iniciar el servidor
|
|
128
|
+
this.server.start();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
stop() {
|
|
132
|
+
this.server.stop();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Crear e iniciar el servidor estándar
|
|
137
|
+
const standardServer = new StandardServer();
|
|
138
|
+
standardServer.start();
|
|
139
|
+
|
|
140
|
+
module.exports = StandardServer;
|
package/cookies.txt
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Controlador de ejemplo para productos
|
|
3
|
-
* Archivo: examples/advanced/controllers/productController.js
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Simulación de base de datos de productos
|
|
7
|
-
let products = [
|
|
8
|
-
{ id: 1, name: 'Laptop', price: 1000, category: 'Electronics' },
|
|
9
|
-
{ id: 2, name: 'Mouse', price: 25, category: 'Accessories' }
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
// Obtener todos los productos
|
|
13
|
-
function getProducts(req, res) {
|
|
14
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
15
|
-
res.end(JSON.stringify({
|
|
16
|
-
success: true,
|
|
17
|
-
data: products
|
|
18
|
-
}));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Actualizar un producto por ID
|
|
22
|
-
function updateProduct(req, res) {
|
|
23
|
-
try {
|
|
24
|
-
const productId = parseInt(req.params.id);
|
|
25
|
-
const { name, price, category } = req.body;
|
|
26
|
-
|
|
27
|
-
const productIndex = products.findIndex(p => p.id === productId);
|
|
28
|
-
|
|
29
|
-
if (productIndex === -1) {
|
|
30
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
31
|
-
res.end(JSON.stringify({
|
|
32
|
-
success: false,
|
|
33
|
-
message: 'Producto no encontrado'
|
|
34
|
-
}));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Actualizar producto
|
|
39
|
-
products[productIndex] = {
|
|
40
|
-
...products[productIndex],
|
|
41
|
-
...(name && { name }),
|
|
42
|
-
...(price && { price }),
|
|
43
|
-
...(category && { category })
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
47
|
-
res.end(JSON.stringify({
|
|
48
|
-
success: true,
|
|
49
|
-
data: products[productIndex]
|
|
50
|
-
}));
|
|
51
|
-
} catch (error) {
|
|
52
|
-
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
53
|
-
res.end(JSON.stringify({
|
|
54
|
-
success: false,
|
|
55
|
-
message: 'Error al actualizar producto'
|
|
56
|
-
}));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Exportar handlers
|
|
61
|
-
module.exports = {
|
|
62
|
-
getProducts,
|
|
63
|
-
updateProduct
|
|
64
|
-
};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Controlador de ejemplo para usuarios
|
|
3
|
-
* Archivo: examples/basic/controllers/userController.js
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Simulación de base de datos
|
|
7
|
-
let users = [
|
|
8
|
-
{ id: 1, name: 'John Doe', email: 'john@example.com' },
|
|
9
|
-
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
// Obtener todos los usuarios
|
|
13
|
-
function getUsers(req, res) {
|
|
14
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
15
|
-
res.end(JSON.stringify({
|
|
16
|
-
success: true,
|
|
17
|
-
data: users
|
|
18
|
-
}));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Obtener un usuario por ID
|
|
22
|
-
function getUserById(req, res) {
|
|
23
|
-
const userId = parseInt(req.params.id);
|
|
24
|
-
const user = users.find(u => u.id === userId);
|
|
25
|
-
|
|
26
|
-
if (!user) {
|
|
27
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
28
|
-
res.end(JSON.stringify({
|
|
29
|
-
success: false,
|
|
30
|
-
message: 'Usuario no encontrado'
|
|
31
|
-
}));
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
36
|
-
res.end(JSON.stringify({
|
|
37
|
-
success: true,
|
|
38
|
-
data: user
|
|
39
|
-
}));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Crear un nuevo usuario
|
|
43
|
-
function createUser(req, res) {
|
|
44
|
-
try {
|
|
45
|
-
const { name, email } = req.body;
|
|
46
|
-
|
|
47
|
-
// Validar datos
|
|
48
|
-
if (!name || !email) {
|
|
49
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
50
|
-
res.end(JSON.stringify({
|
|
51
|
-
success: false,
|
|
52
|
-
message: 'Nombre y correo electrónico son requeridos'
|
|
53
|
-
}));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Crear nuevo usuario
|
|
58
|
-
const newUser = {
|
|
59
|
-
id: users.length + 1,
|
|
60
|
-
name,
|
|
61
|
-
email
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
users.push(newUser);
|
|
65
|
-
|
|
66
|
-
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
67
|
-
res.end(JSON.stringify({
|
|
68
|
-
success: true,
|
|
69
|
-
data: newUser
|
|
70
|
-
}));
|
|
71
|
-
} catch (error) {
|
|
72
|
-
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
73
|
-
res.end(JSON.stringify({
|
|
74
|
-
success: false,
|
|
75
|
-
message: 'Error al crear usuario'
|
|
76
|
-
}));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Exportar handlers
|
|
81
|
-
module.exports = {
|
|
82
|
-
getUsers,
|
|
83
|
-
getUserById,
|
|
84
|
-
createUser
|
|
85
|
-
};
|