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.
Files changed (177) hide show
  1. package/LICENSE +200 -0
  2. package/README.md +171 -0
  3. package/doc/EXTENSION_MANUAL.md +958 -0
  4. package/doc/FIREWALL_MANUAL.md +419 -0
  5. package/doc/HOOKS_REFERENCE_IMPROVED.md +599 -0
  6. package/doc/MANUAL_API_SDK.md +539 -0
  7. package/doc/MANUAL_MVC.md +397 -0
  8. package/doc/MARIADB_TOKENS_IMPLEMENTATION.md +113 -0
  9. package/doc/MIDDLEWARE_MANUAL.md +521 -0
  10. package/doc/OAUTH2_GOOGLE_MANUAL.md +408 -0
  11. package/doc/frontend-and-sessions.md +356 -0
  12. package/examples/advanced/controllers/productController.js +64 -0
  13. package/examples/advanced/controllers/userController.js +85 -0
  14. package/examples/advanced/routes.json +51 -0
  15. package/examples/advanced_example.js +93 -0
  16. package/examples/basic/controllers/userController.js +85 -0
  17. package/examples/basic_example.js +72 -0
  18. package/examples/frontend/README.md +71 -0
  19. package/examples/frontend/app.js +71 -0
  20. package/examples/frontend/controllers/apiController.js +39 -0
  21. package/examples/frontend/controllers/authController.js +220 -0
  22. package/examples/frontend/controllers/formController.js +47 -0
  23. package/examples/frontend/controllers/messageController.js +96 -0
  24. package/examples/frontend/controllers/pageController.js +178 -0
  25. package/examples/frontend/controllers/staticController.js +167 -0
  26. package/examples/frontend/routes.json +90 -0
  27. package/examples/mvc_example/app.js +138 -0
  28. package/examples/mvc_example/views/home/index.html +26 -0
  29. package/examples/mvc_example/views/home/simple.html +3 -0
  30. package/examples/mvc_example/views/layout.html +23 -0
  31. package/examples/mvc_example/views/test.html +3 -0
  32. package/examples/mvc_example/views/user/invalid.html +6 -0
  33. package/examples/mvc_example/views/user/list.html +36 -0
  34. package/examples/mvc_example/views/user/notfound.html +6 -0
  35. package/examples/mvc_example/views/user/profile.html +11 -0
  36. package/examples/mvc_routes_example/app.js +34 -0
  37. package/examples/mvc_routes_example/controllers/mainController.js +27 -0
  38. package/examples/mvc_routes_example/controllers/productController.js +47 -0
  39. package/examples/mvc_routes_example/controllers/userController.js +76 -0
  40. package/examples/mvc_routes_example/routes.json +30 -0
  41. package/examples/mvc_routes_example/views/layout.html +31 -0
  42. package/examples/mvc_routes_example/views/main/index.html +11 -0
  43. package/examples/mvc_routes_example/views/product/catalog.html +24 -0
  44. package/examples/mvc_routes_example/views/user/invalid.html +6 -0
  45. package/examples/mvc_routes_example/views/user/list.html +40 -0
  46. package/examples/mvc_routes_example/views/user/notfound.html +6 -0
  47. package/examples/mvc_routes_example/views/user/profile.html +18 -0
  48. package/examples/public/README.md +92 -0
  49. package/examples/public/app.js +72 -0
  50. package/examples/public/controllers/healthController.js +20 -0
  51. package/examples/public/controllers/mainController.js +22 -0
  52. package/examples/public/controllers/userController.js +139 -0
  53. package/examples/public/routes.json +51 -0
  54. package/examples/v2/README.md +72 -0
  55. package/examples/v2/app.js +74 -0
  56. package/examples/v2/app_fixed.js +74 -0
  57. package/examples/v2/controllers/authController.js +64 -0
  58. package/examples/v2/controllers/mainController.js +24 -0
  59. package/examples/v2/controllers/protectedController.js +12 -0
  60. package/examples/v2/controllers/userController.js +16 -0
  61. package/examples/v2/package.json +27 -0
  62. package/examples/v2/routes.json +30 -0
  63. package/examples/v2/test_api.sh +47 -0
  64. package/examples/v2/tokens_example.sqlite +0 -0
  65. package/examples/v2.1_firewall_demo/README.md +113 -0
  66. package/examples/v2.1_firewall_demo/app.js +182 -0
  67. package/examples/v2.1_firewall_demo/package.json +27 -0
  68. package/examples/v2.1_hooks_demo/README.md +85 -0
  69. package/examples/v2.1_hooks_demo/app.js +101 -0
  70. package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
  71. package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
  72. package/examples/v2.1_hooks_demo/package.json +27 -0
  73. package/examples/v2.1_hooks_demo/routes.json +16 -0
  74. package/examples/v2.1_openapi_demo/README.md +82 -0
  75. package/examples/v2.1_openapi_demo/app.js +296 -0
  76. package/examples/v2.1_openapi_demo/package.json +26 -0
  77. package/examples/v2_cors/README.md +82 -0
  78. package/examples/v2_cors/app.js +108 -0
  79. package/examples/v2_cors/package.json +23 -0
  80. package/examples/v2_json_auth/README.md +83 -0
  81. package/examples/v2_json_auth/app.js +72 -0
  82. package/examples/v2_json_auth/controllers/authController.js +67 -0
  83. package/examples/v2_json_auth/controllers/mainController.js +16 -0
  84. package/examples/v2_json_auth/controllers/protectedController.js +12 -0
  85. package/examples/v2_json_auth/controllers/tokenController.js +28 -0
  86. package/examples/v2_json_auth/controllers/userController.js +15 -0
  87. package/examples/v2_json_auth/package.json +26 -0
  88. package/examples/v2_json_auth/routes.json +37 -0
  89. package/examples/v2_json_auth/tokens.json +20 -0
  90. package/examples/v2_mariadb_auth/README.md +94 -0
  91. package/examples/v2_mariadb_auth/app.js +81 -0
  92. package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
  93. package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
  94. package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
  95. package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
  96. package/examples/v2_mariadb_auth/package.json +27 -0
  97. package/examples/v2_mariadb_auth/routes.json +37 -0
  98. package/examples/v2_no_auth/README.md +75 -0
  99. package/examples/v2_no_auth/app.js +72 -0
  100. package/examples/v2_no_auth/controllers/healthController.js +14 -0
  101. package/examples/v2_no_auth/controllers/mainController.js +19 -0
  102. package/examples/v2_no_auth/controllers/productController.js +31 -0
  103. package/examples/v2_no_auth/controllers/publicController.js +16 -0
  104. package/examples/v2_no_auth/package.json +22 -0
  105. package/examples/v2_no_auth/routes.json +37 -0
  106. package/examples/v2_oauth/README.md +70 -0
  107. package/examples/v2_oauth/app.js +90 -0
  108. package/examples/v2_oauth/controllers/mainController.js +45 -0
  109. package/examples/v2_oauth/controllers/oauthController.js +247 -0
  110. package/examples/v2_oauth/controllers/protectedController.js +13 -0
  111. package/examples/v2_oauth/controllers/userController.js +17 -0
  112. package/examples/v2_oauth/package.json +26 -0
  113. package/examples/v2_oauth/routes.json +44 -0
  114. package/examples/v2_openapi/README.md +77 -0
  115. package/examples/v2_openapi/app.js +222 -0
  116. package/examples/v2_openapi/controllers/authController.js +52 -0
  117. package/examples/v2_openapi/controllers/mainController.js +26 -0
  118. package/examples/v2_openapi/controllers/productController.js +17 -0
  119. package/examples/v2_openapi/controllers/userController.js +27 -0
  120. package/examples/v2_openapi/package.json +26 -0
  121. package/examples/v2_openapi/routes.json +37 -0
  122. package/generate_token.js +10 -0
  123. package/index.js +85 -0
  124. package/jerk.jpg +0 -0
  125. package/lib/core/handler.js +86 -0
  126. package/lib/core/hooks.js +224 -0
  127. package/lib/core/router.js +204 -0
  128. package/lib/core/securityEnhancedServer.js +752 -0
  129. package/lib/core/server.js +369 -0
  130. package/lib/loader/controllerLoader.js +175 -0
  131. package/lib/loader/routeLoader.js +341 -0
  132. package/lib/middleware/auditLogger.js +208 -0
  133. package/lib/middleware/authenticator.js +565 -0
  134. package/lib/middleware/compressor.js +218 -0
  135. package/lib/middleware/cors.js +135 -0
  136. package/lib/middleware/firewall.js +443 -0
  137. package/lib/middleware/rateLimiter.js +210 -0
  138. package/lib/middleware/session.js +301 -0
  139. package/lib/middleware/validator.js +193 -0
  140. package/lib/mvc/controllerBase.js +207 -0
  141. package/lib/mvc/viewEngine.js +752 -0
  142. package/lib/utils/configParser.js +223 -0
  143. package/lib/utils/logger.js +145 -0
  144. package/lib/utils/mariadbTokenAdapter.js +226 -0
  145. package/lib/utils/openapiGenerator.js +140 -0
  146. package/lib/utils/sqliteTokenAdapter.js +224 -0
  147. package/lib/utils/tokenManager.js +254 -0
  148. package/package.json +47 -0
  149. package/v2examplle/v2_json_auth/README.md +83 -0
  150. package/v2examplle/v2_json_auth/app.js +72 -0
  151. package/v2examplle/v2_json_auth/controllers/authController.js +67 -0
  152. package/v2examplle/v2_json_auth/controllers/mainController.js +16 -0
  153. package/v2examplle/v2_json_auth/controllers/protectedController.js +12 -0
  154. package/v2examplle/v2_json_auth/controllers/tokenController.js +28 -0
  155. package/v2examplle/v2_json_auth/controllers/userController.js +15 -0
  156. package/v2examplle/v2_json_auth/package.json +26 -0
  157. package/v2examplle/v2_json_auth/routes.json +37 -0
  158. package/v2examplle/v2_json_auth/tokens.json +20 -0
  159. package/v2examplle/v2_mariadb_auth/README.md +94 -0
  160. package/v2examplle/v2_mariadb_auth/app.js +81 -0
  161. package/v2examplle/v2_mariadb_auth/controllers/authController.js +95 -0
  162. package/v2examplle/v2_mariadb_auth/controllers/mainController.js +31 -0
  163. package/v2examplle/v2_mariadb_auth/controllers/protectedController.js +12 -0
  164. package/v2examplle/v2_mariadb_auth/controllers/userController.js +17 -0
  165. package/v2examplle/v2_mariadb_auth/package.json +27 -0
  166. package/v2examplle/v2_mariadb_auth/routes.json +37 -0
  167. package/v2examplle/v2_sqlite_auth/README.md +72 -0
  168. package/v2examplle/v2_sqlite_auth/app.js +74 -0
  169. package/v2examplle/v2_sqlite_auth/app_fixed.js +74 -0
  170. package/v2examplle/v2_sqlite_auth/controllers/authController.js +64 -0
  171. package/v2examplle/v2_sqlite_auth/controllers/mainController.js +24 -0
  172. package/v2examplle/v2_sqlite_auth/controllers/protectedController.js +12 -0
  173. package/v2examplle/v2_sqlite_auth/controllers/userController.js +16 -0
  174. package/v2examplle/v2_sqlite_auth/package.json +27 -0
  175. package/v2examplle/v2_sqlite_auth/routes.json +30 -0
  176. package/v2examplle/v2_sqlite_auth/test_api.sh +47 -0
  177. package/v2examplle/v2_sqlite_auth/tokens_example.sqlite +0 -0
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Middleware de compresión para el framework API SDK
3
+ * Implementación del componente middleware/compressor.js
4
+ */
5
+
6
+ const zlib = require('zlib');
7
+
8
+ class Compressor {
9
+ /**
10
+ * Constructor del compresor
11
+ * @param {Object} options - Opciones de configuración
12
+ * @param {Array} options.encodings - Tipos de compresión soportados
13
+ * @param {number} options.threshold - Tamaño mínimo en bytes para comprimir
14
+ * @param {Object} options.gzipOptions - Opciones para compresión gzip
15
+ * @param {Object} options.deflateOptions - Opciones para compresión deflate
16
+ */
17
+ constructor(options = {}) {
18
+ this.encodings = options.encodings || ['gzip', 'deflate'];
19
+ this.threshold = options.threshold || 1024; // 1KB por defecto
20
+ this.gzipOptions = options.gzipOptions || {};
21
+ this.deflateOptions = options.deflateOptions || {};
22
+ }
23
+
24
+ /**
25
+ * Middleware de compresión
26
+ * @returns {Function} - Middleware de compresión
27
+ */
28
+ middleware() {
29
+ return (req, res, next) => {
30
+ // Verificar si el cliente acepta compresión
31
+ const acceptEncoding = req.headers['accept-encoding'];
32
+ if (!acceptEncoding) {
33
+ if (next) next();
34
+ return;
35
+ }
36
+
37
+ // Determinar el método de compresión preferido
38
+ let compressionMethod = null;
39
+
40
+ if (acceptEncoding.includes('gzip')) {
41
+ compressionMethod = 'gzip';
42
+ } else if (acceptEncoding.includes('deflate')) {
43
+ compressionMethod = 'deflate';
44
+ }
45
+
46
+ // Si no se soporta ningún método, continuar sin comprimir
47
+ if (!compressionMethod || !this.encodings.includes(compressionMethod)) {
48
+ if (next) next();
49
+ return;
50
+ }
51
+
52
+ // Guardar el método original de res.end
53
+ const originalEnd = res.end;
54
+ const originalWriteHead = res.writeHead;
55
+
56
+ // Variable para almacenar el cuerpo de la respuesta
57
+ let responseBody = '';
58
+
59
+ // Sobrescribir res.write para capturar el cuerpo
60
+ res.write = (chunk, encoding) => {
61
+ responseBody += chunk;
62
+ };
63
+
64
+ // Sobrescribir res.end para comprimir antes de enviar
65
+ res.end = (chunk, encoding) => {
66
+ // Añadir el chunk final al cuerpo si existe
67
+ if (chunk) {
68
+ responseBody += chunk;
69
+ }
70
+
71
+ // Si el cuerpo es menor que el umbral, enviar sin comprimir
72
+ if (Buffer.byteLength(responseBody) < this.threshold) {
73
+ res.removeHeader('Content-Encoding'); // Asegurar que no haya encabezado de codificación
74
+ originalWriteHead.call(res);
75
+ originalEnd.call(res, responseBody, encoding);
76
+ return;
77
+ }
78
+
79
+ // Aplicar compresión según el método seleccionado
80
+ let compressedBody;
81
+ let compressPromise;
82
+
83
+ if (compressionMethod === 'gzip') {
84
+ compressPromise = new Promise((resolve, reject) => {
85
+ zlib.gzip(responseBody, this.gzipOptions, (err, buffer) => {
86
+ if (err) {
87
+ reject(err);
88
+ } else {
89
+ resolve(buffer);
90
+ }
91
+ });
92
+ });
93
+ } else if (compressionMethod === 'deflate') {
94
+ compressPromise = new Promise((resolve, reject) => {
95
+ zlib.deflate(responseBody, this.deflateOptions, (err, buffer) => {
96
+ if (err) {
97
+ reject(err);
98
+ } else {
99
+ resolve(buffer);
100
+ }
101
+ });
102
+ });
103
+ }
104
+
105
+ // Esperar a que se complete la compresión y enviar la respuesta
106
+ compressPromise
107
+ .then(compressed => {
108
+ // Establecer encabezados apropiados
109
+ res.setHeader('Content-Encoding', compressionMethod);
110
+ res.removeHeader('Content-Length'); // Eliminar Content-Length original
111
+
112
+ // Llamar al writeHead original
113
+ originalWriteHead.call(res);
114
+
115
+ // Enviar el cuerpo comprimido
116
+ originalEnd.call(res, compressed, encoding);
117
+ })
118
+ .catch(err => {
119
+ console.error('Error comprimiendo la respuesta:', err);
120
+ // Si ocurre un error, enviar sin comprimir
121
+ res.removeHeader('Content-Encoding');
122
+ originalWriteHead.call(res);
123
+ originalEnd.call(res, responseBody, encoding);
124
+ });
125
+ };
126
+
127
+ // Continuar con el siguiente middleware
128
+ if (next) {
129
+ next();
130
+ }
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Middleware para comprimir solo respuestas JSON
136
+ * @returns {Function} - Middleware de compresión para JSON
137
+ */
138
+ jsonOnly() {
139
+ return (req, res, next) => {
140
+ const originalSend = res.send; // Suponiendo que hay un método send
141
+
142
+ res.send = (data) => {
143
+ // Verificar si el tipo de contenido es JSON
144
+ const contentType = res.getHeader('Content-Type');
145
+ if (contentType && contentType.includes('application/json')) {
146
+ // Convertir a string si no lo es
147
+ const jsonString = typeof data === 'string' ? data : JSON.stringify(data);
148
+
149
+ // Continuar con la lógica de compresión
150
+ // (similar a la implementación en middleware())
151
+ const acceptEncoding = req.headers['accept-encoding'];
152
+ if (!acceptEncoding) {
153
+ res.setHeader('Content-Type', 'application/json');
154
+ originalSend.call(res, jsonString);
155
+ return;
156
+ }
157
+
158
+ let compressionMethod = null;
159
+ if (acceptEncoding.includes('gzip')) {
160
+ compressionMethod = 'gzip';
161
+ } else if (acceptEncoding.includes('deflate')) {
162
+ compressionMethod = 'deflate';
163
+ }
164
+
165
+ if (!compressionMethod || !this.encodings.includes(compressionMethod)) {
166
+ res.setHeader('Content-Type', 'application/json');
167
+ originalSend.call(res, jsonString);
168
+ return;
169
+ }
170
+
171
+ if (Buffer.byteLength(jsonString) < this.threshold) {
172
+ res.setHeader('Content-Type', 'application/json');
173
+ res.removeHeader('Content-Encoding');
174
+ originalSend.call(res, jsonString);
175
+ return;
176
+ }
177
+
178
+ if (compressionMethod === 'gzip') {
179
+ zlib.gzip(jsonString, this.gzipOptions, (err, compressed) => {
180
+ if (err) {
181
+ console.error('Error comprimiendo JSON:', err);
182
+ res.setHeader('Content-Type', 'application/json');
183
+ originalSend.call(res, jsonString);
184
+ } else {
185
+ res.setHeader('Content-Encoding', compressionMethod);
186
+ res.removeHeader('Content-Length');
187
+ res.setHeader('Content-Type', 'application/json');
188
+ originalSend.call(res, compressed);
189
+ }
190
+ });
191
+ } else if (compressionMethod === 'deflate') {
192
+ zlib.deflate(jsonString, this.deflateOptions, (err, compressed) => {
193
+ if (err) {
194
+ console.error('Error comprimiendo JSON:', err);
195
+ res.setHeader('Content-Type', 'application/json');
196
+ originalSend.call(res, jsonString);
197
+ } else {
198
+ res.setHeader('Content-Encoding', compressionMethod);
199
+ res.removeHeader('Content-Length');
200
+ res.setHeader('Content-Type', 'application/json');
201
+ originalSend.call(res, compressed);
202
+ }
203
+ });
204
+ }
205
+ } else {
206
+ // Si no es JSON, enviar normalmente
207
+ originalSend.call(res, data);
208
+ }
209
+ };
210
+
211
+ if (next) {
212
+ next();
213
+ }
214
+ };
215
+ }
216
+ }
217
+
218
+ module.exports = Compressor;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Middleware de CORS para el framework API SDK
3
+ * Implementación del componente middleware/cors.js
4
+ */
5
+
6
+ class Cors {
7
+ /**
8
+ * Constructor del middleware CORS
9
+ * @param {Object} options - Opciones de configuración de CORS
10
+ * @param {Array|string} options.origin - Orígenes permitidos
11
+ * @param {Array} options.methods - Métodos HTTP permitidos
12
+ * @param {Array} options.allowedHeaders - Headers permitidos
13
+ * @param {Array} options.exposedHeaders - Headers expuestos al cliente
14
+ * @param {boolean} options.credentials - Permitir credenciales
15
+ * @param {number} options.maxAge - Tiempo máximo para preflight cache
16
+ */
17
+ constructor(options = {}) {
18
+ this.options = {
19
+ origin: options.origin || '*',
20
+ methods: options.methods || ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
21
+ allowedHeaders: options.allowedHeaders || [
22
+ 'Authorization',
23
+ 'Content-Type',
24
+ 'Accept',
25
+ 'X-Requested-With',
26
+ 'Access-Control-Allow-Origin'
27
+ ],
28
+ exposedHeaders: options.exposedHeaders || [],
29
+ credentials: options.credentials !== undefined ? options.credentials : false,
30
+ maxAge: options.maxAge || 86400 // 24 hours
31
+ };
32
+
33
+ // Convertir métodos a mayúsculas
34
+ this.options.methods = this.options.methods.map(method => method.toUpperCase());
35
+ }
36
+
37
+ /**
38
+ * Middleware de CORS
39
+ * @returns {Function} - Middleware de CORS
40
+ */
41
+ middleware() {
42
+ return (req, res, next) => {
43
+ // Determinar el origen permitido
44
+ const origin = this.determineOrigin(req);
45
+
46
+ if (origin) {
47
+ res.setHeader('Access-Control-Allow-Origin', origin);
48
+ } else {
49
+ // Si no está permitido y no es wildcard, no establecer encabezado
50
+ if (this.options.origin !== '*') {
51
+ res.setHeader('Access-Control-Allow-Origin', 'null');
52
+ } else {
53
+ res.setHeader('Access-Control-Allow-Origin', '*');
54
+ }
55
+ }
56
+
57
+ // Métodos permitidos
58
+ res.setHeader('Access-Control-Allow-Methods', this.options.methods.join(','));
59
+
60
+ // Headers permitidos
61
+ res.setHeader('Access-Control-Allow-Headers', this.options.allowedHeaders.join(','));
62
+
63
+ // Headers expuestos
64
+ if (this.options.exposedHeaders.length > 0) {
65
+ res.setHeader('Access-Control-Expose-Headers', this.options.exposedHeaders.join(','));
66
+ }
67
+
68
+ // Credenciales
69
+ if (this.options.credentials) {
70
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
71
+ }
72
+
73
+ // Max age para preflight
74
+ res.setHeader('Access-Control-Max-Age', this.options.maxAge);
75
+
76
+ // Manejar solicitud preflight (OPTIONS)
77
+ if (req.method === 'OPTIONS') {
78
+ // Solo responder con 204 si el origen es válido o es wildcard
79
+ if (origin || this.options.origin === '*') {
80
+ res.writeHead(204); // No content
81
+ res.end();
82
+ } else {
83
+ // Si el origen no es válido, responder con 403 o permitir que la solicitud continúe
84
+ // para que otros middlewares o handlers puedan manejarla
85
+ if (next) {
86
+ next();
87
+ }
88
+ }
89
+ return;
90
+ }
91
+
92
+ // Continuar con el siguiente middleware
93
+ if (next) {
94
+ next();
95
+ }
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Determina el origen permitido para la solicitud
101
+ * @param {Object} req - Objeto de solicitud HTTP
102
+ * @returns {string|boolean} - Origen permitido o falso si no está permitido
103
+ */
104
+ determineOrigin(req) {
105
+ const requestOrigin = req.headers.origin;
106
+
107
+ if (!requestOrigin) {
108
+ return false;
109
+ }
110
+
111
+ // Si el origen es wildcard, permitir cualquier origen
112
+ if (this.options.origin === '*') {
113
+ return requestOrigin;
114
+ }
115
+
116
+ // Si es un string, comparar directamente
117
+ if (typeof this.options.origin === 'string') {
118
+ return requestOrigin === this.options.origin ? requestOrigin : false;
119
+ }
120
+
121
+ // Si es un array, verificar si está incluido
122
+ if (Array.isArray(this.options.origin)) {
123
+ return this.options.origin.includes(requestOrigin) ? requestOrigin : false;
124
+ }
125
+
126
+ // Si es una función, llamarla para determinar el origen
127
+ if (typeof this.options.origin === 'function') {
128
+ return this.options.origin(requestOrigin);
129
+ }
130
+
131
+ return false;
132
+ }
133
+ }
134
+
135
+ module.exports = Cors;