UNPKG

sgapps-server

Version:
470 lines (397 loc) 24.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>prototypes/server/extend/request-session.js - SGApps Server - Framework</title> <meta name="description" content="SGApps Server for high performance results" /> <meta name="keywords" content="javascript, js, application-prototype, prototype" /> <meta name="keyword" content="javascript, js, application-prototype, prototype" /> <meta property="og:title" content="SGApps Server - Framework"/> <meta property="og:type" content="website"/> <meta property="og:image" content=""/> <meta property="og:url" content="https://labs.sgapps.io/open-source/sgapps-server"/> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav class="wrap"> <input type="text" id="nav-search" placeholder="Search" /> <h2><a href="index.html">Home</a></h2><h2><a href="https://labs.sgapps.io/open-source/sgapps-server" target="_blank" class="menu-item" id="website_link" >Project Page ( Git Lab )</a></h2><h2><a href="http://gordienco.net/" target="_blank" class="menu-item" id="website_link" >About Me</a></h2><h2><a href="https://labs.sgapps.io/open-source/sgapps-server" target="_blank" class="menu-item" id="github_link" >GitHub</a></h2><h3>Classes</h3><ul><li><a href="AccessLogger.html">AccessLogger</a><ul class='methods'><li data-type='method' style='display: none;'><a href="AccessLogger.html#formattedDate">formattedDate</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#getProtocol">getProtocol</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#getReferer">getReferer</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#getRemoteIp">getRemoteIp</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#getSize">getSize</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#getUsername">getUsername</a></li><li data-type='method' style='display: none;'><a href="AccessLogger.html#logRequest">logRequest</a></li></ul></li><li><a href="FaceboxTemplate.html">FaceboxTemplate</a><ul class='methods'><li data-type='method' style='display: none;'><a href="FaceboxTemplate.html#render">render</a></li><li data-type='method' style='display: none;'><a href="FaceboxTemplate.html#renderCode">renderCode</a></li><li data-type='method' style='display: none;'><a href="FaceboxTemplate.html#renderFile">renderFile</a></li></ul></li><li><a href="FSLibrary.html">FSLibrary</a></li><li><a href="LoggerBuilder.html">LoggerBuilder</a><ul class='methods'><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#decorateGlobalLogger">decorateGlobalLogger</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#error">error</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#info">info</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#log">log</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#prettyCli">prettyCli</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#prompt">prompt</a></li><li data-type='method' style='display: none;'><a href="LoggerBuilder.html#warn">warn</a></li></ul></li><li><a href="SGAppsServer.html">SGAppsServer</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServer.html#all">all</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#connect">connect</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#delete">delete</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#Email">Email</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#finalHandler">finalHandler</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#get">get</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#handle">handle</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#handleErrorRequest">handleErrorRequest</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#handlePostData">handlePostData</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#handleRequest">handleRequest</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#handleStaticRequest">handleStaticRequest</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#head">head</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#options">options</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#patch">patch</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#post">post</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#put">put</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#server">server</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#trace">trace</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.html#use">use</a></li></ul></li><li><a href="SGAppsServer.NodeJsMvc.html">NodeJsMvc</a></li><li class="level-hide"><a href="SGAppsServer.NodeJsMvc.Controller.html">Controller</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#actionExists">actionExists</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#addAction">addAction</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#addView">addView</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#getAction">getAction</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#getView">getView</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#removeAction">removeAction</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#removeView">removeView</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#render">render</a></li><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.html#viewExists">viewExists</a></li></ul></li><li class="level-hide"><a href="SGAppsServer.NodeJsMvc.Controller.Action.html">Action</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServer.NodeJsMvc.Controller.Action.html#run">run</a></li></ul></li><li><a href="SGAppsServerDecoratorsLibrary.html">SGAppsServerDecoratorsLibrary</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerDecoratorsLibrary.html#.AccessLoggerDecorator">AccessLoggerDecorator</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerDecoratorsLibrary.html#.NodeJsMvcDecorator">NodeJsMvcDecorator</a></li></ul></li><li><a href="SGAppsServerDictionary.html">SGAppsServerDictionary</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerDictionary.html#generatePathKey">generatePathKey</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerDictionary.html#push">push</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerDictionary.html#run">run</a></li></ul></li><li><a href="SGAppsServerEmail.html">SGAppsServerEmail</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerEmail.html#.from">from</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerEmail.html#.isValidAddress">isValidAddress</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerEmail.html#.timeout">timeout</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerEmail.html#send">send</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerEmail.html#valid">valid</a></li></ul></li><li><a href="SGAppsServerRequest.html">SGAppsServerRequest</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerRequest.html#_parseDeepFieldName">_parseDeepFieldName</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerRequest.html#getMountUpdatedUrl">getMountUpdatedUrl</a></li></ul></li><li><a href="SGAppsServerRequestCookie.html">SGAppsServerRequestCookie</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerRequestCookie.html#get">get</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerRequestCookie.html#set">set</a></li></ul></li><li><a href="SGAppsServerRequestSession.html">SGAppsServerRequestSession</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerRequestSession.html#destroy">destroy</a></li></ul></li><li><a href="SGAppsServerResponse.html">SGAppsServerResponse</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#pipeFile">pipeFile</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#pipeFileStatic">pipeFileStatic</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#redirect">redirect</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#send">send</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#sendError">sendError</a></li><li data-type='method' style='display: none;'><a href="SGAppsServerResponse.html#sendStatusCode">sendStatusCode</a></li></ul></li><li><a href="SGAppsServerShared.html">SGAppsServerShared</a></li><li><a href="SGAppsSessionManager.html">SGAppsSessionManager</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SGAppsSessionManager.html#handleRequest">handleRequest</a></li><li data-type='method' style='display: none;'><a href="SGAppsSessionManager.html#removeExpiredSessions">removeExpiredSessions</a></li></ul></li><li><a href="TemplateManager.html">TemplateManager</a><ul class='methods'><li data-type='method' style='display: none;'><a href="TemplateManager.html#add">add</a></li><li data-type='method' style='display: none;'><a href="TemplateManager.html#addList">addList</a></li><li data-type='method' style='display: none;'><a href="TemplateManager.html#get">get</a></li><li data-type='method' style='display: none;'><a href="TemplateManager.html#remove">remove</a></li><li data-type='method' style='display: none;'><a href="TemplateManager.html#render">render</a></li><li data-type='method' style='display: none;'><a href="TemplateManager.html#templateExists">templateExists</a></li></ul></li><li><a href="TemplateManagerViewer.html">TemplateManagerViewer</a><ul class='methods'><li data-type='method' style='display: none;'><a href="TemplateManagerViewer.html#render">render</a></li><li data-type='method' style='display: none;'><a href="TemplateManagerViewer.html#renderCode">renderCode</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#LoggerBuilderPrompt">LoggerBuilderPrompt</a></li><li><a href="global.html#MountUpdatedURL">MountUpdatedURL</a></li><li><a href="global.html#RequestHandler">RequestHandler</a></li><li><a href="global.html#RequestPathStructure">RequestPathStructure</a></li><li><a href="global.html#RequestPathStructureMap">RequestPathStructureMap</a></li><li><a href="global.html#RequestSessionDecorator">RequestSessionDecorator</a></li><li><a href="global.html#ResourcesExtensions">ResourcesExtensions</a></li><li><a href="global.html#routeMatch">routeMatch</a></li><li><a href="global.html#SGAppsServerDecorator">SGAppsServerDecorator</a></li><li><a href="global.html#SGAppsServerDictionaryRunCallBack">SGAppsServerDictionaryRunCallBack</a></li><li><a href="global.html#SGAppsServerErrorCallBack">SGAppsServerErrorCallBack</a></li><li><a href="global.html#SGAppsServerErrorOnlyCallback">SGAppsServerErrorOnlyCallback</a></li><li><a href="global.html#SGAppsServerHandlerPostData">SGAppsServerHandlerPostData</a></li><li><a href="global.html#SGAppsServerOptions">SGAppsServerOptions</a></li><li><a href="global.html#SGAppsServerRequestFile">SGAppsServerRequestFile</a></li><li><a href="global.html#SGAppsServerRequestPostDataItem">SGAppsServerRequestPostDataItem</a></li><li><a href="global.html#SGAppsServerRequestSessionCache">SGAppsServerRequestSessionCache</a></li><li><a href="global.html#SGAppsSessionManagerOptions">SGAppsSessionManagerOptions</a></li><li><a href="global.html#TemplateManagerRenderOptions">TemplateManagerRenderOptions</a></li><li><a href="global.html#TemplateManagerTemplate">TemplateManagerTemplate</a></li></ul> </nav> <div id="main"> <h1 class="page-title">prototypes/server/extend/request-session.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>const _cluster = require('cluster'); /** * @class * @name SGAppsServerRequestSession * @param {SGAppsServerRequest} request * @param {SGAppsSessionManagerOptions} options */ function SGAppsServerRequestSessionBuilder(request, options) { /** * @typedef {object} SGAppsSessionManagerOptions * @property {number} [SESSION_LIFE=600] * @property {string} [cookie='ssiddyn'] */ /** * @typedef {object} SGAppsServerRequestSessionCache * @property {number} expire * @property {object} data */ /** * @memberof SGAppsServerRequestSession# * @name _created * @type {number} */ this._created = new Date().valueOf(); var _this = this; /** * @memberof SGAppsServerRequestSession# * @name _ip * @type {string} */ this._ip = ( ( request.request ? ( Array.isArray(request.request.headers['x-forwarded-for']) ? ( request.request.headers['x-forwarded-for'][0] ) : request.request.headers['x-forwarded-for'] ) : null ) || ( ( request.request &amp;&amp; request.request.connection ) ? request.request.connection.remoteAddress : null ) || ( ( request.request &amp;&amp; request.request.socket ) ? request.request.socket.remoteAddress : null ) || '' ); /** * Session was received from previously saved cookie * @memberof SGAppsServerRequestSession# * @name _confirmed * @type {boolean} */ this._confirmed = false; /** * @memberof SGAppsServerRequestSession# * @name _id * @type {string} */ this._id = request.cookies ? ( request.cookies.get( options.cookie, { secure: true } ) || request.cookies.get( options.cookie, { secure: false } ) || null ) : null; if (this._id === null) { this._id = `sess-${ Math.floor(1E6 + 1E6 * Math.random()).toString(36) }-${ new Date().valueOf().toString(36) }`; request.cookies.set( options.cookie, this._id, { secure: true }, true ); request.cookies.set( options.cookie, this._id, { secure: false }, true ); } else { this._confirmed = true; } /** * @memberof SGAppsServerRequestSession# * @name _options * @type {SGAppsSessionManagerOptions} */ this._options = Object.assign( { SESSION_LIFE: 600, cookie: 'ssiddyn' }, options || {} ); /** * @memberof SGAppsServerRequestSession# * @name data * @type {object} */ this.data = null; /** * @memberof SGAppsServerRequestSession# * @method destroy */ this.destroy = function () { _this.data = null; _this._id = null; _this._ip = null; _this._options = null; delete _this.destroy; }; return this; } /** * @class * @name SGAppsSessionManager * @param {SGAppsServer} server * @param {SGAppsSessionManagerOptions} [options] */ function SGAppsSessionManager(server, options) { /** * @memberof SGAppsSessionManager# * @name _options * @type {SGAppsSessionManagerOptions} */ this._options = Object.assign( { SESSION_LIFE: 600, cookie: 'ssiddyn', workersSyncMaxDelay: 200 }, options || {} ); /** * @memberof SGAppsSessionManager# * @name _enabled * @type {boolean} */ this._enabled = true; /** * @memberof SGAppsSessionManager# * @name _sessions * @type {Object&lt;string,SGAppsServerRequestSessionCache>} */ this._sessions = {}; return this; }; /** * @memberof SGAppsSessionManager# * @method removeExpiredSessions */ SGAppsSessionManager.prototype.removeExpiredSessions = function () { const time = new Date().valueOf(); let sessionId; for (sessionId in this._sessions) { if (this._sessions[sessionId].expire &lt;= time) { this._sessions[sessionId].data = null; delete this._sessions[sessionId]; } } }; /** * @memberof SGAppsSessionManager# * @method handleRequest * @param {SGAppsServerRequest} request */ SGAppsSessionManager.prototype.handleRequest = function (request) { request.session = new SGAppsServerRequestSessionBuilder( request, this._options ); const SessionManager = this; if (request.session._id in SessionManager._sessions) { request.session.data = SessionManager._sessions[request.session._id].data; SessionManager._sessions[request.session._id].expire = request.session._created + SessionManager._options.SESSION_LIFE * 1000; } else { SessionManager._sessions[request.session._id] = { expire: request.session._created + SessionManager._options.SESSION_LIFE * 1000, data: {} }; request.session.data = SessionManager._sessions[request.session._id].data; } }; /** * @param {SGAppsServerRequest} request * @param {SGAppsServerResponse} response * @param {SGAppsServer} server * @param {function} callback */ function RequestSessionDecorator(request, response, server, callback) { if ( request === null &amp;&amp; response === null ) { /** * @memberof SGAppsServer# * @name SessionManager * @type {SGAppsSessionManager} */ server.SessionManager = new SGAppsSessionManager(server); if (_cluster.isPrimary || _cluster.isMaster) { let workerId; const decorateWorker = (worker) => { worker.on('message', function (message) { if ( message &amp;&amp; typeof(message) === "object" &amp;&amp; ( 'type' in message ) &amp;&amp; typeof(message.type) === "string" &amp;&amp; typeof(message.pid) === "number" &amp;&amp; message.pid &amp;&amp; typeof(message.sessionId) === "string" &amp;&amp; message.sessionId ) { if ( message.type === "sgapps-server:session-manager:worker-data-request" ) { if ( (message.sessionId in server.SessionManager._sessions) &amp;&amp; typeof(server.SessionManager._sessions[message.sessionId].data) === "object" &amp;&amp; server.SessionManager._sessions[message.sessionId].data ) { server.SessionManager._sessions[message.sessionId].expire = new Date().valueOf() + server.SessionManager._options.SESSION_LIFE * 1000; worker.send({ type: "sgapps-server:session-manager:worker-data-response", sessionId: message.sessionId, data: server.SessionManager._sessions[message.sessionId].data, pid: process.pid }); } else { worker.send({ type: "sgapps-server:session-manager:worker-data-response", sessionId: message.sessionId, data: {}, pid: process.pid }); } } else if ( message.type === "sgapps-server:session-manager:worker-data-store" &amp;&amp; typeof(message.data) === "object" &amp;&amp; message.data ) { if ( (message.sessionId in server.SessionManager._sessions) &amp;&amp; typeof(server.SessionManager._sessions[message.sessionId].data) === "object" &amp;&amp; server.SessionManager._sessions[message.sessionId].data ) { Object.assign( server.SessionManager._sessions[message.sessionId].data, message.data ); server.SessionManager._sessions[message.sessionId].expire = new Date().valueOf() + server.SessionManager._options.SESSION_LIFE * 1000; } else { server.SessionManager._sessions[message.sessionId] = { expire: new Date().valueOf() + server.SessionManager._options.SESSION_LIFE * 1000, data: Object.assign({}, message.data) }; } } } }); }; _cluster.on('fork', (worker) => { decorateWorker(worker); }); for (workerId in _cluster.workers) { let worker = _cluster.workers[workerId]; decorateWorker(worker); } } setInterval(() => { //@ts-ignore server.SessionManager.removeExpiredSessions(); }, 5000); callback(); return; } if (!server.SessionManager._enabled) { callback(); return; } /** * @memberof SGAppsServerRequest# * @name session * @type {SGAppsServerRequestSession} */ server.SessionManager.handleRequest(request); if (_cluster.isPrimary || _cluster.isMaster) { response._destroy.push(function () { request.session.destroy(); delete request.session; }); callback(); } else { response._destroy.unshift(function () { process.send({ type: 'sgapps-server:session-manager:worker-data-store', sessionId: request.session._id, data: request.session.data, pid: process.pid }); }); response._destroy.push(function () { request.session.destroy(); delete request.session; }); process.send({ type: 'sgapps-server:session-manager:worker-data-request', sessionId: request.session._id, pid: process.pid }); let callbackSent = false; const callbackOnce = () => { if (callbackSent) return false; callbackSent = true; callback(); return true; } process.on('message', function (message) { if ( message &amp;&amp; typeof(message) === "object" &amp;&amp; request.session &amp;&amp; ( 'type' in message ) &amp;&amp; typeof(message.type) === "string" &amp;&amp; ( 'pid' in message ) &amp;&amp; typeof(message.pid) === "number" &amp;&amp; message.type === "sgapps-server:session-manager:worker-data-response" &amp;&amp; typeof(message.sessionId) === "string" &amp;&amp; message.sessionId === request.session._id &amp;&amp; typeof(message.data) === "object" &amp;&amp; message.data ) { request.session.data = Object.assign(request.session.data, message.data); callbackOnce(); } }); setTimeout(function () { if (callbackOnce()) server.logger.warn( process.pid, ' SessionSync between worker and master skipped after ' + server.SessionManager._options.workersSyncMaxDelay + 'ms' ); }, server.SessionManager._options.workersSyncMaxDelay); } }; module.exports = RequestSessionDecorator;</code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.5</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> <script src="scripts/search.js" defer></script> <script src="scripts/collapse.js" defer></script> <script src="https://sgapps.io/components/sgapps-labs-examples/toolbar/loader.js"></script> </body> </html>