mastercontroller 1.3.24 → 1.3.26

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
@@ -146,25 +146,10 @@ class MasterControl {
146
146
  // Only freeze in production to allow for easier debugging in development
147
147
  const isProduction = process.env.NODE_ENV === 'production';
148
148
 
149
- if (isProduction) {
150
- // Freeze prototypes to prevent prototype pollution attacks
151
- try {
152
- Object.freeze(Object.prototype);
153
- Object.freeze(Array.prototype);
154
- Object.freeze(Function.prototype);
155
-
156
- logger.info({
157
- code: 'MC_SECURITY_PROTOTYPE_FROZEN',
158
- message: 'Prototypes frozen in production mode for security'
159
- });
160
- } catch (err) {
161
- logger.warn({
162
- code: 'MC_SECURITY_FREEZE_FAILED',
163
- message: 'Failed to freeze prototypes',
164
- error: err.message
165
- });
166
- }
167
- }
149
+ // NOTE: Prototype freezing was removed. Freezing Object.prototype/Array.prototype/
150
+ // Function.prototype breaks third-party libraries (e.g., long, mysql2) that define
151
+ // properties on their prototypes after framework init. Prototype pollution protection
152
+ // is handled via input validation in MasterValidator.js instead.
168
153
 
169
154
  // Add prototype pollution detection utility
170
155
  this._detectPrototypePollution = (obj) => {
@@ -490,7 +475,7 @@ class MasterControl {
490
475
  if(type === "http"){
491
476
  $that.serverProtocol = "http";
492
477
  const server = http.createServer(async function(req, res) {
493
- $that.serverRun(req, res);
478
+ await $that.serverRun(req, res);
494
479
  });
495
480
  // Set server immediately so config can access it
496
481
  $that.server = server;
@@ -534,7 +519,7 @@ class MasterControl {
534
519
  if(credentials.honorCipherOrder === undefined){ credentials.honorCipherOrder = true; }
535
520
  if(!credentials.ALPNProtocols){ credentials.ALPNProtocols = ['h2', 'http/1.1']; }
536
521
  const server = https.createServer(credentials, async function(req, res) {
537
- $that.serverRun(req, res);
522
+ await $that.serverRun(req, res);
538
523
  });
539
524
  // Set server immediately so config can access it
540
525
  $that.server = server;
@@ -1006,25 +991,23 @@ class MasterControl {
1006
991
  const $that = this;
1007
992
  console.log("path", `${req.method} ${req.url}`);
1008
993
 
1009
- // Create request context for middleware pipeline
1010
- const parsedUrl = url.parse(req.url);
1011
- const pathname = parsedUrl.pathname;
1012
- const ext = path.parse(pathname).ext;
1013
-
1014
- const context = {
1015
- request: req,
1016
- response: res,
1017
- requrl: url.parse(req.url, true),
1018
- pathName: pathname.replace(/^\/|\/$/g, '').toLowerCase(),
1019
- type: req.method.toLowerCase(),
1020
- params: {},
1021
- state: {}, // User-defined state shared across middleware
1022
- master: $that, // Access to framework instance
1023
- isStatic: ext !== '' // Is this a static file request?
1024
- };
1025
-
1026
- // Execute middleware pipeline
1027
994
  try {
995
+ const parsedUrl = url.parse(req.url);
996
+ const pathname = parsedUrl.pathname;
997
+ const ext = path.parse(pathname).ext;
998
+
999
+ const context = {
1000
+ request: req,
1001
+ response: res,
1002
+ requrl: url.parse(req.url, true),
1003
+ pathName: pathname.replace(/^\/|\/$/g, '').toLowerCase(),
1004
+ type: req.method.toLowerCase(),
1005
+ params: {},
1006
+ state: {},
1007
+ master: $that,
1008
+ isStatic: ext !== ''
1009
+ };
1010
+
1028
1011
  await $that.pipeline.execute(context);
1029
1012
  } catch (error) {
1030
1013
  console.error('Pipeline execution failed:', error);
package/MasterCors.js CHANGED
@@ -235,6 +235,7 @@ class MasterCors{
235
235
  // Handle preflight OPTIONS request
236
236
  if (ctx.type === 'options') {
237
237
  $that.load({ request: ctx.request, response: ctx.response });
238
+ ctx.request.resume();
238
239
  ctx.response.statusCode = 204;
239
240
  ctx.response.end();
240
241
  return; // Terminal - don't call next()
package/MasterRouter.js CHANGED
@@ -805,11 +805,12 @@ class MasterRouter {
805
805
 
806
806
  tools.combineObjectPrototype(Control, this._master.controllerList);
807
807
  Control.prototype.__namespace = Control.name;
808
- Control.prototype.__requestObject = requestObject;
809
- Control.prototype.__currentRoute = currentRoute;
810
- Control.prototype.__response = requestObject.response;
811
- Control.prototype.__request = requestObject.request;
812
808
  const control = new Control(requestObject);
809
+ // Set request-specific state on INSTANCE (not prototype) for concurrency safety
810
+ control.__requestObject = requestObject;
811
+ control.__currentRoute = currentRoute;
812
+ control.__response = requestObject.response;
813
+ control.__request = requestObject.request;
813
814
  const _callEmit = new EventEmitter();
814
815
 
815
816
  _callEmit.once(EVENT_NAMES.CONTROLLER, function(){
@@ -837,7 +838,16 @@ class MasterRouter {
837
838
  // and no response was sent yet (e.g., overridden returnJson pattern)
838
839
  if (returnValue !== undefined && returnValue !== null
839
840
  && !requestObject.response.headersSent && !requestObject.response._headerSent) {
840
- const json = JSON.stringify(returnValue);
841
+ const seen = new WeakSet();
842
+ const json = JSON.stringify(returnValue, (key, value) => {
843
+ if (typeof value === 'object' && value !== null) {
844
+ if (seen.has(value)) {
845
+ return '[Circular Reference]';
846
+ }
847
+ seen.add(value);
848
+ }
849
+ return value;
850
+ });
841
851
  requestObject.response.writeHead(200, {
842
852
  'Content-Type': 'application/json',
843
853
  'Content-Length': Buffer.byteLength(json, 'utf8')
@@ -880,7 +890,21 @@ class MasterRouter {
880
890
 
881
891
  // check if before function is avaliable and wait for it to return
882
892
  if(control.__hasBeforeAction(control, requestObject)){
883
- control.__callBeforeAction(control, requestObject, _callEmit);
893
+ control.__callBeforeAction(control, requestObject, _callEmit)
894
+ .catch((error) => {
895
+ if (!requestObject.response.headersSent && !requestObject.response._headerSent) {
896
+ const mcError = handleControllerError(
897
+ error,
898
+ requestObject.toController,
899
+ requestObject.toAction,
900
+ requestObject.pathName,
901
+ currentRoute.routeDef
902
+ );
903
+ sendErrorResponse(requestObject.response, mcError, requestObject.pathName);
904
+ }
905
+ performanceTracker.end(requestId);
906
+ _callEmit.removeAllListeners();
907
+ });
884
908
  }else{
885
909
  _callEmit.emit("controller");
886
910
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mastercontroller",
3
- "version": "1.3.24",
3
+ "version": "1.3.26",
4
4
  "description": "Fortune 500 ready Node.js MVC framework with enterprise security, monitoring, and horizontal scaling",
5
5
  "main": "MasterControl.js",
6
6
  "license": "MIT",