UNPKG

zeanium-node

Version:

Zeanium for Node.js, simple http server and custome your business.

389 lines (369 loc) 15.8 kB
/** * Created by yangyxu on 8/20/14. */ zn.define([ '../../templete/html/exports.js', './config/zn.mime.config.js', 'node:fs', 'node:path' ], function (html, mime, node_fs, node_path) { var CONTENT_TYPE = { 'DEFAULT': 'text/plain;charset=UTF-8', 'HTML':'text/html;charset=UTF-8', 'XML': 'text/xml;charset=UTF-8', 'JSON':'application/json;charset=UTF-8', 'JAVASCRIPT': 'text/javascript;charset=UTF-8' }; var _slice = Array.prototype.slice; var _htmlRender = new html.Render(); var _package = require("../../../package.json"); return zn.Class({ events: ['end', 'finish', 'timeout'], properties: { request: null, contentType: 'JSON', context: null, applicationContext: { value: null, get: function (){ return this._applicationContext; }, set: function (value){ if(value){ this._applicationContext = value; this.request.applicationContext = value; } } }, serverResponse: { value: null, get: function (){ return this._serverResponse; }, set: function (value){ this.reset(); if(!value){ return; } this._serverResponse = value; this._beginTimestamp = (new Date()).getTime(); value.on('timeout', function (){ this.fire('timeout', this); }.bind(this)); value.on('finish', function (){ this._endTimestamp = (new Date()).getTime(); this.fire('finish', this); }.bind(this)); } } }, methods: { init: function (context, request){ this._context = context; this._request = request; }, reset: function (){ this._applicationContext = null; }, getTimestamp: function (){ return this._endTimestamp - this._beginTimestamp; }, writeHead: function (httpStatus, inArgs){ var _self = this, _args = inArgs || {}, _session = this._request._session, _origin = this._request._serverRequest.headers.origin || this._request._serverRequest.headers.host || this._request._serverRequest.headers.Host || ''; var _crossSetting = { 'Access-Control-Allow-Origin': _origin, 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE, PUT', 'Access-Control-Allow-Headers': 'Accept,Accept-Charset,Accept-Encoding,Accept-Language,Connection,Content-Type,Cookie,DNT,Host,Keep-Alive,Origin,Referer,User-Agent,X-CSRF-Token,X-Requested-With', "Access-Control-Allow-Credentials": true, 'Access-Control-Max-Age': '3600',//一个小时时间 'X-Powered-By': _package.name + '@' + _package.version, 'Content-Type': 'application/json;charset=utf-8' }; _args = zn.overwrite(_args, { 'Server-Version': _self.__getServerVersion(), 'Content-Type': _self.__getContentType() }); if(this._context._config.CORS){ _args = zn.overwrite(_args, _crossSetting); } if(_session){ if(_session.hasItem()){ _args['Set-Cookie'] = this._request._session.serialize(); } else { this._context._sessionManager.remove(_session.getId()); } } this._request.clearTempFiles(); this._serverResponse.writeHead(httpStatus, _args); }, setTimeout: function (timeout){ var _timeout = timeout || this._context._config.timeout || 20000; this._serverResponse.setTimeout(_timeout, function (){ this.error('Error: Request handler timeout.'); }.bind(this)); return this; }, write: function(inData, inEncode){ try { if(this._serverResponse.finished){ return; } var _req = this._request; var _callback = _req.getValue('callback'), _data = inData||''; if(typeof _data === 'object'){ _data = JSON.stringify(inData, null, ' '); } if(_callback){ _data = _callback+'('+_data+')'; this.contentType = 'JAVASCRIPT'; } this.writeHead(200, { 'Content-Type': CONTENT_TYPE[this.contentType] }); this._serverResponse.write(_data, inEncode); if(zn._request){ zn._oldRequest = zn._request; zn._request = null; } if(zn._response){ zn._oldResponse = zn._response; zn._response = null; } } catch (err) { zn.error('Response write error: ' + JSON.stringify(err)); } }, writeContent: function (status, content, contentType){ contentType = (contentType||'.html').toLowerCase(); var _encode = (contentType=='.html'||contentType=='.htm') ? 'utf8' : 'binary'; var _contentType = mime[contentType] || CONTENT_TYPE.HTML; if(_contentType.indexOf(';') === -1){ _contentType = [_contentType, "charset="+_encode].join(';'); } this.writeHead(status, { "Content-Type": _contentType, "Content-Length": Buffer.byteLength(content, _encode) }); this._serverResponse.write(content, _encode); this.end(); }, writePath: function (path, encoding){ path = node_path.normalize(path).split('?')[0]; if(node_fs.existsSync(path)){ var _encoding = 'binary', _extname = node_path.extname(path); switch (_extname) { case ".htm": case ".html": _encoding = "utf-8"; break; } node_fs.readFile(path, encoding||_encoding, function(err, content){ if(err){ this.viewModel('_error', { code: 500, msg: '服务器错误 Error: ' + err.message, detail: '' }, true); }else { this.writeContent(200, content, _extname); } }.bind(this)); } else { zn.error("Can't Open Path: ", path); this.viewModel('_error', { code: 404, msg: '未找到资源文件', detail: '' }, true); } }, writeURL: function (url, encoding){ this.writePath(this.__fixBasePath() + url, encoding); }, doIndex: function (path){ var _basePath = this.__fixBasePath(); _mode = null, _path = null; if(this._applicationContext){ _mode = this._applicationContext._config.mode; _basePath = _basePath + this._request._uri; } else { _basePath = _basePath + this._request.url; } _basePath = node_path.normalize(_basePath); if(!_mode){ _mode = this._context._config.mode; } //release, debug, view, catalog switch (_mode) { case 'release': zn.each(this._context._config.indexs || [], function (index){ if(node_fs.existsSync(_basePath + index)){ _path = _basePath + index; return false; } }); if(_path){ this.writePath(_path); } else { if(!this._context._config.debug){ _basePath = this._request.url; } this.viewModel('_error', { code: 404, msg: '未找到资源文件: ' + _basePath, detail: '' }, true); } break; case 'debug': this.success('正在完善中...'); break; case 'view': case 'catalog': this.doCatalog(_basePath); break; } }, doCatalog: function (src){ var _baseURL = node_path.normalize(this.request._pathname + zn.SLASH); var _dirPath = src || this.__fixBasePath(); if(!node_fs.statSync(_dirPath).isDirectory()){ if(node_fs.existsSync(_dirPath)){ this.writePath(_dirPath); }else { this.viewModel('_error', { code: 404, msg: '未找到资源文件: ' + _dirPath, detail: '' }, true); } return; } node_fs.readdir(_dirPath, function(err, files){ if(err){ this.viewModel('_error', { code: 500, msg: '服务器错误 Error: ' + err.message, detail: '' }, true); }else { files = files.map(function(file){ if(node_fs.statSync(node_path.join(src, file)).isDirectory()){ file = node_path.basename(file) + zn.SLASH; }else{ file = node_path.basename(file); } return { href: _baseURL + file, name: file }; }); this.viewModel('_catalog', { files: files, title: _baseURL }, true); } }.bind(this)); }, end: function () { this._serverResponse.end(); this.fire('end', this); }, writeEnd: function (inData, inEncode){ this.write(inData, inEncode); this.end(); }, success: function (inData, inEncode){ this.__writeJson({ result: inData, status: 200 }, inEncode); }, error: function (inData, inEncode){ this.writeHead(500,{}); this.__writeJson({ result: inData, status: 500 }, inEncode); }, sessionTimeout: function (inData, inEncode){ this.writeHead(401,{}); this.__writeJson({ result: inData, status: 401 }, inEncode); }, forword: function (url, isInternal){ this.fire('end', this); var _serverRequest = this.request._serverRequest, _serverResponse = this._serverResponse; if(isInternal!==false && this.applicationContext){ url = zn.SLASH + this.applicationContext.deploy + zn.SLASH + url; } _serverRequest.url = node_path.normalize(url); this._context.accept(_serverRequest, _serverResponse); }, redirect: function (url){ this._serverResponse.statusCode = 302; this._serverResponse.setHeader("Location", url); this.end(); }, viewModel: function (view, model, isServerView){ var _response = this; this._isServerView = isServerView; zn.extend(model, this._context.gets()); if(this.applicationContext){ zn.extend(model, this.applicationContext.gets()); } _htmlRender.sets({ templete: view, templeteConvert: this.__getTempletePath.bind(this), data: model }); _htmlRender.toRender(function (data){ _response.writeContent(200, data, '.html'); }); }, __getTempletePath: function (view){ var _view = { absolutePath: zn.SERVER_PATH, path: '/view/', suffix: 'html' }; if(!this._isServerView && this.applicationContext){ var _config = this.applicationContext._config; _view = _config.views || _config.view || _view; _view.absolutePath = _config.root; } if(view.indexOf('.') === -1){ view += '.' + _view.suffix; } return _view.absolutePath + _view.path + view; }, __writeJson: function (inData, inEncode){ inData.version = this.__getServerVersion(); //this.contentType = 'JSON'; this.writeEnd(inData, inEncode); }, __getContentType: function (type){ return CONTENT_TYPE[type||this.contentType]; }, __getServerVersion: function (){ return _package.name + ' V ' + _package.version; }, __fixBasePath: function (){ var _basePath = null; if(this._applicationContext){ _basePath = this._applicationContext._config.root; } else if(this._context) { _basePath = this._context._webPath; } return _basePath + zn.SLASH; } } }); });