Browse Source

Fix session && support set cookie

HonorLee 5 years ago
parent
commit
3943c8ab25
10 changed files with 187 additions and 129 deletions
  1. 1 0
      .gitignore
  2. 4 1
      README.md
  3. 3 0
      config.js
  4. 12 69
      package-lock.json
  5. 4 4
      package.json
  6. 34 4
      system/lib/core/handler.js
  7. 23 0
      system/lib/core/module.js
  8. 4 1
      system/lib/core/router.js
  9. 102 45
      system/lib/core/session.js
  10. 0 5
      system/lib/helper/mysqldb.js

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 /node_modules
 npm-debug.log
+package-lock.json
 /log
 .idea
 .DS_Store

+ 4 - 1
README.md

@@ -19,7 +19,10 @@ Waiting...
 ```
 Waiting...
 ```
-
+## TODO
+```
+Waiting...
+```
 ## License
 本框架采用MIT协议,任何人可随意使(商)用本框架,无需通知作者本人,但请保留协议文件及文件署名
 

+ 3 - 0
config.js

@@ -72,4 +72,7 @@ debug:true,
 write_log_file:false,
 write_error_file:true,
 
+//You can add your own config here
+
+
 };

+ 12 - 69
package-lock.json

@@ -26,9 +26,9 @@
             "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
         },
         "async": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
-            "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
+            "version": "2.6.1",
+            "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
+            "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
             "requires": {
                 "lodash": "4.17.10"
             }
@@ -67,14 +67,6 @@
             "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz",
             "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg=="
         },
-        "boom": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
-            "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
-            "requires": {
-                "hoek": "4.2.1"
-            }
-        },
         "brace-expansion": {
             "version": "1.1.11",
             "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -110,9 +102,9 @@
             "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
         },
         "colors": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.4.tgz",
-            "integrity": "sha512-6Y+iBnWmXL+AWtlOp2Vr6R2w5MUlNJRwR0ShVFaAb1CqWzhPOpQg4L0jxD+xpw/Nc8QJwaq3KM79QUCriY8CWQ=="
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz",
+            "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw=="
         },
         "combined-stream": {
             "version": "1.0.6",
@@ -142,24 +134,6 @@
             "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
             "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
         },
-        "cryptiles": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
-            "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
-            "requires": {
-                "boom": "5.2.0"
-            },
-            "dependencies": {
-                "boom": {
-                    "version": "5.2.0",
-                    "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
-                    "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
-                    "requires": {
-                        "hoek": "4.2.1"
-                    }
-                }
-            }
-        },
         "d": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
@@ -340,22 +314,6 @@
                 "simple-lru-cache": "0.0.2"
             }
         },
-        "hawk": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
-            "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
-            "requires": {
-                "boom": "4.3.1",
-                "cryptiles": "3.1.2",
-                "hoek": "4.2.1",
-                "sntp": "2.1.0"
-            }
-        },
-        "hoek": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
-            "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
-        },
         "http-signature": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -409,9 +367,9 @@
             }
         },
         "js-base64": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz",
-            "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw=="
+            "version": "2.4.5",
+            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz",
+            "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ=="
         },
         "jsbn": {
             "version": "0.1.1",
@@ -668,9 +626,9 @@
             }
         },
         "request": {
-            "version": "2.85.0",
-            "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz",
-            "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==",
+            "version": "2.87.0",
+            "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
+            "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
             "requires": {
                 "aws-sign2": "0.7.0",
                 "aws4": "1.7.0",
@@ -680,7 +638,6 @@
                 "forever-agent": "0.6.1",
                 "form-data": "2.3.2",
                 "har-validator": "5.0.3",
-                "hawk": "6.0.2",
                 "http-signature": "1.2.0",
                 "is-typedarray": "1.0.0",
                 "isstream": "0.1.2",
@@ -690,7 +647,6 @@
                 "performance-now": "2.1.0",
                 "qs": "6.5.2",
                 "safe-buffer": "5.1.2",
-                "stringstream": "0.0.5",
                 "tough-cookie": "2.3.4",
                 "tunnel-agent": "0.6.0",
                 "uuid": "3.2.1"
@@ -747,14 +703,6 @@
             "resolved": "https://registry.npmjs.org/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz",
             "integrity": "sha1-1ZzDoZPBpdAyD4Tucy9uRxPlEd0="
         },
-        "sntp": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
-            "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
-            "requires": {
-                "hoek": "4.2.1"
-            }
-        },
         "sqlstring": {
             "version": "2.3.0",
             "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz",
@@ -788,11 +736,6 @@
                 "safe-buffer": "5.1.2"
             }
         },
-        "stringstream": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
-            "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
-        },
         "tinytim": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/tinytim/-/tinytim-0.1.1.tgz",

+ 4 - 4
package.json

