node.js: запрос к базе данных + данные из нескольких частей блокируются - PullRequest
0 голосов
/ 14 июня 2011

Я все еще довольно плохо знаком со всем узлом, так что, пожалуйста, прости меня, если это невероятно глупо, но:

Если я позвоню query() на node-mysql объект клиента, я больше не могу получить тело объекта запроса из моего веб-приложения ( 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 "image_file=@test.jpg" http://localhost:8080/test

блокируется и никогда не возвращается.Я видел ту же ошибку с connect-form и multipart-js .Вид тупика здесь и сейчас.

Я полный идиот?Разве это не правильный способ делать вещи?

1 Ответ

1 голос
/ 14 июня 2011

Я думаю, что к тому моменту, когда вы добавите свой end слушатель к объекту запроса, событие end уже сработало.Вам необходимо добавить прослушиватели событий ввода-вывода в объект req немедленно в основной области действия app.post, а не в асинхронном обратном вызове, когда ваш запрос БД вернется.Вот версия с некоторыми инструкциями журнала, которые показывают последовательность событий, вызывающих эту проблему.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
    }
}
...