iT邦幫忙

DAY 36
5

node.js伺服器實戰系列 第 33

node.js伺服器實戰(-2) - 賽後補完,做出plugin架構

之前的程式著重在伺服器流程的構成,還沒有考慮到如何提供使用者可用的api,所以再來加強一下。
目前的伺服器流程

使用者可以自訂的地方,主要在pre(pre dispatch)這個hook,但是通常除了在流程中對http.ServerRequest做預處理,很多時候還需要在伺服器中加入一些API來使用。

構想很簡單,就是設計好一個plugin模組的格式,然後利用一個use方法把plugin載入。例如如果要把cookie相關的功能移到plugin,可以這樣設計plugin模組(cookie.js):

module.exports = {
    app: {
        "cookieParser": function(cookie_str) {
            var tmp1 = cookie_str.split(/[;,] */g),
            tmp2,
            i=0,
            l=tmp1.length,
            ret={};
            for(;i<l;i++) {
                tmp2 = tmp1[i].split('=');
                ret[tmp2[0].trim().replace(/^[\'\"]+/g, '').replace(/[\'\"]+$/g, '')] = tmp2[1].trim().replace(/^[\'\"]+/g, '').replace(/[\'\"]+$/g, '');
            }
            return ret;
        },
        "setCookie": function() {
        }
    },
    pre: [
        function(request, response, next) {
            if(request.headers.cookie) {
                request.cookie = this.cookieParser(request.headers.cookie);
            } else {
                request.cookie = {};
            }
            next();
        }
    ]
};

然後在伺服器加上一個use方法(evolve.js):

    this.use = function(name) {
        var obj = require('./plugins/'+name);//plugin集中放置在lib/plugins目錄中
        var i = '';
        for(i in obj) {
            if(obj.hasOwnProperty(i)) {
                switch(i) {
                    case 'pre':
                    case 'dispatch':
                    case 'post':
                        var j = 0, l = obj[i].length;
                        for(; j<l; j++) {
                            this.handle(i, obj[i][j]);
                        }
                        break;
                    case 'app':
                        var k = '';
                        for(k in obj.app) {
                            if(obj.app.hasOwnProperty(k)) {
                                switch(k) {
                                    case 'handle':
                                    case 'use':
                                    case 'end':
                                    case 'host':
                                    case 'listen':
                                    case 'close':
                                    case 'listen':
                                        break;
                                    default:
                                        if(typeof obj.app[k] === 'function') {
                                            this[k] = obj.app[k];
                                        }
                                        break;
                                }
                            }
                        }
                        break;
                }
            }
        }
        return this;
    };

這樣就可以把定義好的api:cookieParser以及setCookie加到伺服器的instance中,讓使用者可以在router中使用。

使用

在需要使用到cookie相關功能時,就可以(調整一下之前寫的整合測試:testCookie.js):

var Evolve = require('../lib/evolve');
var testCase = require('nodeunit').testCase;

module.exports = testCase({
    "setUp": function(cb) {
        this.http = require('http');
        this.evolve = new Evolve({dirindex: ['index.html', 'index.htm', 'default.htm']})
        .use('cookie')
        .host('localhost:8443')
        .get('/testcookie', function(request, response, cb) {
            if(request.cookie) {
                var str = ''+request.headers.cookie;
                this.setCookie(...); // 還沒實作出來
                cb(false, '/testcookie', {type:'text/plain', data: str}, true);
            }else{
                var str = "no cookie";
                cb(false, '/testcookie', {type:'text/plain', data: str}, true)
            }
        })
        .listen(8443, 'localhost');
        cb();
    },
    "tearDown": function(cb) {
        this.evolve.close();
        cb();
    },
    "test if cookie received and appended to request": function(test) {
        test.expect(2);
        var cv = new Date().getTime();
        var req = this.http.request({
            "host": "localhost",
            "port": 8443,
            "path": "/testcookie",
            "method": "GET",
            "headers": {
                "Cookie": "SID="+cv
            }
        }, function(response) {
            var result = [];
            response.on('data', function(data) {
                result.push(data);
            });
            response.on('end', function() {
                var total = 0;
                var entity = '';
                for(var i=0; i<result.length; i++) {
                   total += result[i].length;
                   entity += result[i].toString('ascii');
                }
                test.ok(entity.indexOf('SID')>-1);
                test.ok(entity.indexOf(cv+"")>-1);
                //可以檢查是否有set新的cookie
                test.done();
            });
        });
        req.end();
    }
});

功能就更完整了,也更模組化。

就先到這裡告一段落吧,之後再慢慢把功能實作進去。

相關文章


上一篇
node.js伺服器實戰(-1) - 賽後亂搞dnode
系列文
node.js伺服器實戰33

尚未有邦友留言

立即登入留言