Frage

Ich möchte Anfrage (POST) Körper von http.ServerRequest zu bekommen, aber tun so nicht gerade, wenn meine Anfrage Funktion aufgerufen wird, aber erst nach einiger Zeit (Redis Abfrage).

Ich habe ein sehr einfaches Beispiel zur Veranschaulichung:

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);

In diesem Beispiel data und end Ereignisse völlig verfehlt werden, obwohl ich req.pause() / req.resume() bin Aufruf, so Wunsch des "stecken".

Wenn ich setTimeout() Anruf Kommentar und alles tun, gerade in Anforderungsfunktion, alles funktioniert wie erwartet. Aber ich will Redis abfragen, wenn die Anforderung die gültig anzusehen. Die Pfosten sind große Datei-Uploads, und ich möchte nicht, Zeit verschwenden für erfolglose Upload auf vollständige warten.

Der einfache Weg, dies zu tun ist, um die POST für einige Millisekunden Verzögerung (in meinem Fall POSTs zumindest einige Sekunden dauern würde, so solche winzige Verzögerung ziemlich unbedeutend ist). Die sauberere ist eingehende Daten-Parsing zu starten, gleichzeitig die Anforderung zu validieren und die Verbindung fallen, wenn Wunsch des gefunden ungültig.

Die Frage ist: Wie ich irgendetwas davon tun würde? Ich verwende Node.js Version 0.1.97-14-g0055dd1 wenn diese Angelegenheiten.

Vielen Dank für alle Vorschläge.

War es hilfreich?

Lösung

Sie wissen nicht, wann immer ich das richtig mache, aber das scheint das Richtige für mich:

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);

Addition: Wenn Connect Middleware einige asynchrone Anfragen ausführen möchte (das heißt die Steuerung zurück zu der Ereignisschleife passieren) es funktioniert um auf diese Weise:

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

Wo utils.pause() ein Hack zu puffern Ereignisse anhängig .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top