node js 初次接觸

其實去看nodejs不是因爲喜歡他,或則他有多好用。

純粹是因爲,之前ace的服務器能訪問內網,而ace的環境只支持php和nodejs,所以,就有這個想法,想通過在ace服務器上部署一個proxy,這樣,週末就能在家訪問內網的機器和服務,而不用vpn和動態口令了。另外一方面,用了vpn,本身的網絡感覺也有變慢。所以。。。


網上找了proxy的例子,很詳細,看了下,就把他部署到自己的測試linux虛擬機上去了。

代碼如下:

var net = require('net');
var local_port = 8893;

//在本地創建一個server監聽本地local_port端口
net.createServer(function (client)
{

    //首先監聽瀏覽器的數據發送事件,直到收到的數據包含完整的http請求頭
    var buffer = new Buffer(0);
    client.on('data',function(data)
    {
        buffer = buffer_add(buffer,data);
        if (buffer_find_body(buffer) == -1) return;
        var req = parse_request(buffer);
        if (req === false) return;
        client.removeAllListeners('data');
var net = require('net'); 
var local_port = 8893;

//在本地創建一個server監聽本地local_port端口
net.createServer(function (client)
{

    //首先監聽瀏覽器的數據發送事件,直到收到的數據包含完整的http請求頭
    var buffer = new Buffer(0);
    client.on('data',function(data)
    {
        buffer = buffer_add(buffer,data);
        if (buffer_find_body(buffer) == -1) return;
        var req = parse_request(buffer);
        if (req === false) return;
        client.removeAllListeners('data');
        relay_connection(req);
    });

    //從http請求頭部取得請求信息後,繼續監聽瀏覽器發送數據,同時連接目標服務器,並把目標服務器的數據傳給瀏覽器
    function relay_connection(req)
    {
        console.log(req.method+' '+req.host+':'+req.port);

        //如果請求不是CONNECT方法(GET, POST),那麼替換掉頭部的一些東西
        if (req.method != 'CONNECT')
        {
            //先從buffer中取出頭部
            var _body_pos = buffer_find_body(buffer);
            if (_body_pos < 0) _body_pos = buffer.length;
            var header = buffer.slice(0,_body_pos).toString('utf8');
            //替換connection頭
            header = header.replace(/(proxy\-)?connection\:.+\r\n/ig,'')
                    .replace(/Keep\-Alive\:.+\r\n/i,'')
                    .replace("\r\n",'\r\nConnection: close\r\n');
            //替換網址格式(去掉域名部分)
            if (req.httpVersion == '1.1')
            {
                var url = req.path.replace(/http\:\/\/[^\/]+/,'');
                if (url.path != url) header = header.replace(req.path,url);
            }
            buffer = buffer_add(new Buffer(header,'utf8'),buffer.slice(_body_pos));
        }

        //建立到目標服務器的連接
        var server = net.createConnection(req.port,req.host);
        //交換服務器與瀏覽器的數據
-- VISUAL LINE --                                                                                          1,1           Top
    {
        var arr = s.match(/^([A-Z]+)\s([^\:\s]+)\:(\d+)\sHTTP\/(\d\.\d)/);
        if (arr && arr[1] && arr[2] && arr[3] && arr[4])
            return { method: arr[1], host:arr[2], port:arr[3],httpVersion:arr[4] };
    }
    else
    {
        var arr = s.match(/^([A-Z]+)\s([^\s]+)\sHTTP\/(\d\.\d)/);
        if (arr && arr[1] && arr[2] && arr[3])
        {
            var host = s.match(/Host\:\s+([^\n\s\r]+)/)[1];
            if (host)
            {
                var _p = host.split(':',2);
                return { method: arr[1], host:_p[0], port:_p[1]?_p[1]:80, path: arr[2],httpVersion:arr[3] };
            }
        }
    }
    return false;
}

/**
* 兩個buffer對象加起來
*/
function buffer_add(buf1,buf2)
{
    var re = new Buffer(buf1.length + buf2.length);
    buf1.copy(re);
    buf2.copy(re,buf1.length);
    return re;
}

/**
* 從緩存中找到頭部結束標記("\r\n\r\n")的位置
*/
function buffer_find_body(b)
{
    for(var i=0,len=b.length-3;i<len;i++)
    {
        //if ((b[i] == 0×0d) && (b[i+1] == 0×0a) && (b[i+2] == 0×0d) && (b[i+3] == 0×0a))
	//這裏原來的例子是用16進製表示,但是不知道爲什麼老是報下面的錯誤,所以我把他改成了十進制的,就好了。
	/*/home/admin/chat/proxy.js:116
        if ((b[i] == 0×0d) && (b[i+1] == 0×0a) && (b[i+2] == 0×0d) && (b[i+3] 
                      ^
	node.js:201
        	throw e; // process.nextTick error, or 'error' event on first tick
              	^
	SyntaxError: Unexpected token ILLEGAL
	*/
        if ((b[i] == 13) && (b[i+1] == 10) && (b[i+2] == 13) && (b[i+3] == 10))
        {
            return i+4;
        }
    }
    return -1;
}

然後,用node proxy.js & 直接運行服務


在本機設置代理訪問正常。


然後,需要把這個服務放到ace上去,通過ftp傳上去之後,發現起不來,悲劇。。

查看了ace的論壇,發現如下:

禁用API

  • child_process
  • net.listenFD()
  • net.listen() 
    僅支持port與callback參數, 不支持監聽unix domain sock與指定監聽ip
  • fs.rename()/fs.renameSync() 
    不支持對目錄進行操作
  • fs.link()/fs.linkSync()
  • fs.symlink()/fs.symlinkSync()

原來,net.listen()是禁用的api,怪不得起不來。。。

無語了。


本來想通過http的重定向來做代理,但是某位同學告知,ace服務器訪問內網的權限被咔嚓掉了,於是,最後的一點動力也沒有了。。


不過感覺是,這玩意兒,確實挺簡單,方便的。

另外ace也不錯,就是限制太多了。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章