node.jsに手を出してみる

以前から小耳に挟んでいた謎のnode.jsに手を出してみた。


ちょっと使った感じから察するに、v8のスタンドアロンインタプリタにlibeventを組み込んだものらしい。あんまサーバとして使う気は無くて、libevent駆動のterminfoアプリ(cursesだと、マルチバイトではまるので敢えて)を作るのに使えるのかという観点で下調べ。

var port=process.argv.length>1 ? 8080 : process.argv[1];

// require
var HTTP=require('http');
var URL=require('url');
var count=0;

function proxyRequest(url, req, count){
    var headers={};
    for(var _key in req.headers){
        var key=_key.toLowerCase();
        if(key=='host'){
            headers[_key]=url.host;
        }
        else if(key.match(/^proxy/)){
            // skip
            console.log('skip request header: '+key);
        }
        else{
            headers[_key]=req.headers[_key];
        }
    }
    console.log('['+count+']'+req.method+' ####################');
    console.log(url.host);
    var href=url.pathname+(url.search || '');
    console.log(href);
    console.log(headers);
    var proxy_request=HTTP.createClient(url.port || 80, url.host).request(
        req.method, href, req.headers);
    proxy_request.count=count;
    return proxy_request;
}


// http
var http=HTTP.createServer(function(req, client){
    // http.Server Event: 'request'
    var proxy_request=proxyRequest(URL.parse(req.url), req, count++);

    req.on('data', function(chunk) {
        // request body
        proxy_request.write(chunk, 'binary');
    });

    req.on('end', function() {
        // enf of request
        proxy_request.end();
    });

    // http.ClinetRequest Event: 'response'
    proxy_request.on('response', function(res){
        console.log('['+proxy_request.count+']response: '+res.statusCode);
        console.log(res.headers);
        // reponse header
        client.writeHead(res.statusCode, res.headers);

        res.on('data', function(chunk) {
            // response body
            client.write(chunk, 'binary');
        });

        res.on('end', function() {
            // end of response
            client.end();
        });
    });

    // error handling
    proxy_request.on('# error ## ', function(e){
        client.log('error: '+e);
    });


});

http.on('connect', function(stream){
    console.log('connect');
});

http.on('clientError', function(e){
    console.log(e);
});

console.log('listen '+port+'...');
http.listen(port);

最近多いがhttp proxyであります。
とりあえず、GETメソッド, POSTメソッドは問題なし。
最初、yieldが無いか探したのだがIOのところでメインループに戻ってよきにはからってくれるようですな。
HTTP1.1のkeep-aliveやchunkを隠蔽してくれるので、
こいつは便利だ(たぶん1.1で動いたと思う)。
あと、ssl proxyのCONNECTを実装しようとしたのだがこれは分らんかった。
CONNECTが来たら黙って揉み消してるようだが、なんか
CONNECT用にハンドラを登録するところでもあるのだろうか。


テキストブラウザrubyで作ろうとしていたのだが、
node.jsで実装した方がjavascript対応の芽が残るので
こっちの方が面白い。
terminfoとかwcwidthをwrapするモジュールを作って
node.jsでやってみるか。。。