iT邦幫忙

DAY 24
6

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

node.js伺服器實戰(24) - 開始設計視圖機制

  • 分享至 

  • xImage
  •  

先考慮到http response各個部份的需求,把這部份的實做確定下來。
與伺服器流程與機制整合

對http來說,伺服器的回應,主要就是由header與body組合而成,而且header必須在body之前送出,body則可以一個chuck一個chuck送出,直到結束。因為header與body必須有這樣先後的關係,在設計上,最好能保證這樣的輸出順序。另外,response還有一個特別的功能是addTrailers(),可以利用他來送出trailer header。trailer header有一些特別的條件:必須在header中有trailer這個header,然後在body之後送出trailer headers,最後才結束response。

有一個簡單的方法可以達到目的,並且把它與伺服器的流程做結合:

* 在route handler中,可以隨時呼叫response.setHeader/getHeader/deleteHeader,但是無法直接使用response.write寫入到response,而是把要輸出的東西放進output buffer
* 同樣在route handler中,可以隨時呼叫response.addTrailers,但是它也會把trailer header寫入到output buffer中
* 在post dispatch才進行reponse.write,把output buffer的資料寫入到response,所有資料輸出後,呼叫response.addTrailers來輸出trailer headers,最後才呼叫response.end來結束request事件

不過要做到的這樣的功能,需要重新包裝傳給route handler的response物件。

這樣做還有一個好處,除了保證輸出的順序是正確的,因為操作介面對使用者來說並沒有變,所以對使用者的習慣來說,並沒有影響。如果要在route handler(也就是controller)中引入template引擎,也只要把他的輸出直接轉到response.write就可以,對於要使用怎樣的視圖機制,影響都不大。

另外,原先在伺服器程式中,設計好了一個用來render的callback函數。現在還是使用這個callback函數來負責render,只要傳給它content type以及http response body的資料就可以。是否需要調整,等到實做template引擎,與這部份搭配看看就知道是否還需要調整。

實做

就先來實做看看,這樣是否可行吧。

原始碼請參考github:
https://github.com/fillano/evolve/blob/ec5917f002a8ba3b736224d9c58a646d931defe4/lib/evolve.js

主要的改變是利用responseWrapper函數來包裝response物件並且提供一致的介面,把一些操作改寫入buffer,到post dispatch時才實際寫入response。

跑一下整合測試,發現testCookie.js沒有寫好,稍微改一下:

 var Evolve = require('../lib-cov/evolve');
 var testCase = require('nodeunit').testCase;
 var tools = require('../lib-cov/tools');
 
 module.exports = testCase({
     "setUp": function(cb) {
         this.http = require('http');
         this.evolve = new Evolve({dirindex: ['index.html', 'index.htm', 'default.htm']});
         this.evolve.handle('pre', tools.cookieHandler);
         this.evolve.host('localhost:8443')
         .get('/testcookie', function(request, response, cb) {
             if(request.cookie) {
 				var str = ''+request.headers.cookie;
     			cb(false, '/testcookie', {type:'text/plain', data: str})
             }else{
             	var str = "no cookie";
     			cb(false, '/testcookie', {type:'text/plain', data: str})
             }
         });
         this.evolve.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);
                 test.done();
             });
         });
         req.end();
     }
 });

ok,這樣就可以跑完測試了。

後續

接下來要寫一個簡單的template引擎,並且考慮與model整合的情形,來做比較詳細的設計與實作。

今天的範例檔fillano-evolve-v0.0.17-0-g1b2dcab.zip,目前版本是v0.0.17。

相關文章


上一篇
node.js伺服器實戰(23) - 考慮MVC
下一篇
node.js伺服器實戰(25) - 初步設計視圖與模型的互動方式
系列文
node.js伺服器實戰33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言