UNPKG

sgapps-server

Version:
494 lines (429 loc) 24.7 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>prototypes/dictionary.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/dictionary.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>const parseParams = require('application-prototype/constructors/request/params-parser'); /** * * @param {RequestPathStructure} route * @param {string} url * @param {boolean} strictRouting * @param {object} _cache */ function routeMatch(route, url, strictRouting, _cache) { if ( route === '*' || route === '/*' || route === '^/*' || ( !strictRouting &amp;&amp; ( route === '/' ) ) ) return true; if (typeof (route) === "string") { // if ( // route[1] !== url[1] // ) return false; if ( url === route ) { return true; } else if ( url.indexOf(route) === 0 &amp;&amp; !strictRouting ) { return true; } else if ( strictRouting &amp;&amp; url.indexOf(route) === 0 &amp;&amp; ( ( // /path/route/ --- /path/route/ url.length === route.length ) || ( // /path/route? --- /path/route url[route.length - 1] === '?' ) ) ) { return true; } else if ( !strictRouting &amp;&amp; //@ts-ignore url.indexOf(route.subs(0, -1)) === 0 &amp;&amp; ( url.length === route.length - 1 || ( ( url[route.length - 1] === '?' || url[route.length - 1] === '/' ) &amp;&amp; route[route.length - 1] === '/' ) ) ) { const params = parseParams(url, route, { cache: _cache || {} }); if ( params !== null ) { return params || true; } } else { return false; } } else if (route &amp;&amp; route instanceof RegExp) { const result = route.exec(url); if (result) { const { groups } = result; return groups || true; } else { return false; } } return false; } /** * @typedef {object} RequestPathStructureMap * @property {string} key * @property {RequestPathStructure} path * @property {Array&lt;RequestHandler>} handlers */ /** * @class * @name SGAppsServerDictionary * @description a dictionary for storing * @param {object} [options] * @param {string} [options.name=""] * @param {boolean} [options.reverse=false] */ function SGAppsServerDictionary(options) { /** * @memberof SGAppsServerDictionary# * @name _paths * @type {Array&lt;RequestPathStructureMap>} */ this._paths = []; /** * @memberof SGAppsServerDictionary# * @name _dictionary * @type {Object&lt;string,Array&lt;RequestHandler>>} */ this._dictionary = {}; this._cache = {}; this._options = Object.assign( { reverse: false, name: "" }, options || {} ); /** * @memberof SGAppsServerDictionary# * @method generatePathKey * @param {RequestPathStructure} path * @returns {string} */ this.generatePathKey = function (path) { if (typeof(path) === "string") { return `s:${path}`; } else if (path instanceof RegExp) { return `r:${path.toString()}`; } else { return `*:${path}`; } }; return this; } /** * @example * server.get('/', (req, res) => { * res.send('root'); * }) * // will match "test" "best", everything with est * server.get(/.*est/, (req, res) => { * res.send('root'); * }) * server.get('/:name/:surname', (req, res) => { * const { name, surname } = req.params; * res.send(`Hi ${name} ${surname}`); * }) * // apply rules with regexp emulation, they are marked with "^" in the start * server.get('^/:name([a-z]+)/:age(\d+)', (req, res, next) => { * const { name, age } = req.params; * if (age &lt; 18) { * res.send(`Hi ${name}, you are not allowed`); * } else { * next() * } * }) * // apply rules with regexp emulation, they are marked with "^" in the start * server.get('^/([a-z]+)/', (req, res, next) => { * const { name, age } = req.params; * if (age &lt; 18) { * res.send(`Hi ${name}, you are not allowed`); * } else { * next() * } * }) * // add regular expression with group names * server.get('^/(?&lt;test>[a-z]+)/', (req, res, next) => { * const { test } = req.params; * res.send(`param: ${test}`); * }) * server.get('/', (req, res) => { * res.send('root'); * }) * * @memberof SGAppsServerDictionary# * @method push * @param {RequestPathStructure} path * @param {RequestHandler[]} handlers */ SGAppsServerDictionary.prototype.push = function (path, handlers) { if (path === '') path = '*'; const pathKey = this.generatePathKey(path); if (typeof(path) === "string" &amp;&amp; path[0] === "^") { // (?&lt;name>...) const rule = path .replace(/([^\w\*\$\{\}\|\+\?\#\!&lt;\>\\\(\)\[\]\-\=\,\.\~\:\;\&amp;\^])/g,'\\$1') .replace(/\/\*$/, '\/.*') .replace(/\:([a-zA-Z][a-zA-Z\d]*)\((.*?)\)/g, '(?&lt;$1>$2)') .replace(/\:([a-zA-Z][a-zA-Z\d]*)/g, '(?&lt;$1>[^\/\:]+)') + '$'; //@ts-ignore const regRule = rule.toRegexp(); if (regRule &amp;&amp; (regRule instanceof RegExp)) { path = regRule; } } if (this._options.reverse) { this._paths.unshift({ key: pathKey, path, // : handlers.map(v => v).reverse() handlers }); } else { this._paths.push({ key: pathKey, path, handlers }); } }; /** * @callback SGAppsServerDictionaryRunCallBack * @param {SGAppsServerRequest} request * @param {SGAppsServerResponse} response * @param {SGAppsServer} server */ /** * @memberof SGAppsServerDictionary# * @method run * @param {SGAppsServerRequest} request * @param {SGAppsServerResponse} response * @param {SGAppsServer} server * @param {SGAppsServerDictionaryRunCallBack} callback */ SGAppsServerDictionary.prototype.run = function (request, response, server, callback) { let index = 0; const { strictRouting } = server._options; // const url = request.request.url; const url = request.urlInfo.pathname.replace(/^\/+/, '/'); const _cache = this._cache; const _debug = server.logger._debug; let _errorDetected = null; let next = () => { if (_errorDetected) { server.handleErrorRequest( request, response, _errorDetected ); } else if (!this._paths[index]) { callback(request, response, server); } else { const matchResult = routeMatch( this._paths[index].path, url, strictRouting, _cache ); // TODO apply cache // IF response is 200 &amp;&amp; matched by a string path // TODO add cache pathname|pathkey // TODO add cache pathname|handlers // console.info( // { // matchResult, // url, // path: this._paths[index].path, // strictRouting // } // ); if (typeof(matchResult) === "object" &amp;&amp; matchResult) { request.params = Object.assign( request.urlInfo.pathname.split('/'), matchResult ); } if ( !!matchResult ) { let itemIndex = 0; let itemNext = () => { if (_errorDetected) { next(); } else if (itemIndex >= this._paths[index].handlers.length) { index++; next(); } else { let err, timer = null; let _startTime = _debug ? ( new Date().valueOf() ) : null; let _endTime = null; const path = this._paths[index].path; if (_debug) { timer = setTimeout(() => { if (request._flags.aborted || response._flags.finished || _endTime !== null) return; const endTime = _endTime || new Date().valueOf(); if ( typeof(request._flags._DEBUG_MAX_HANDLER_EXECUTION_TIME) === "number" &amp;&amp; request._flags._DEBUG_MAX_HANDLER_EXECUTION_TIME >= 1 ) { var remain = request._flags._DEBUG_MAX_HANDLER_EXECUTION_TIME - ( endTime - _startTime ); if (remain > 0) { timer = setTimeout(() => { if (request._flags.aborted || response._flags.finished || _endTime !== null) return; const endTime = _endTime || new Date().valueOf(); server.logger.warn( `[SGAppsServer.Handler] Max Execution time exceeded ( ${ request._flags._DEBUG_MAX_HANDLER_EXECUTION_TIME } ms ) ; time spend ${_endTime === null ? 'more than' : ''} ${ endTime - _startTime } ms` ); server.logger.warn(this._paths[index].path); server.logger.warn(this._paths[index].handlers[itemIndex].toString()); }, remain); } else { server.logger.warn( `[SGAppsServer.Handler] Max Execution time exceeded ( ${ server._options._DEBUG_MAX_HANDLER_EXECUTION_TIME } ms ) ; time spend ${_endTime === null ? 'more than' : ''} ${ endTime - _startTime } ms` ); server.logger.warn(this._paths[index].path); server.logger.warn(this._paths[index].handlers[itemIndex].toString()); } } else { server.logger.warn( `[SGAppsServer.Handler] Max Execution time exceeded ( ${ server._options._DEBUG_MAX_HANDLER_EXECUTION_TIME } ms ) ; time spend ${_endTime === null ? 'more than' : ''} ${ endTime - _startTime } ms` ); server.logger.warn(this._paths[index].path); server.logger.warn(this._paths[index].handlers[itemIndex].toString()); } }, server._options._DEBUG_MAX_HANDLER_EXECUTION_TIME); } try { this._paths[index].handlers[itemIndex] .apply( server, [ request, response, function () { if (_debug &amp;&amp; timer !== null) { _endTime = new Date().valueOf(); if (server._options._DEBUG_REQUEST_HANDLERS_STATS) { server.logger.info( `[STATS] ${request.request.method} ${path} : `, { time: _endTime - _startTime, bytesRead: (request.request.socket || {}).bytesRead || 0, bytesWritten: (request.request.socket || {}).bytesWritten || 0, url: request.request.url } ); } clearTimeout(timer); timer = null; } itemIndex++; itemNext(); } ] ); } catch (err) { _errorDetected = err; // TODO Server Error page handler server.logger.error(err); if (_debug) { _endTime = new Date().valueOf(); } itemNext(); } } }; itemNext(); } else { index++; next(); } } }; next(); }; module.exports = SGAppsServerDictionary;</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>