mastercontroller 1.3.13 → 1.3.15

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/MasterControl.js CHANGED
@@ -1,16 +1,28 @@
1
1
  // MasterControl - by Alexander rich
2
2
  // version 1.0.252
3
3
 
4
- var url = require('url');
5
- var fileserver = require('fs');
6
- var http = require('http');
7
- var https = require('https');
8
- var tls = require('tls');
9
- var fs = require('fs');
10
- var url = require('url');
11
- var path = require('path');
12
- var globSearch = require("glob");
13
- var crypto = require('crypto'); // CRITICAL FIX: For ETag generation
4
+ const url = require('url');
5
+ const fileserver = require('fs');
6
+ const http = require('http');
7
+ const https = require('https');
8
+ const tls = require('tls');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const globSearch = require("glob");
12
+ const crypto = require('crypto'); // CRITICAL FIX: For ETag generation
13
+
14
+ // HTTP Status Code Constants
15
+ const HTTP_STATUS = {
16
+ OK: 200,
17
+ MOVED_PERMANENTLY: 301,
18
+ FOUND: 302,
19
+ NOT_MODIFIED: 304,
20
+ BAD_REQUEST: 400,
21
+ FORBIDDEN: 403,
22
+ NOT_FOUND: 404,
23
+ PAYLOAD_TOO_LARGE: 413,
24
+ INTERNAL_ERROR: 500
25
+ };
14
26
 
15
27
  // Enhanced error handling - setup global handlers
16
28
  const { setupGlobalErrorHandlers } = require('./error/MasterErrorMiddleware');
@@ -176,7 +188,10 @@ class MasterControl {
176
188
  return false;
177
189
  };
178
190
 
179
- console.log('[MasterControl] Prototype pollution protection initialized');
191
+ logger.info({
192
+ code: 'MC_INFO_PROTOTYPE_PROTECTION',
193
+ message: 'Prototype pollution protection initialized'
194
+ });
180
195
  }
181
196
 
182
197
  // extends class methods to be used inside of the view class using the THIS keyword
