Pergunta

Eu quero obter solicitação (postar) corpo de http.ServerRequest, mas não faça isso reto quando minha função de solicitação é chamada, mas somente depois de algum tempo (Redis Query).

Eu tenho um exemplo muito simples para ilustrar:

var http = require('http'),
    sys = require('sys');

http.createServer(function (req, res) {
    sys.puts("Got request");
    req.pause();
    setTimeout(function() { // In real code I'm accessing Redis here.
        var body = "";
        req.addListener('data', function (chunk) {
            sys.puts("Got 'data' event");
            body += chunk;
        });
        req.addListener('end', function () {
            sys.puts("Got 'end' event");
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(body);
        });
        req.resume();
    }, 10);
}).listen(8000);

Neste exemplo data e end Os eventos são completamente perdidos, mesmo que eu esteja ligando req.pause()/req.resume(), então o pedido está "preso".

Se eu comentar setTimeout() Ligue e faça tudo diretamente na função de solicitação, tudo funciona conforme o esperado. Mas quero consultar o Redis para ver sempre que a solicitação é válida. As postagens são grandes uploads de arquivo e não quero perder tempo esperando o upload malsucedido será concluído.

A maneira simples de fazer isso é adiar o post para alguns milissegundos (no meu caso, as postagens levariam pelo menos vários segundos, portanto, esse pequeno atraso é bastante insignificante). O mais intenso é começar a analisar dados de entrada, validando simultaneamente a solicitação e soltar a conexão se a solicitação for considerada inválida.

A questão é: como eu faria nada disso? Estou usando o Node.js versão 0.1.97-14-G0055DD1 se isso importa.

Obrigado por quaisquer sugestões.

Foi útil?

Solução

Não sei sempre que estou fazendo isso direito, mas isso parece certo para mim:

var http = require('http'),
    sys = require('sys');

http.createServer(function (req, res) {
    var body = "",
        body_complete = false,
        wait_complete = false;
    sys.debug("Got request");

    // This will be called on each process' completion
    var final_cb = function(err) {
        if (err) throw new Error(err);
        if (body_complete && wait_complete) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(body);
        }
    };

    // Async process one: get POST body
    req.addListener('data', function (chunk) {
        sys.debug("Got 'data' event");
        body += chunk;
    });
    req.addListener('end', function () {
        sys.debug("Got 'end' event");
        body_complete = true;
        final_cb(null)
    });

    // Async process two: wait 10ms
    setTimeout(function() { // In real code I'm accessing Redis here.
        sys.debug("Timeout passed");
        if (false) { // Okay, timeout can't go wrong
            res.writeHead(403);
            res.end('Sorry');
        }
        wait_complete = true;
        final_cb(null);
    }, 10);
}).listen(8000);

Adição: Quando o Connect Middleware deseja executar algumas solicitações assínconas (ou seja, o controle de passe de volta ao loop do evento), ele funciona dessa maneira:

var pause = utils.pause(req);
fs.readFile(path, function(){
    next();
    pause.resume();
});

Onde utils.pause() é um hack para buffer eventos pendentes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top