使用nodejs解析指定扩展名,实现简易安全的动态路由。
发布在nodejs 边角料2014年4月12日view:6677
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

最近写的项目中,使用了node-static作为静态server的实现,遇到了想实现简单动态路由的需求,分享下解决思路。

第一想法很单纯,我想像apache解析php一样,解析一个独特得扩展名文件,实现动态路由。当然你可以直接解析php,道理和我后面说的一样。从req.url中匹配到extname,再用php-cgi解析之后,返回结果吐回来。

说起来简单,实现起来你还需要安装php环境,怪麻烦的,而且我php也不熟,干脆,我解析nodejs算了。。所以,我增加一个额外的.node扩展名的文件解析支持。

思路先说,后上代码。基本原理同上解析php文件一样,只不过php-cgi换成了nodejs模块中的vm。

没用过vm模块的同学可以先去读一读文档。再回来看。

下面上代码:

function isNode(file){
    return path.extname(file) == '.node';
}

function runNodeFile(file,req,res){
    var code = fs.readFileSync(file, 'utf-8');
    var dirname = path.dirname(file);
    try {
      vm.runInNewContext(code, {
        console: console,
        '__dirname': dirname,
        addModule: function(mod) {
              return require(dirname + '/node_modules/' + mod);
        },
        require: require,
        route: function(run) {
              run(req, res);
        }
     });
   } catch(e) {
          console.error(e);
   }
}

http.createServer(function(req,res){
    var file = path.join(rootpath, url.parse(req.url).pathname); //这里的rootpath要额外做些工作,其实就类似实现了一个vhosts,这个这里不具体说了,留着以后再讲,大家脑补一下,rootpath对应的就是这个server的documentRoot。
    if(isNode(file) && fs.existsSync(file)){
        runNodeFile(file,req,res);      
    }
});

代码有修改,算是简单提出实现部分吧,先匹配文件扩展名,如果符合要求,读出文件内容,再使用vm的runInNewContext方法执行code。

执行时隔离作用域,再注入你所需要的一些方法和global属性,比如我注入了文档的dirname,增加require当前file路径的addModule方法,又注入了普通的require方法。

最关键在于那个route方法。

看一个简单的路由,我是如何写的:

var combine = addModule('css-combine');
var u = require('url');
var fs = require('fs');
var path = require('path');
var qs = require('querystring');

route(function(req,res){
    var file = decodeURIComponent(qs.parse(u.parse(req.url).query).file) + '.css';
    file = path.resolve(__dirname,file);
    if(fs.existsSync(file)){
        res.writeHeader(200,{
            'content-type':'text/css'
        });
        combine(file).pipe(res);
    }else{
        res.writeHeader(404,'text/html');
        res.end('404');
    }
});

文件名为css.node,css-combine是这个node扩展所在目录下安装的module,route方法可以操作当前请求的req,res并反馈结果给客户端。

so。。通过这种方法给静态服务server写写扩展也还是不错的选择。抛砖引玉,这也是最近项目遇到的一种解决思路吧- -。

这个扩展实现的是访问一个带improt关键字的css,自动解析成合并后的css。

评论
发表评论
暂无评论
WRITTEN BY
PUBLISHED IN
nodejs 边角料

分享和记录一下,个人在学习nodejs中遇到的一些有意思的事。

我的收藏