@@ -291,7 +306,7 @@ class MasterControl {
291
306
 
292
307
  // Enhanced: Support both relative (to master.root) and absolute paths
293
308
  // If folderLocation is absolute, use it directly; otherwise join with master.root
294
- var rootFolderLocation;
309
+ let rootFolderLocation;
295
310
  if (path.isAbsolute(folderLocation)) {
296
311
  // Absolute path provided - use it directly
297
312
  rootFolderLocation = path.join(folderLocation, innerFolder);
@@ -301,16 +316,20 @@ class MasterControl {
301
316
  }
302
317
 
303
318
  // Structure is always: {rootFolderLocation}/config/initializers/config.js
304
- var configPath = path.join(rootFolderLocation, 'config', 'initializers', 'config.js');
319
+ const configPath =path.join(rootFolderLocation, 'config', 'initializers', 'config.js');
305
320
  if(fs.existsSync(configPath)){
306
321
  require(configPath);
307
322
  }else{
308
- this.error.log(`Cannot find config file at ${configPath}`, "error");
323
+ logger.error({
324
+ code: 'MC_ERR_CONFIG_NOT_FOUND',
325
+ message: 'Cannot find config file',
326
+ path: configPath
327
+ });
309
328
  }
310
329
 
311
330
  // Structure is always: {rootFolderLocation}/config/routes.js
312
- var routePath = path.join(rootFolderLocation, 'config', 'routes.js');
313
- var routeObject = {
331
+ const routePath =path.join(rootFolderLocation, 'config', 'routes.js');
332
+ const routeObject ={
314
333
  isComponent : true,
315
334
  root : rootFolderLocation
316
335
  }
@@ -318,7 +337,11 @@ class MasterControl {
318
337
  if(fs.existsSync(routePath)){
319
338
  require(routePath);
320
339
  }else{
321
- this.error.log(`Cannot find routes file at ${routePath}`, "error");
340
+ logger.error({
341
+ code: 'MC_ERR_ROUTES_NOT_FOUND',
342
+ message: 'Cannot find routes file',
343
+ path: routePath
344
+ });
322
345
  }
323
346
  }
324
347
 
@@ -335,7 +358,7 @@ class MasterControl {
335
358
 
336
359
  if(settings.httpPort || settings.requestTimeout){
337
360
  this.server.timeout = settings.requestTimeout;
338
- var host = settings.hostname || settings.host || settings.http;
361
+ const host =settings.hostname || settings.host || settings.http;
339
362
  if(host){
340
363
  this.server.listen(settings.httpPort, host);
341
364
  }else{
@@ -391,7 +414,7 @@ class MasterControl {
391
414
  // sets up https or http server protocals
392
415
  setupServer(type, credentials ){
393
416
  try {
394
- var $that = this;
417
+ const $that = this;
395
418
 
396
419
  // SECURITY: Initialize prototype pollution protection
397
420
  this._initPrototypePollutionProtection();
@@ -401,12 +424,10 @@ class MasterControl {
401
424
  const internalModules = {
402
425
  'MasterPipeline': './MasterPipeline',
403
426
  'MasterTimeout': './MasterTimeout',
404
- 'MasterErrorRenderer': './error/MasterErrorRenderer',
405
427
  'MasterAction': './MasterAction',
406
428
  'MasterActionFilters': './MasterActionFilters',
407
429
  'MasterRouter': './MasterRouter',
408
430
  'MasterRequest': './MasterRequest',
409
- 'MasterError': './error/MasterError',
410
431
  'MasterCors': './MasterCors',
411
432
  'SessionSecurity': './security/SessionSecurity',
412
433
  'MasterSocket': './MasterSocket',
@@ -422,8 +443,6 @@ class MasterControl {
422
443
  const moduleRegistry = {
423
444
  'pipeline': { path: './MasterPipeline', exportName: 'MasterPipeline' },
424
445
  'timeout': { path: './MasterTimeout', exportName: 'MasterTimeout' },
425
- 'errorRenderer': { path: './error/MasterErrorRenderer', exportName: 'MasterErrorRenderer' },
426
- 'error': { path: './error/MasterError', exportName: 'MasterError' },
427
446
  'router': { path: './MasterRouter', exportName: 'MasterRouter' },
428
447
  'request': { path: './MasterRequest', exportName: 'MasterRequest' },
429
448
  'cors': { path: './MasterCors', exportName: 'MasterCors' },
@@ -551,7 +570,7 @@ class MasterControl {
551
570
  * @security CRITICAL: Always provide allowedHosts in production to prevent open redirect attacks
552
571
  */
553
572
  startHttpToHttpsRedirect(redirectPort, bindHost, allowedHosts = []){
554
- var $that = this;
573
+ const $that = this;
555
574
 
556
575
  // Security warning if no hosts specified
557
576
  if (allowedHosts.length === 0) {
@@ -562,8 +581,8 @@ class MasterControl {
562
581
 
563
582
  return http.createServer(function (req, res) {
564
583
  try{
565
- var host = req.headers['host'] || '';
566
- var hostname = host.split(':')[0]; // Remove port number
584
+ const host = req.headers['host'] || '';
585
+ const hostname = host.split(':')[0]; // Remove port number
567
586
 
568
587
  // CRITICAL SECURITY: Validate host header to prevent open redirect attacks
569
588
  if (allowedHosts.length > 0) {
@@ -711,7 +730,7 @@ class MasterControl {
711
730
  * This includes: static files, body parsing, scoped services, routing, error handling
712
731
  */
713
732
  _registerCoreMiddleware(){
714
- var $that = this;
733
+ const $that = this;
715
734
 
716
735
  // 1. Static File Serving (with path traversal protection)
717
736
  $that.pipeline.use(async (ctx, next) => {
@@ -754,17 +773,17 @@ class MasterControl {
754
773
  return;
755
774
  }
756
775
 
757
- // Check if file exists
758
- fs.exists(resolvedPath, function (exist) {
759
- if (!exist) {
760
- ctx.response.statusCode = 404;
761
- ctx.response.setHeader('Content-Type', 'text/plain');
762
- ctx.response.end('Not Found');
763
- return;
764
- }
776
+ // Check if file exists (use synchronous check for better performance in middleware)
777
+ if (!fs.existsSync(resolvedPath)) {
778
+ ctx.response.statusCode = 404;
779
+ ctx.response.setHeader('Content-Type', 'text/plain');
780
+ ctx.response.end('Not Found');
781
+ return;
782
+ }
765
783
 
766
- // Get file stats
767
- let finalPath = resolvedPath;
784
+ // Get file stats
785
+ let finalPath = resolvedPath;
786
+ try {
768
787
  const stats = fs.statSync(resolvedPath);
769
788
 
770
789
  // If directory, try to serve index.html
@@ -881,7 +900,19 @@ class MasterControl {
881
900
  }
882
901
  });
883
902
  }
884
- });
903
+ } catch (error) {
904
+ // Handle file stat errors
905
+ logger.error({
906
+ code: 'MC_ERR_FILE_STAT',
907
+ message: 'Error accessing static file',
908
+ path: resolvedPath,
909
+ error: error.message
910
+ });
911
+ ctx.response.statusCode = 500;
912
+ ctx.response.setHeader('Content-Type', 'text/plain');
913
+ ctx.response.end('Internal Server Error');
914
+ return;
915
+ }
885
916
 
886
917
  return; // Terminal - don't call next()
887
918
  }
@@ -972,7 +1003,7 @@ class MasterControl {
972
1003
  }
973
1004
 
974
1005
  async serverRun(req, res){
975
- var $that = this;
1006
+ const $that = this;
976
1007
  console.log("path", `${req.method} ${req.url}`);
977
1008
 
978
1009
  // Create request context for middleware pipeline
@@ -1020,7 +1051,7 @@ class MasterControl {
1020
1051
  var rootFolderLocation = path.join(this.root, foldername);
1021
1052
 
1022
1053
  // Structure is always: {rootFolderLocation}/routes.js
1023
- var routePath = path.join(rootFolderLocation, 'routes.js');
1054
+ const routePath =path.join(rootFolderLocation, 'routes.js');
1024
1055
  var route = {
1025
1056
  isComponent : false,
1026
1057
  root : `${this.root}`
@@ -1029,20 +1060,22 @@ class MasterControl {
1029
1060
  if(fs.existsSync(routePath)){
1030
1061
  require(routePath);
1031
1062
  }else{
1032
- this.error.log(`Cannot find routes file at ${routePath}`, "error");
1063
+ logger.error({
1064
+ code: 'MC_ERR_ROUTES_NOT_FOUND',
1065
+ message: 'Cannot find routes file',
1066
+ path: routePath
1067
+ });
1033
1068
  }
1034
1069
  }
1035
1070
 
1036
1071
 
1037
1072
  // builds and calls all the required tools to have master running completely
1038
1073
  addInternalTools(requiredList){
1039
- if(requiredList.constructor === Array){
1074
+ if(Array.isArray(requiredList)){
1040
1075
  // Map module names to their new organized paths
1041
1076
  const modulePathMap = {
1042
1077
  'MasterPipeline': './MasterPipeline',
1043
1078
  'MasterTimeout': './MasterTimeout',
1044
- 'MasterErrorRenderer': './error/MasterErrorRenderer',
1045
- 'MasterError': './error/MasterError',
1046
1079
  'MasterAction': './MasterAction',
1047
1080
  'MasterActionFilters': './MasterActionFilters',
1048
1081
  'MasterRouter': './MasterRouter',
package/MasterCors.js CHANGED
@@ -1,6 +1,27 @@
1
1
  // version 0.0.3 - robust origin handling (all envs), creds-safe reflection, function origins, extended Vary
2
2
 
3
- // todo - res.setHeader('Access-Control-Request-Method', '*');
3
+ const { logger } = require('./error/MasterErrorLogger');
4
+
5
+ // HTTP Status Code Constants
6
+ const HTTP_STATUS = {
7
+ NO_CONTENT: 204,
8
+ BAD_REQUEST: 400
9
+ };
10
+
11
+ // CORS Header Name Constants
12
+ const CORS_HEADERS = {
13
+ ALLOW_ORIGIN: 'Access-Control-Allow-Origin',
14
+ ALLOW_METHODS: 'Access-Control-Allow-Methods',
15
+ ALLOW_HEADERS: 'Access-Control-Allow-Headers',
16
+ ALLOW_CREDENTIALS: 'Access-Control-Allow-Credentials',
17
+ MAX_AGE: 'Access-Control-Max-Age',
18
+ EXPOSE_HEADERS: 'Access-Control-Expose-Headers',
19
+ REQUEST_HEADERS: 'Access-Control-Request-Headers',
20
+ REQUEST_METHOD: 'Access-Control-Request-Method',
21
+ VARY: 'Vary'
22
+ };
23
+
24
+ // todo - res.setHeader('Access-Control-Request-Method', '*');
4
25
  class MasterCors{
5
26
 
6
27
  // Lazy-load master to avoid circular dependency (Google-style lazy initialization)
@@ -16,7 +37,10 @@ class MasterCors{
16
37
  this.options = options;
17
38
  }
18
39
  else{
19
- this._master.error.log("cors options missing", "warn");
40
+ logger.warn({
41
+ code: 'MC_CORS_OPTIONS_MISSING',
42
+ message: 'CORS options missing'
43
+ });
20
44
  }
21
45
 
22
46
  // Auto-register with pipeline if available
@@ -32,7 +56,15 @@ class MasterCors{
32
56
  this.response = params.response;
33
57
  this.request = params.request;
34
58
  // Always signal that response may vary by Origin and requested headers/method
35
- try { this.response.setHeader('Vary', 'Origin, Access-Control-Request-Headers, Access-Control-Request-Method'); } catch(_) {}
59
+ try {
60
+ this.response.setHeader('Vary', 'Origin, Access-Control-Request-Headers, Access-Control-Request-Method');
61
+ } catch(error) {
62
+ logger.warn({
63
+ code: 'MC_CORS_VARY_HEADER_FAILED',
64
+ message: 'Failed to set Vary header',
65
+ error: error.message
66
+ });
67
+ }
36
68
  this.configureOrigin();
37
69
  this.configureMethods()
38
70
  this.configureAllowedHeaders();
@@ -41,7 +73,10 @@ class MasterCors{
41
73
  this.configureMaxAge();
42
74
  }
43
75
  else{
44
- this._master.error.log("cors response and requests missing", "warn");
76
+ logger.warn({
77
+ code: 'MC_CORS_PARAMS_MISSING',
78
+ message: 'CORS response and request params missing'
79
+ });
45
80
  }
46
81
  }
47
82
 
@@ -63,7 +98,7 @@ class MasterCors{
63
98
 
64
99
  if(this.options.origin === true){
65
100
  // If credentials are enabled, reflect request origin per spec
66
- var requestOrigin = this.request.headers.origin;
101
+ const requestOrigin =this.request.headers.origin;
67
102
  if (this.options.credentials === true && requestOrigin) {
68
103
  this.setHeader('access-control-allow-origin', requestOrigin);
69
104
  } else {
@@ -76,9 +111,9 @@ class MasterCors{
76
111
  this.removeHeader('access-control-allow-origin');
77
112
  }
78
113
 
79
- if(this.options.origin.constructor === Array){
114
+ if(Array.isArray(this.options.origin)){
80
115
  // Get the origin from the incoming request
81
- var requestOrigin = this.request.headers.origin;
116
+ const requestOrigin =this.request.headers.origin;
82
117
 
83
118
  // Check if the request origin is in our allowed list
84
119
  if(requestOrigin && this.options.origin.includes(requestOrigin)){
@@ -90,15 +125,22 @@ class MasterCors{
90
125
  // Function predicate support: (origin, req) => boolean|string
91
126
  if (typeof this.options.origin === 'function'){
92
127
  try {
93
- var requestOrigin = this.request.headers.origin;
94
- var res = this.options.origin(requestOrigin, this.request);
128
+ const requestOrigin = this.request.headers.origin;
129
+ const res = this.options.origin(requestOrigin, this.request);
95
130
  if (res === true && requestOrigin){
96
131
  this.setHeader('access-control-allow-origin', requestOrigin);
97
132
  }
98
133
  else if (typeof res === 'string' && res){
99
134
  this.setHeader('access-control-allow-origin', res);
100
135
  }
101
- } catch(_) {}
136
+ } catch(error) {
137
+ logger.error({
138
+ code: 'MC_CORS_ORIGIN_FUNCTION_ERROR',
139
+ message: 'Error in origin function predicate',
140
+ error: error.message,
141
+ stack: error.stack
142
+ });
143
+ }
102
144
  }
103
145
 
104
146
  }
@@ -106,16 +148,16 @@ class MasterCors{
106
148
 
107
149
  configureMethods(){
108
150
  if(this.options.methods){
109
- if(this.options.methods.constructor === Array){
110
- var elements = this.options.methods.join(", ");
151
+ if(Array.isArray(this.options.methods)){
152
+ const elements =this.options.methods.join(", ");
111
153
  this.setHeader('access-control-allow-methods', elements);
112
154
  }
113
155
  }
114
156
  }
115
157
 
116
158
  configureAllowedHeaders(){
117
- var requestheader = this.request.headers["access-control-request-headers"];
118
- var $that = this;
159
+ const requestheader =this.request.headers["access-control-request-headers"];
160
+ const $that =this;
119
161
  if(this.options.allowedHeaders){
120
162
 
121
163
  if($that.options.allowedHeaders === true){
@@ -135,8 +177,8 @@ class MasterCors{
135
177
  this.setHeader("access-control-allow-headers", $that.options.allowedHeaders);
136
178
  }
137
179
 
138
- if($that.options.allowedHeaders.constructor === Array){
139
- var elements = $that.options.allowedHeaders.join(", ");
180
+ if(Array.isArray($that.options.allowedHeaders)){
181
+ const elements =$that.options.allowedHeaders.join(", ");
140
182
  $that.request.headers['access-control-allow-headers'] = elements;
141
183
  this.setHeader("access-control-allow-headers", elements);
142
184
  }
@@ -158,8 +200,8 @@ class MasterCors{
158
200
  this.setHeader('access-control-expose-headers', this.options.exposeHeaders);
159
201
  }
160
202
 
161
- if(this.options.exposeHeaders.constructor === Array){
162
- var elements = this.options.exposeHeaders.join(", ");
203
+ if(Array.isArray(this.options.exposeHeaders)){
204
+ const elements =this.options.exposeHeaders.join(", ");
163
205
  this.setHeader('access-control-expose-headers', elements);
164
206
  }
165
207
 
@@ -187,7 +229,7 @@ class MasterCors{
187
229
  * Handles both preflight OPTIONS requests and regular requests
188
230
  */
189
231
  middleware() {
190
- var $that = this;
232
+ const $that =this;
191
233
 
192
234
  return async (ctx, next) => {
193
235
  // Handle preflight OPTIONS request
package/MasterPipeline.js CHANGED
@@ -3,6 +3,11 @@
3
3
 
4
4
  const { logger } = require('./error/MasterErrorLogger');
5
5
 
6
+ // HTTP Status Code Constants
7
+ const HTTP_STATUS = {
8
+ INTERNAL_ERROR: 500
9
+ };
10
+
6
11
  class MasterPipeline {
7
12
  constructor() {
8
13
  this.middleware = [];
@@ -214,7 +219,7 @@ class MasterPipeline {
214
219
  });
215
220
 
216
221
  if (!context.response.headersSent) {
217
- context.response.statusCode = 500;
222
+ context.response.statusCode = HTTP_STATUS.INTERNAL_ERROR;
218
223
  context.response.end('Internal Server Error');
219
224
  }
220
225
  return;
@@ -285,7 +290,11 @@ class MasterPipeline {
285
290
  folders.forEach(folder => {
286
291
  const dir = path.join(this._master.root, folder);
287
292
  if (!fs.existsSync(dir)) {
288
- console.warn(`[Middleware] Folder not found: ${folder}`);
293
+ logger.warn({
294
+ code: 'MC_MIDDLEWARE_FOLDER_NOT_FOUND',
295
+ message: 'Middleware folder not found',
296
+ folder: folder
297
+ });
289
298
  return;
290
299
  }
291
300
 
@@ -305,16 +314,30 @@ class MasterPipeline {
305
314
  }
306
315
  // Pattern 2: module.exports = { register: (master) => {} }
307
316
  else if (middleware.register && typeof middleware.register === 'function') {
308
- middleware.register(master);
317
+ middleware.register(this._master);
309
318
  }
310
319
  else {
311
- console.warn(`[Middleware] Invalid export in ${folder}/${file}`);
320
+ logger.warn({
321
+ code: 'MC_MIDDLEWARE_INVALID_EXPORT',
322
+ message: 'Invalid middleware export',
323
+ file: `${folder}/${file}`
324
+ });
312
325
  return;
313
326
  }
314
327
 
315
- console.log(`[Middleware] Loaded: ${folder}/${file}`);
328
+ logger.info({
329
+ code: 'MC_MIDDLEWARE_LOADED',
330
+ message: 'Middleware loaded',
331
+ file: `${folder}/${file}`
332
+ });
316
333
  } catch (err) {
317
- console.error(`[Middleware] Failed to load ${folder}/${file}:`, err.message);
334
+ logger.error({
335
+ code: 'MC_MIDDLEWARE_LOAD_FAILED',
336
+ message: 'Failed to load middleware',
337
+ file: `${folder}/${file}`,
338
+ error: err.message,
339
+ stack: err.stack
340
+ });
318
341
  }
319
342
  });
320
343
  });