UNPKG

node-ursa

Version:

A front end development workbench with server/https/template engine/optimization tools support

242 lines (223 loc) 8.74 kB
/** * handler.js * * changelog * 2013/11/03:replace request to connect's,response reserved. * * @author yinyong#sogou-inc.com * @version 0.0.2 */ var fs = require("fs"), mime = require('mime'), sysPath = require('path'), sysUrl= require('url'), config = require('./config'), utils = require('./utils'), util = require('util'), filter = require('./filter'), Render = require('./tool/render'), plugin = require('./tool/plugin'), Stamp = require('./tool/timestamp'), less = require('./tool/less'), logger = require("./tool/logger"); module.exports = { /** * 显示模板列表 * @param {Request] req [description] * @param {Response} res [description] * @see ./http/Response */ index: function(req, res) { var htmlFiles = config.get('require_html_modules'); if (!util.isArray(htmlFiles)) { logger.logError("require_html_modules MUST BE an array,but it is a %s".error, typeof htmlFiles); htmlFiles = []; utils.walkSync(config.templateDir, htmlFiles, /\.tpl$/i); htmlFiles.forEach(function(tpl, index) { htmlFiles[index] = sysPath.relative(config.templateDir, tpl); }); } //遍历构建模板的完整路径 htmlFiles.forEach(function(file, index) { //file可能带.tpl后缀也可能不带 var realPath = sysPath.join(config.templateDir, file + (/\.tpl$/i.test(file) ? "" : ".tpl")); if (!fs.existsSync(realPath)) { logger.logWarn("%s does not exist".warn, realPath); htmlFiles.splice(index, 1); } else { htmlFiles[index] = file; } }); //不使用模板达到夸模板引擎的目的 var tplHtmlStr = ""; htmlFiles.forEach(function(tpl, index) { tplHtmlStr += '<li><a class="title" href="{{tpl}}.ut">{{tpl}}</a><a class="mgr" href="{{tpl}}.m">mgr</a></li>'.replace(/\{\{tpl\}\}/g, tpl.replace(/\.tpl$/i, "")); //可能需要去掉.tpl后缀 }); fs.readFile(sysPath.join(__dirname, "../template/index.tpl"), 'utf-8', function(err, content) { if (err) { return res.send(500, String(err)); } content = content.replace('__TPL_HTML_STR__', tplHtmlStr); return res.send(content); }); }, /** * 处理后缀ut的请求,输出模板。 * @param {Request} req * @param {Response} res * @see ./http/Response */ tpl: function(req, res) { var startTime = Date.now(); var pathname =sysUrl.parse(req.url).pathname || ""; pathname = pathname.replace(/\.ut$/i, ''); var render = new Render(config.templateDir); return render.render(pathname, { //AOP }, function(err, content) { if (err) { logger.logError("%s".error, err); return res.send(500, String(err)); } content = filter(content); //服务器输出时间戳 if (config.get("server_add_timestamp")) { var stamp = new Stamp("."); content = stamp.addToHtmlLink(content); content = stamp.addToHtmlScript(content); content = stamp.addToCssUrl(content, "."); } content = plugin.compilePlugins(pathname, content); res.send(content); logger.logInfo("200 %s %dbytes %dms".info, pathname, content.length, new Date - startTime); }); }, /** * 输出模板数据,以供修改. * @param {Request} req [description] * @param {Response} res [description] * @see ./http/Response */ m: function(req, res) { var pathname =sysUrl.parse(req.url).pathname || ""; //This template is not the app's but the node-ursa's. var render = new Render(sysPath.join(__dirname, "../", config.templateDir)); //要输出的json var dataFile = sysPath.join(config.dataDir, pathname.replace(/\.m$/i, '.json')); return fs.readFile(dataFile, function(err, json) { json = json || ""; fs.readFile(sysPath.join(__dirname, "../template/mgr.tpl"), "utf-8", function(err, content) { if (err) { return res.send(500, String(err)); } var data = { name: pathname.replace(/\.m$/i, ''), data: json, tpl: sysPath.join(".", pathname.replace(/\.m$/i, '.json')) }; content = content.replace(/\{\{(name|data|tpl)\}\}/g, function(k) { return data[RegExp.$1]; }); return res.send(content); }); }); }, /** * 保存提交来的json数据。 * @param {Request} req [description] * @param {Response} res [description] * @see ./http/Response */ data_so: function(req, res) { if (req.method !== 'POST') { return res.send(405, "GET is not supported"); } var tpl = req.body.tpl; var data = req.body.data; if (!tpl || !data) { logger.logError("has tpl:%s;has data:%s".error, !! tpl, !! data); return res.send("Lack of parameters!"); } //校验格式 try { JSON.parse(utils.rmComment(data)) } catch (e) { return res.send("<pre>" + data + "</pre> JSON failure"); }; //写入文件 return fs.writeFile(sysPath.join(config.dataDir, tpl), data, function(err) { if (err) { logger.logError("%s".error, err); return res.send("Save failed"); } else { return res.redirect('/'); } }); }, /** * 静态资源 * @param {Request} req [description] * @param {Response} res [description] */ _static: function(req, res) { //var startTime = Date.now(); var pathname = sysUrl.parse(req.url).pathname; var file = sysPath.join(".", pathname); return fs.exists(file, function(exists) { if (exists) { var contentType = mime.lookup(file); //Read file return fs.readFile(file, function(err, content) { if (err) { logger.logError("%s".error, err); return res.send(500, file + " read failed:" + String(err)); } else { try { //期望文本文件内存在替换变量 if (/text|javascript/ig.test(contentType)) { content = content.toString(); //Buffer转String,不影响String自转。 content = filter(content, null); //服务器模式输出时间戳 if (config.get("server_add_timestamp") && /css|less|styl/i.test(contentType)) { var stamp = new Stamp("."); content = stamp.addToCssUrl(content, sysPath.dirname(file)); } } res.send({ 'content-type': contentType, 'content-length': content.length }, content); // logger.logInfo("200 %s %dbytes %dms".info, pathname, content.length, Date.now() - startTime); } catch (e) { logger.logError("%s".error, e); res.send(500, String(e)); } return; } }); } else { return res.send(404, file + ' not found!') } }); }, /** * 处理其它请求,如图片、脚本、样式表 * @param {Request} req * @param {Response} res * @see ./http/Response */ none: function(req, res) { var pathname = sysUrl.parse(req.url).pathname || ""; var file = sysPath.join(".", pathname); var self=this; if (/\.css$/i.test(file)) { less.compile(file, function(err) { if (err) logger.logError("%s".error, err) self._static(req,res); }); } else { self._static(req,res); } } };