2016-07-07 9 views
0

リクエストの特定のパラメータを記録してオンラインで確認できるページに出力するモジュールを作成しようとしていますが、このページではsocket.ioを使用して最新のログ。NodeJSの次のイベントハンドラにリクエストを送信

そして、私はこのモジュールをプラグインとして機能させて、このモジュールを呼び出して初期化してから、追加のエントリポイント/_loggerがあなたのアプリケーションに追加され、一度そのページにアクセスすれば最新のログがリアルタイムで更新されます。だから、モジュールは、要求をインターセプトする必要があります。

function setup(httpServer) { 
    //page 
    httpServer.on("request", function (request, response) { 
     var pathname = url.parse(request.url).pathname; 
     if (pathname === '/_logger') { 
      fs.readFile(__dirname + '/logger.html', (err, data) => { 
       response.writeHead(200, { 'Content-Type': 'text/html' }); 
       response.write(data); 
       response.end(); 
      }); 
     }else{ 
      // how to give up the control for this requset 
     } 
    }); 


    var io = require('socket.io')(httpServer); 
    io.on('connection', function (socket) { 
     //TO BE DONE 
     socket.on('event', function (data) { }); 
     socket.on('disconnect', function() { }); 
    }); 
} 
module.exports = { 
    setup: setup 
} 

使用法:

var logger= require("./logger/index"); 
var server = require('http').createServer(); 
logger.setup(server); 
server.on("request", function(req,res){ 
    //Normal logic for different application 
}); 
server.listen(3333); 

今の問題は、要求されたURLが/_loggerではないと、私はこの要求の制御を解放すべきであるということです。

 if (pathname === '/_logger') { 
      //take control 
     }else{ 
      // Nothing should be done here, it should go to the next request chain. 
     } 

文書を読み終えたら、正しい方法を見つけることができません。

アイデア?

答えて

1

低レベルのNodeJS HTTP APIを使用すると仮定します。関数の構成を使用して、複数のハンドラを1つのハンドラにまとめることができます。各ハンドラは、req.urlが一致しない場合は、次のハンドラに実行を渡す必要があります。

var http = require('http'); 

var handler1 = function(req, res) { 
    res.writeHead(200, { 'Content-Type': 'text/html' }); 
    res.write('/'); 
    res.end(); 
} 

var handler2 = function(req, res) { 
    res.writeHead(200, { 'Content-Type': 'text/html' }); 
    res.write('/Hello'); 
    res.end(); 
} 

var middleware = compose([wrapHandler('/', handler1), 
         wrapHandler('/hello', handler2)]); 

http.createServer(middleware).listen(3000); 

function wrapHandler(path, cb) { 
    return function (req, res, next) { 
     if (req.url === path) { 
      cb(req, res); 
     } else { 
      next(); 
     } 
    }; 
} 

function notFoundHandler(req, res) { 
    res.writeHead(404, { 'Content-Type': 'text/html' }); 
    res.write('No Path found'); 
    res.end();  
}; 

// adapted from koa-compose 
function compose(middleware) { 
    return function (req, res){ 
     let next = function() { 
      notFoundHandler.call(this, req, res); 
     }; 

     let i = middleware.length; 
     while (i--) { 
      let thisMiddleware = middleware[i]; 
      let nextMiddleware = next; 
      next = function() { 
       thisMiddleware.call(this, req, res, nextMiddleware); 
      } 
     } 
     return next(); 
    } 
} 

あなたの場合は、あなたが書くことができます。

var loggerHandler = wrapHandler('/_logger', logger.handler); 
httpServer.on('request', compose(loggerHandler, handler2, handler3)); 
+0

私は恐れては、 'logger'モジュールが別々のプラグインとして動作するはずないです。つまり、 'logger'モジュールはun-invasionでなければなりません。 – hguser

+0

@hguser 'logger.setup(server)'を使う代わりに、以下のようにロガーモジュールからハンドラーをエクスポートすることができます: 'var logH = logger.handler; server.on( 'request'、compose([logH、otherHandler])) '; – zeronone

+0

@hguser 'wrapHandler'関数を使うと、単純なハンドラと特定のパスを束縛することができます。 – zeronone

1

httpServer.on("request", ...)はリクエストリスナーの1つです。それが必要でない場合、要求を処理する義務はありません。何もしなくても、他のリクエストリスナーには依然としてこのリクエストが通知されます。

他のリクエストリスナー(そこにあることを暗示している)がある場合は、表示するリクエストリスナーで何もしないで、他のリスナーも特定のリクエストでショットを取得します。これにより、自分の要求リスナーを稼働中のHTTPサーバーに追加することができます。リスナーは、サポートしたい新しいルートに注意を払うだけで、他のすべてのルートを無視して他のリスナーによって処理されますすでに設置されています。


ここでは、これをさらに簡単にし、より多くの制御を行うためのフレームワークが用意されています。一般に、これらのフレームワークは1つのリスナを使用し、リクエストを処理する手段を提供します。または、リクエストを処理していないことをフレームワークに明示し、他のルートハンドラがリクエストを処理するようにします。これは、複数のリスナーを持つよりも柔軟性があり、すべてが同じルートを通知されます。

たとえば、Expressのフレームワークを使用して、あなたはこれを行うことができます。

var express = require('express'); 
var app = express(); 

// route handler for/request only when a user=xxx is in the query string 
app.get('/', function(req, res, next) { 
    // if user was included in query parameter 
    if (req.query.user) { 
     // do something specific when ?user=xxxx is included in the URL 
    } else { 
     // pass handling to the next request handler in the chain 
     next(); 
    } 
}); 

// route handler for/request that wasn't already handled 
app.get('/', function(req, res) { 
    // handle the/route here 
}); 

app.listen(80); 
+0

しかし、私は、 'logger'モジュールを使う可能性のあるアプリケーションは全て、明示的、接続的、または何か他のものに基づいて構築されているとは思いません。 – hguser

+0

あなたが言及したように、1つのリスナーは何もする必要がない場合は何もできません。私の例では、 'request'イベントに2つのリスナーが追加されています。もう1つはアプリケーションです。もう1つは' logger'モジュールです。リクエストは最初に 'logger'で処理され、次にアプリケーションが処理されます。リクエストされたURLが' _logger'であると、アプリケーションハンドラが呼び出され、 'write after end'エラーが発生します。 – hguser

+0

@hguser - 実際のフレームワークがどのハンドラから次のハンドラにリクエストを渡すかを説明するだけです。そのようなフレームワークにアクセスできない場合は、実行していたようにリスナーを追加し、ルートと一致する場合はリクエストを処理し、そうでない場合は何もしません。他のhttpサーバーのリスナーに "フック"する一般的な方法はありません。それがExpressのような要求フレームワークが提供するものです。プレーンなhttpオブジェクトはそれを提供しません。 – jfriend00

関連する問題