2011-06-14 119 views
0

我仍然相當新來的整個節點的thingie,所以請原諒我,如果這是猖獗愚蠢,但:的node.js:數據庫查詢+多形式的數據鎖定了

如果我叫query()node-mysql客戶端對象,我不能再從我的web應用程序(express)中獲取請求對象的正文。

我的基本POST/PUT請求模式需要用戶身份驗證是:

_db_client = connect_to_db_server(); 
app.post("/some/path", function (req, res) { 
    _db_client.query("SELECT * FROM Users WHERE username = ?", 
        [ http_basic_auth.username ], function (err, results) { 
     if (err != null || resp == null) { 
     res.send("AUTH FAILURE: sorry, you can't do that", 403); 
     } else { 
     get_request_body(req, function (body) { 
      do_something(); 
      res.send("yay, I'm happy", 200); 
     }); 
     } 
    }); 
}); 

現在的問題是,get_request_body功能根本不會回來。它看起來好像只是在請求對象上「被阻塞」。

下面是一個簡單的程序:

var express = require('express'), 
    mysql = require('mysql'); 

var MySQLClient = mysql.Client; 
var client = new MySQLClient(); 

client.user = 'root'; 
client.password = ''; 

client.connect(function(err, res) { 
    client.query("USE Gazelle", function (qerr, qresp) { 
    }); 
}); 

var app = express.createServer(); 
app.use(express.bodyParser()); 

app.post("/test", function (req, res) { 
    client.query('SELECT * FROM Users', function (err, results) { 
     get_request_body(req, function (body) { 
      console.log("wooo"); 
      console.log(body); 
      res.send("cool", 200); 
     }); 
    }); 
}); 


app.listen(8080); 


function get_request_body (req, callback) { 
    if (req.rawBody != undefined) { 
     callback(req.rawBody); 
    } else { 
     var data = ''; 
     req.setEncoding('binary'); 

     req.on('data', function(chunk) { 
      data += chunk; 
     }); 

     req.on('end', function() { 
      callback(data); 
     }); 
    } 
} 

訣竅:它只有失敗,如果我使用多表單POST數據,而不是常規的POST數據:

curl -u un:pw -X POST -d ' { "cat" : "meow" }' http://localhost:8080/test 

工作

curl -u un:pw -X POST -F "[email protected]" http://localhost:8080/test 

鎖定並永不返回。我看到與連接形式multipart-js相同的錯誤。現在在這裏難倒了。

我是個白癡嗎?這不是正確的做事方式嗎?

回答

1

我認爲在您將end偵聽器添加到請求對象時,end事件已經觸發。您需要立即在主要app.post函數作用域中將您的IO事件偵聽器添加到req對象中,而不是在數據庫查詢返回時進行異步回調。這是一個帶有一些日誌語句的版本,可以顯示導致此問題的事件序列。底部的req.emit('end');僅僅是一個黑客來證明爲什麼請求被鎖定。您的end事件處理程序永遠不會被調用,但合成重複的end事件確實允許請求完成(但未正確解析正文)。

var express = require('express'); 
var app = express.createServer(); 
app.use(express.bodyParser()); 

app.post("/test", function (req, res) { 
    req.on('data', function(){ 
    console.log("data fired but your listener is not yet added"); 
    }); 
    req.on('end', function() { 
    console.log('end fired but your listener is not yet added'); 
    }); 
    setTimeout(function() { //Simulating your async DB query 
    console.log("setTimeout finished and fired callback"); 
     get_request_body(req, function (body) { 
      console.log("wooo"); 
      console.log(body); 
      res.send("cool", 200); 
     }); 
     }, 50); 
}); 


app.listen(8081); 


function get_request_body (req, callback) { 
    if (req.rawBody != undefined) { 
     console.log('express.bodyParser parsed it already'); 
     callback(req.rawBody); 
    } else { 
     console.log('get_request_body going to parse because ' + req.rawBody); 
     var data = ''; 
     req.setEncoding('binary'); 

     req.on('data', function(chunk) { 
      console.log('get_request_body got data event'); 
      data += chunk; 
     }); 

     req.on('end', function() { 
      console.log('get_request_body parsed it'); 
      callback(data); 
     }); 
     req.emit('end');//BUGBUG 
    } 
} 
+0

乾杯,就是這樣。我知道這將是飛行員的錯誤。 – MarcWan 2011-06-15 03:31:23