UNPKG

rrestjs

Version:

HIgh performance node.js ROA & RESTFUL web framework.

309 lines (300 loc) 12.6 kB
/* *RestRes.js 是对response对象进行封装,并最小化程度的污染命名空间 * *具体封装的属性和方法详见rrestjs api */ var fs = require('fs'), http = require('http'), path = require('path'), RestUtils = require('./RestUtils'), mime = require('mime'), sendfile = require('./RestStatic'), sendfavicon = require('./RestFavicon'), restzlib = require('./RestZlib'), configZlib = _restConfig.isZlib, RestSession = require('./RestSession'), sessionName = RestSession.sessionName, tempSet = _restConfig.tempSet, JadeRender = require('./JadeRender'), ejsRender = require('./ejsRender'), outerror = require('./Outerror'), msg = require('./msg/msg'), RestRes404 = require('./RestRes404.js'), RestRes_errorres = require('./RestRes404.js').errorres, apiXmlToString = require('./apiXml').ToString,//解析xml数据格式 defaultcharset = _restConfig.charset, baseDir = _restConfig.baseDir, RestRes = module.exports = function(){ if(!(this instanceof arguments.callee)) return new arguments.callee(); this.res = http.ServerResponse.prototype; this._restResMethod = ['cache', 'send', 'sendjson', 'sendjsonp', 'sendfile', 'file', 'contenttype', 'download', 'r404', 'r403', 'r500', 'attachment', 'set', 'get', 'clearcookie', 'cookie', 'cookiep3p', 'redirect', 'render', 'compiletemp', 'favicon', 'links', 'api']; if(RestSession.isSession) this._restResMethod.push('gensession', 'updatesession', 'delsession'); //如果开启session支持 this._restdefine(this.res, this._restResMethod); //定义res对象的方法 }; RestRes.prototype={ _cache:function(res, type, maxAge){ //设置缓存头,如果想要此请求被缓存 var type = type; if(type === false){ res._nocache = true; return res; } if (maxAge){ if(maxAge < 0){ type += ', max-age=-1'; res._nocache = true; } else{ type += ', max-age=' + (maxAge / 1000); } } this._set(res, 'Cache-Control', type); return res; }, _send:function(res, body, statscode, iszlib, issession){ //核心函数,响应buffer或者字符串 var type, req = res._restReq, acceptEncoding = req.headers['accept-encoding'], issession = 'undefined' == typeof issession? true : issession, charset = res.charset || defaultcharset, body = body || ''; if(typeof body === 'number') body += ''; if(statscode) res.statusCode = statscode; //如果传递了http状态码 if(RestSession.isSession && issession) res.updatesession(req._restSessionObj); //更新session if(204 == res.statusCode || 304 == res.statusCode) { res.removeHeader('Content-Type'); res.removeHeader('Content-Length'); body = ''; } else if(!res.getHeader('Content-Type')) res.setHeader('Content-Type', 'text/html; charset='+charset); this._sercookie(res);//发送cookie if('undefined' === typeof iszlib) var iszlib = configZlib;//如果未单独传递gizp,则使用默认规则 if(iszlib && (type = restzlib.check(acceptEncoding))) restzlib.send(res, body, type); //是否使用gizp输出 else{ if(typeof body === 'string'){ res.setHeader('Content-Length', Buffer.byteLength(body, charset));//增加content-length长度 } else{ res.setHeader('Content-Length',body.length);//增加content-length长度 } body = RestUtils.headReq(req, body);//如果是head请求,则值响应http头,返回空 res.end(body);//正常输出 } return res; }, _sendjson:function(res, obj, statscode, iszlib, issession){ //json字符串输出 this._contenttype(res, '.json'); this._send(res, JSON.stringify(obj), statscode, iszlib, issession); return res; }, _sendjsonp:function(res, obj, statscode, iszlib, issession){//jsonp支持,参数必须为小写的 callback var body = JSON.stringify(obj), callback = res._restReq.getparam['callback']; res.setHeader('Content-Type', 'text/javascript'); if(callback){ body = callback.replace(/[^\w$.]/g, '') + '(' + body + ');'; this._send(res, body, statscode, iszlib, false); } else res.send(msg.resmsg.resJsonpError); return res; }, _sendfile:function(res, filepath, callback){//响应文件 if(!filepath) return callback(msg.errmsg.resFilepathError); sendfile(res, filepath, callback); return res; }, _file:function(res, filepath, callback){//响应文件,这个api是输出相对于 if(!filepath) return callback(msg.errmsg.resFilepathError); sendfile(res, baseDir+filepath, callback); return res; }, _contenttype:function(res, filename){ //设置 Content-Type 的值 var charset = res.charset || defaultcharset; res.setHeader('Content-Type', mime.lookup(filename)+'; charset='+charset); return res; }, _attachment:function(res, filename){ //设置下载头 if(filename) this._contenttype(res, filename); res.setHeader('Content-Disposition', 'attachment; filename="' + path.basename(filename) + '"'); return this; }, _download:function(res, filepath, fn){ //响应下载 this._attachment(res, filepath)._sendfile(res, filepath, fn); return res; }, _r404:function(res, filepath, fn){ //响应下载 if (2 == arguments.length && 'function' === typeof filepath){ var fn = filepath, filepath = false; } RestRes404(res, filepath, fn); return res; }, _r403:function(res, fn){ RestRes_errorres(res, fn, 403) return res; }, _r500:function(res, fn){ RestRes_errorres(res, fn, 500) return res; }, _set:function(res, field, val){ //设置响应头 if (3 == arguments.length) res.setHeader(field, val); else for (var key in field) res.setHeader(key, field[key]); return res; }, _get:function(res, field){ //获得响应头 res.getHeader(field); return res; }, _clearcookie:function(res, name){ //清除cookie var opts = { expires: new Date(1), path: '/' }; this._cookie(res, name, '', opts); return res; }, _cookie:function(res, name, val, options){ //设置cookie var options = options || {}; if ('object' == typeof val) val = 'j:' + JSON.stringify(val); if (options.maxAge) options.expires = new Date(Date.now() + options.maxAge); if (null == options.path) options.path = '/'; var cookie = RestUtils.serializeCookie(name, val, options); if(!res._restcookieobj) res._restcookieobj = {}; res._restcookieobj[name] = { name:name, val:val, options:options, } return res; }, _cookiep3p:function(res){ res.setHeader('p3p', 'CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"') return res; }, _sercookie:function(res){ if(!res._restcookieobj) return; var cookiestr = '', co,coarray=[]; for(var j in res._restcookieobj){ co = res._restcookieobj[j]; coarray.push(RestUtils.serializeCookie(j, co.val, co.options)); } res.setHeader('Set-Cookie', coarray); }, _redirect:function(res, url, statecode){ //跳转 if(url == 'back') var url = res.get('Referrer')||'/'; this._set(res, {'Location':url, 'Content-Type':'text/plain'}).statusCode = statecode || 302; this._cache(res, 'no-cache'); res.send(msg.tipsmsg.resRedirect + url); return res; }, _render:function(res, view, ispage, options, fn, iscompile){ //输出模版 var arg = [].slice.call(arguments, 0), tpRender = iscompile? templateRender.compiler:templateRender.render; if(arg[1].indexOf('.') === -1){//如果不传.jade则默认加上后缀名 arg[1] += '.'+tempSet; } arg = arg.filter(function(value){ if('undefined' === typeof value || value === true) return false; return true; }); if(view === 'auto'){ var pathary = res._restReq.path; arg[1] = '/'+pathary[0]+'/'+pathary[1]+'.'+tempSet;//自动拼接模版地址 } if(arg.length === 2){//如果只2个参数,view必传 tpRender(arg[0], arg[1], '', {}, function(){}); } else if(arg.length === 3){//传3个参数,则可能是options和fn if('function' === typeof arg[2]) tpRender(arg[0], arg[1], '', {}, arg[2]); else tpRender(arg[0], arg[1], '', arg[2], function(){}); } else if(arg.length === 4){//如果传递4个参数,则可能options后者fn没穿 if('function' === typeof arg[3]) tpRender(arg[0], arg[1], '', arg[2], arg[3]); else tpRender(arg[0], arg[1], arg[2], arg[3], function(){}); } else tpRender.apply(null, arg); //如果传递参数是4个,表示此页面无需分页,则ispage设置为空 return res; }, _compiletemp:function(res, view, ispage, options, fn){//编译模版 var arg = [].slice.call(arguments, 0); arg[5] = true; this._render.apply(this, arg); }, _favicon:function(res, filepath){ //输出favicon sendfavicon(res, filepath); return res; }, _gensession:function(res, obj, callback){ //创建sessionid入口 var callback = callback || function(){}, obj = obj || {}; return RestSession.genSession(obj, function(err, _restsid, sobj){ var reqobj = res._restReq; reqobj._restSessionObj = sobj; //更新req对象的 _restSessionObj 对象,因为第一次创建,否则为 undefined var sessionName = reqobj._sessionName;//设置sessionName,不使用默认配置的,为了支持sepSeesion res.cookie(sessionName, _restsid, {maxAge: RestSession.expire, path:reqobj._sessionPath || '/'}); //设置cookie callback(err, sobj); }); }, _updatesession:function(res, obj){ //更新session if(obj && obj._restsid){ var _restsid = obj._restsid; var reqobj = res._restReq; var sessionName = reqobj._sessionName;//设置sessionName,不使用默认配置的,为了支持sepSeesion res.cookie(sessionName, _restsid, {maxAge: RestSession.expire, path:reqobj._sessionPath || '/'}); RestSession.updateSession(_restsid, obj); } return res; }, _delsession:function(res){ //删除session var _restsid = this._restgetSessionId(res); if(_restsid){ res.cookie(sessionName, _restsid, {maxAge:-1}); RestSession.delSession(_restsid); } return res; }, _links:function(res, links){//copy from expressjs return res.set('Link', Object.keys(links).map(function(rel){ return '<' + links[rel] + '>; rel="' + rel + '"'; }).join(', ')); }, _api:function(res, obj){ if(typeof obj !== 'object'){ return RestUtils.errorRes(res, msg.errmsg.resapiError, 500); } var reqobj = res._restReq, that = this; if(reqobj._accept === 'xml'){ apiXmlToString(obj, function(err, xml){ var charset = res.charset || defaultcharset; if(err) return RestUtils.errorRes(res, msg.errmsg.resapiError, 500); res.setHeader('Content-Type', 'application/xml; charset='+charset); res.send(xml); }) } else{ that._sendjson(res, obj) } }, _restgetSessionId:function(res){ //根据请求对象,获得sessionid return RestUtils.parseJSONCookies(RestUtils.parseCookie(res._restReq.headers.cookie||''))[sessionName] || false; }, _restdefine:function(res, array){ //定义res的方法 var that = this; array.forEach(function(value, i){ res[value] = (function(value){ return function(){ var arg = Array.prototype.slice.apply(arguments); arg.unshift(this); return that['_'+value].apply(that, arg); } })(value) }); }, }; var templateRender = function(){//选择模版输出 var errfn = function(res){//否则模版设置错误 RestUtils.errorRes(res, msg.resmsg.templateSetError); }; if(tempSet === 'jade') return {render:JadeRender, compiler:JadeRender.compiler}; //输出jade模版 else if(tempSet === 'ejs') return {render:ejsRender, compiler:ejsRender.compiler};//输出ejs模版 else return {render:errfn, compiler:errfn}; }()