@@ -5,12 +5,12 @@
     "license": "SEE LICENSE IN LICENSE.txt",
     "description": "A quick,easy,free MVC development framework based on NodeJS",
     "dependencies": {
-        "async": "^2.0.0-rc.5",
-        "colors": "^1.1.2",
+        "async": "^2.6.1",
+        "colors": "^1.3.0",
         "ejs": "^2.4.2",
         "formidable": "^1.1.1",
         "fs-extra": "^0.30.0",
-        "js-base64": "^2.1.9",
+        "js-base64": "^2.4.5",
         "klaw-sync": "^4.0.0",
         "md5": "^2.2.1",
         "memcached": "^2.2.2",
@@ -21,7 +21,7 @@
         "mysql": "^2.11.1",
         "path": "^0.12.7",
         "querystring": "^0.2.0",
-        "request": "^2.85.0",
+        "request": "^2.87.0",
         "sha1": "^1.1.1",
         "string-random": "^0.1.0",
         "tracer": "^0.8.3"

+ 34 - 4
system/lib/core/handler.js

@@ -18,7 +18,7 @@ module.exports = function(req,res){
      */
     this.end = this.response = function(){
         let mimeType = 'text/plain';
-        let status = 200;
+        let status = null;
         let endContent = '';
         switch(arguments.length){
             case 1:
@@ -34,11 +34,13 @@ module.exports = function(req,res){
                 mimeType = arguments[2];
                 break;
         }
-        this.Response.writeHead(status, { 'Content-Type': `${mimeType}; charset=UTF-8`});
+        if(status) this.Response.status(status);
+        if(mimeType) this.Response.setHeader('Content-Type', `${mimeType}; charset=UTF-8`);
         this.Response.write(endContent);
         this.Response.end();
     }
-    this.endRedirect = this.responseRedirect = function(status,location){
+    this.endRedirect = this.responseRedirect = function(location,permanently){
+        let status = permanently?301:302;
         this.Response.writeHead(status,{'Location':location});
         this.Response.end();
     }
@@ -83,7 +85,35 @@ module.exports = function(req,res){
         if(view && view.html){
             this.end(200,view.html,'text/html');
         }else{
-            this.end(403,`View [${viewName}] not found`);
+            this.end(502,`View [${viewName}] not found`,'text/plain');
         }
     }
+
+    this.setCookie = function(key,value,expire,path){
+        let cookie,originCookie;
+        if(this.Response.hasHeader('Set-Cookie')){
+            originCookie = this.Response.getHeader('Set-Cookie');
+        }else{
+            originCookie = [];
+        }
+        cookie = `${key}=${value}`;
+        if(path) cookie += ';path=' + path;
+        if(expire){
+            let expireTime;
+            if(expire=='forever'){
+                expireTime = new Date('9999/01/01 00:00:00').toGMTString();
+            }else{
+                expireTime = new Date(new Date().getTime()+Number(expire)*1000*60).toGMTString();
+            }
+            cookie += ';expires=' + expireTime;
+        }
+        originCookie.push(cookie);
+        this.Response.setHeader('Set-Cookie',cookie);
+    }
+
+    this.renewCookie = function(key,expire,path){
+        let originCookieValue = this.COOKIE[key];
+        if(!originCookieValue) return false;
+        this.setCookie(key,originCookieValue,expire,path);
+    }
 }

+ 23 - 0
system/lib/core/module.js

@@ -0,0 +1,23 @@
+/**
+ * @Author  HonorLee (dev@honorlee.me)
+ * @Version 1.0 (2018-05-27)
+ * @License MIT
+ */
+'use strict'
+global.M = function(moduleName){
+    console.log(this)
+    if(!moduleName){
+        LOGGER.error('Module name is empty!');
+        return null;
+    }
+    let modulePath = Core.Path.Module + '/' + moduleName + '.js';
+    let Module;
+    try{
+        Module = require(modulePath);
+    }catch(e){
+        LOGGER.error('Module load error:');
+        LOGGER.error(e);
+        return null;
+    }
+    return Module;
+};

+ 4 - 1
system/lib/core/router.js

@@ -46,16 +46,19 @@ var Router ={
         
         match = new RegExp(expArr.join('|')).exec(CACHE.HandlersString);
         if(!match) return Router._error('No such handler ['+handlerFile+']',res);
-        
+
         method = methodMark[match];
         handlerFile = Core.Path.Handler + match;
 
+        if(method=='__construct') return Router._error('__construct can\'t be called outside in ['+handlerFile+']',res);
+        
         let handler;
         try {
             handler = require(handlerFile);
         }catch(e){
             Router._error(e.stack,res);
         }
+        if(typeof handler === 'function') handler = new handler();
         let baseClass = new HANDLER(req,res);
         let newHandlerClass = Object.assign(baseClass,handler);
 

+ 102 - 45
system/lib/core/session.js

@@ -5,60 +5,117 @@
  */
 'use strict'
 var Session = {
-    set:function(key,value,arg1,arg2){
-        if(!key || !value) return null;
-        let sessionData;
-        if(sessionid){
-            try{
-                sessionData = JSON.parse(FILE.readFileSync(Core.Path.Session + '/' + sessionid,'UTF-8'));
-            }catch(e){
-                sessionid = '';
-            }
-        }
-        if(!sessionid){
-            sessionid = MD5(new Date().getTime()+''+Math.floor(Math.random()*9000+1000));
-            sessionData = {id:sessionid,expire:(new Date().getTime()+Config.SessionExpire*60000)};
-        }
-
-        sessionData[key]=value;
+    set:function(key,value,callback){
+        callback = Manager.buildCallback(callback);
+        if(!key || value==null) return callback.call(this,'Session key or value is empty',null);
+        let _this = this;
+        let session = {};
+        
+        session.id = MD5(new Date().getTime()+''+Math.floor(Math.random()*9000+1000));
+        session.data = {};
+        session.data[key] = value;
+        session.expire = Config.SessionExpire*60;
+        session.expireTime = new Date().getTime()+session.expire*1000;
 
-        FILE.writeFileSync(Core.Path.Session + '/' + sessionid,JSON.stringify(sessionData),'UTF-8');
-        return sessionid;
+        Manager.set(session,function(err){
+            if(err) return callback.call(_this,'Session set err;',null);
+            callback.call(_this,null,session);
+        });
     },
-    get:function(sessionid,key,callback){
-        if(!sessionid) return null;
-        let sessionData;
-        try{
-            sessionData = JSON.parse(FILE.readFileSync(Core.Path.Session + '/' + sessionid,'UTF-8'));
-            if(sessionData.expire < new Date().getTime()){
-                sessionData = null;
-                Session.clear(sessionid);
-            }
-        }catch(e){
-            sessionData = null;
-        }
-        if(key && sessionData){
-            if(sessionData[key]!=undefined){
-                return sessionData[key];
+    update:function(sessionid,key,value,callback){
+        callback = Manager.buildCallback(callback);
+        if(!sessionid || !key || value==null) return callback.call(this,'Session id,key or value is empty',null);
+        let _this = this;
+        Manager.get(sessionid,function(err,result){
+            let session;
+            if(err || result == null){
+                session = {id:sessionid,data:{}};
             }else{
-                return null;
+                session = result;
             }
-        }
-        return sessionData;
+
+            if(err || result == null || Config.Session.AutoRefresh){
+                session.expire = Config.SessionExpire*60;
+                session.expireTime = new Date().getTime()+session.expire*1000;
+            }
+
+            session.data[key] = value;
+            Manager.set(session,function(err){
+                if(err) return callback.call(_this,'Session set error');
+                callback.call(_this,null,session)
+            });
+        });
+    },
+    get:function(sessionid,callback){
+        callback = Manager.buildCallback(callback);
+        if(!sessionid) return callback.call(this,'Session id is empty',null);
+        let _this = this;
+        Manager.get(sessionid,function(err,result){
+            callback.call(_this,null,result);
+        });
+    },
+    getKeyValue:function(sessionid,key,callback){
+        callback = Manager.buildCallback(callback);
+        if(!sessionid || !key) return callback.call(this,'Session id or key is empty',null);
+        let _this = this;
+        Session.get(sessionid,function(err,result){
+            if(err || !result) return callback.call(_this,null);
+            callback.call(_this,null,result.data[key]);
+        });
     },
     clear:function(sessionid){
         if(!sessionid) return;
-        try{
-            FILE.rmdirSync(Core.Path.Session + '/' + sessionid);
-        }catch(e){}
+        Manager.clear(sessionid);
     }
 };
 module.exports = Session;
 
-var FileManager = {
-
-}
-
-var MemcacheManager = {
-
+var Manager = {
+    get:function(sessionid,callback){
+        if(Config.Database.Memcache.on && Memcache){
+            Memcache.get('session_'+sessionid,function(err,result){
+                if(err) return callback(err);
+                callback(null,result);
+            });
+        }else{
+            let sessionData = null;
+            try{
+                sessionData = JSON.parse(FILE.readFileSync(Core.Path.Session + '/' + sessionid,'UTF-8'));
+            }catch(e){}
+            if(sessionData && sessionData.expireTime){
+                if(new Date().getTime()>sessionData.expireTime){
+                    sessionData = null;
+                    Manager.clear(sessionid);
+                }
+            }
+            callback(null,sessionData);
+        }
+    },
+    set:function(session,callback){
+        if(Config.Database.Memcache.on && Memcache){
+            Memcache.set('session_'+session.id,session,session.expire,function(err){
+                if(err){
+                    Logger.error(err);
+                    return callback(err);
+                }
+                callback();
+            });
+        }else{
+            FILE.writeFileSync(Core.Path.Session + '/' + session.id,JSON.stringify(session),'UTF-8');
+            callback();
+        }
+    },
+    clear:function(sessionid){
+        if(Config.Database.Memcache.on && Memcache){
+            Memcache.del('session_'+sessionid);
+        }else{
+            try{
+                FILE.rmdirSync(Core.Path.Session + '/' + sessionid);
+            }catch(e){}
+        }
+    },
+    buildCallback:function(callback){
+        if(callback && typeof callback=='function') return callback;
+        callback = function(){}
+    }
 }

+ 0 - 5
system/lib/helper/mysqldb.js

@@ -15,11 +15,6 @@ module.exports={
     }
 };
 
-global.M = function(table){
-    if(!table) return null;
-    return new Module(Config.mysql_cfg.prefix+table);
-};
-
 var Module = function(table){
     let instance = this;
     let tableName = table;