UNPKG

epi

Version:

A Api Service Framework Base On Express.js

724 lines (545 loc) 18.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: HttpServer.js</title> <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-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: HttpServer.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * @desc 封装express创建服务的方法 * @author sam * @version 0.8.3 * */ var https = require('https'); var cluster = require('cluster'); var os = require('os'); var util = require('util'); var EventEmitter = require('events').EventEmitter; var express = require('express'); /** * @desc 创建一个http服务程序,包括https和http服务 * @constructor HttpServer * @this {HttpServer} * @param {Object} options * @example * * *'use strict'; * *var HttpServer = require('epi').HttpServer; * *var util = require('util'); * * var config = { * host : null, * key : 'string', //https监听时需要这个key * cert : 'string', //https监听的时候需要证书 * version : '1.0.0' //api默认的版本信息 * port : { * http : 8000, //如果想要监听http端口,直接写 * https : 4433 //如果不想监听https,直接置为null * } * } * * //创建一个httpServer===================================== * var httpServer = new HttpServer(config); * * * //设置================================================== * httpServer.setting(function (app) { * app.set('trust proxy', true); * app.set('x-powered-by', false); * }); * //导入中间件============================================= * var body = require('body-parser'); * var cookie = require('cookie-parser'); * var compression = require("compression"); * * //应用中间件 * httpServer.use(function (app) { * app.use(compression()); * app.use(cookie()); * app.use(body.json()); * app.use(body.urlencoded({ * extended: true * })); * }); * * * //导入路由============================================== * var testRouter = require('./router/test'); * * //注册路由 * testRouter.map(httpServer); * //错误处理============================================= * httpServer.error(function (err, req, res, next) { * console.error(err.stack); * res.status(500).json({ * error: err * }); * }); * */ var HttpServer = function (options) { /* * * { * host : null, * key : 'string', * cert : 'string', * version : '1.0.0' //api默认的版本信息 * port : { * http : 8000, * https : 4433 * } * } * */ options = options || {}; EventEmitter.call(this); this.__host = options.host || null; this.__version = options.version; this.__key = options.key; this.__cert = options.cert; this.__port = { http: options.port.http, https: options.port.https }; this.__server = null; /** * 如果调用cluster方法启动程序,所有子进程都在这里 * */ this.workers = null; /** * express 创建的app,如果想调用express的相关方法,可以使用这个app * */ this.app = null; this.__init(); }; util.inherits(HttpServer, EventEmitter); /** * @desc 初始化系统 * @access private * */ HttpServer.prototype.__init = function () { this.app = express(); if (this.__port.https) { if (!this.__key || !this.__cert) { throw new Error('listen https need key and cert'); } this.__server = https.createServer({ key: this.__key, cert: this.__cert }, this.app); } /** * 用于解析version和device的中间件 * 添加一个解析version和device设备类型的中间件 */ this.app.use(function (req, res, next) { req.startTime = Date.now(); req.version = req.get('accept-version') || req.query.version; req.channel = req.get('client-channel') || req.query.channel; req.cache = { use : req.get('use-api-cache') ? true : false, ttl : null, check : function(callback){ callback(); } }; next(); }); return this.app; }; /*** * @desc handler * */ var routerHandler = function (options, handler, ttl) { return function(req, res, next){ if (options.v &amp;&amp; req.version !== options.v) { return next(); } if (options.c &amp;&amp; req.channel !== options.c) { return next(); } if(util.isNumber(cache) &amp;&amp; req.cache &amp;&amp; (req.cache.use == true) &amp;&amp; util.isFunction(req.cache.check)){ req.cache.check(function(err, result){ if(!err &amp;&amp; result){ res.set('data-from-cache', 'true'); return res.send(result); }else{ req.cache.ttl = ttl; handler(req, res, next); } }); }else{ handler(req, res, next); } } }; /** * @desc Router.all 相当于express router.all * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.all('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.all('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.all('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.all = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.all(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.get 相当于express router.get * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.get('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.get('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.get('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.get = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } var self = this; options = options || {}; options.v = options.v || self.__version; self.app.get(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.post 相当于express router.post * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.post('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.post('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.post('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.post = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.post(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.put 相当于express router.put * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.put('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.put('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.put('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.put = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.put(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.delete 相当于express router.delete * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.delete('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.delete('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.delete('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.delete = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.delete(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.header 相当于express router.header * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.header('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.header('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.header('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.header = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.header(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.options 相当于express router.options * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.options('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.options('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.options('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.options = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.options(path, routerHandler(options, handler, ttl)); }; /** * @desc Router.trace 相当于express router.trace * @param {String | Regex} path '/api/name' | /^\/api\/name$/ * @param {String} options .v '1.0.1' * @param {String} options .c 你定义的频道类型 * @param handler {Function} function(req, res, next){} * @param ttl {Number} 设置api缓存时间 * @example * 使用缓存: * httpServer.trace('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, 100) * * 不使用 * httpServer.trace('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}) * httpServer.trace('/test', {v : '1.0.0', c : 'pc'}, function(req, res, next){}, null) * */ HttpServer.prototype.trace = function (path, options, handler, ttl) { if (!util.isObject(options)) { throw new Error('options is object {v : "1.0.0", c : "pc"}'); } options = options || {}; options.v = options.v || this.__version; this.app.trace(path, routerHandler(options, handler, ttl)); }; /** * @desc 设置程序属性 * @param {Function} fn function(app){} * @example * httpServer.setting(function (app) { * app.set('trust proxy', true); * app.set('x-powered-by', false); * }); * */ HttpServer.prototype.setting = function (fn) { fn(this.app); }; /** * @desc 应用中间件 * @param fn {Function} function(app){} * @example * httpServer.use(function(app){ * app.use(compression()); * app.use(timeout('10s')); * app.use(cookie()); * app.use(body.json()); * }); * */ HttpServer.prototype.use = function (fn) { fn(this.app); }; /** * @desc 注册路由 * @param fn {Function} function(app){} * */ HttpServer.prototype.route = function (fn) { fn(this.app); }; /** * @desc 添加错误处理 * @param fn {Function} function(err, req, res, next){} * */ HttpServer.prototype.error = function (fn) { this.app.use(function (err, req, res, next) { fn(err, res, res, next); }); }; /** * @desc 监听端口 * @param callback {Function} 监听后返回的消息 * @example * httpServer.listen(8000, function(err, message){ * console.log(message); * }) * */ HttpServer.prototype.listen = function (callback) { if (!this.__port.http &amp;&amp; !this.__port.https) { throw new Error('port.http or port.https is not set'); } var listenMessage = ''; var flag = 0; var count = 0; var self = this; if (this.__port.http) { count++; } if (this.__port.https) { count++; } if (this.__port.http) { this.app.listen(this.__port.http, self.__host, function (err) { flag++; if (err) { listenMessage += err.message; } var host = self.__host || '127.0.0.1'; listenMessage += 'server listen on : http://' + host + ':' + self.__port.http + ', pid : ' + process.pid; if (flag >= count) { self.emit('listen', self.__port.http); callback &amp;&amp; callback(listenMessage); } }); } if (this.__port.https) { this.__server.listen(this.__port.https, self.__host, function (err) { flag++; if (err) { listenMessage += err.message; } var host = self.__host || '127.0.0.1'; listenMessage += '\nserver listen on : https://' + host + ':' + self.__port.https + ', pid : ' + process.pid; if (flag >= count) { self.emit('listen', self.__port.https); callback &amp;&amp; callback(listenMessage); } }); } }; /** * @desc 以集群的方式启动程序 * @param number {Number} 要启动的监听进程数量,null || 0 启动和 cpu个数 - 1 的进程数量 * @param callback {Function} 监听后返回的消息 * @example * //子进程启动事件 * httpServer.on('childStart', function(worker){ * //记录子进程启动 * logger.info(Date.now(), worker.pid); * }); * * * //子进程退出事件 * httpServer.on('childStop', function(worker, code, signal){ * //记录子进程非正常退出 * if(!signal &amp;&amp; code !== 0){ * logger.fatal(Date.now(), worker.pid, code, signal); * } * }); * * //子进程退出事件 * httpServer.on('childRestart', function(worker){ * //记录子进程重启 * logger.fatal(Date.now(), worker.pid); * }); * * * //使用集群方式监听======================================= * httpServer.cluster(0, function (message) { * console.log(message); * }); * */ HttpServer.prototype.cluster = function (number, callback) { var self = this; var cpuCount = number || os.cpus().length - 1; self.workers = {}; if (cluster.isMaster) { for (var i = 0; i &lt; cpuCount; i++) { var workerProcess = cluster.fork(); self.workers[workerProcess.process.pid] = workerProcess; self.emit('childStart', workerProcess); } cluster.on('exit', function (worker, code, signal) { self.emit('childStop', worker, code, signal); delete self.workers[worker.process.pid]; setTimeout(function(){ var workProcess = cluster.fork(); self.workers[workProcess.process.pid] = cluster.fork(); self.emit('childRestart', workProcess); }, 1000); }); } else { self.listen(callback); } }; exports.HttpServer = HttpServer;</code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="HttpServer.html">HttpServer</a></li></ul><h3>Global</h3><ul><li><a href="global.html#app">app</a></li><li><a href="global.html#https">https</a></li><li><a href="global.html#workers">workers</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.2</a> on Sun Sep 20 2015 11:45:44 GMT+0800 (CST) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>