Umgang mit POST-Anforderungen in node.js

Lesezeit: 12 Minuten

Benutzer-Avatar
Sau

Ich versuche, eine Post-Anforderung zu verarbeiten, die an meinen node.js-Server gesendet wird. JavaScript-Datei mit dem Namen server.js zeigt ein Formular im Browser an. Ich möchte Zugriff auf die Formularwerte, nachdem sie an das node.js-Backend gesendet wurden.

Das Formular enthält einen Benutzernamen, ein Repository und einen Zweig. Wenn das Formular gesendet wird, möchte ich diese Daten dem Benutzer wieder anzeigen.

Der server.js-Code:

var http = require('http');

http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<html><body>'
    + '<h1>XYZ Repository Commit Monitor</h1>'
    + '<form method="post" action="." enctype="application/x-www-form-urlencoded"><fieldset>'
    + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
    + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
    + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
    + '<div><input id="ListCommits" type="submit" value="List Commits" /></div>'
    + '</fieldset></form>'
    + '</body></html>');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

  • Ich würde Ihnen dringend empfehlen, ein (auch niedriges) Framework zum Erstellen von Apps mit Node zu verwenden. Ich persönlich benutze Express (expressjs.com), es gibt jedoch auch andere Optionen, wenn Sie dies wünschen. Unter anderem ermöglicht es Ihnen, verschiedene Anfragetypen und -routen sowie statische Inhalte einfach zu handhaben.

    – Nick Mitchinson

    15. März 2013 um 8:06 Uhr

  • Siehe stackoverflow.com/questions/6158933/…

    – Benutzer568109

    15. März 2013 um 11:00 Uhr

  • In meinem Blog sehen Sie ein einfaches Beispiel zur Handhabung von HTTP POST mit Express.js hectorcorrea.com/blog/introduction-to-node-js

    – Hector Correa

    15. März 2013 um 13:23 Uhr

  • benutze expressjs. Sie erhalten auch Beispiel server.js. expressjs.com/guide.html . dann benutze app.post(“/pageurl”, function(req, res){ /* use req.body.UserName, req.body.Branch etc */ });

    – gp.

    30. August 2013 um 15:50 Uhr

  • mögliches Duplikat von Wie extrahieren Sie POST-Daten in node.js?

    – Mokka

    10. September 2013 um 10:05 Uhr

Benutzer-Avatar
L0j1k

Ich werde den von Ihnen bereitgestellten Code verwenden und eine gründlichere Antwort geben als in Ihrer Frage behandelt, um Menschen in The Distant Future entgegenzukommen. Ich werde auch eine Antwort geben, die “Vanilla JS” verwendet (http://www.vanilla-js.com/), weil ich denke, dass zu viele Hipster sagen “benutze ein Framework”, wenn du versuchst zu lernen, wie das funktioniert. Ich denke, der Grund, warum sie das tun, ist, dass ihnen jemand gesagt hat, sie sollten “ein Framework verwenden”, als sie lernten, wie das funktioniert. Da sie keine Hacker sind, haben sie sich nicht darum gekümmert, den Prozess zu verstehen, so dass viele von ihnen oft nicht verstehen, wie sie dies alleine ohne ein Framework tun sollen (daher das allgegenwärtige „Use a Framework“). Sie werden ein besserer Hacker, wenn Sie verstehen, was unter der Haube vor sich geht, und ich hoffe, diese Antwort hilft Ihnen dabei.

Da Sie nun POST-(Formular-)Daten über das ausgegebene Formular akzeptieren möchten, ist es notwendig, einen Routing-Mechanismus in Ihrem Server bereitzustellen. Dies bedeutet, dass Sie Ihren Server anweisen, das Formular an Personen weiterzugeben, die Ihre Site besuchen, aber wenn der Benutzer dann ein Formular absendet, leitet Node die POST-Daten an eine kleine Verarbeitungsfunktion weiter. Ich habe zuerst die vollständige Antwort gegeben und sie dann weiter unten seziert, um Leuten entgegenzukommen, die aus dem Code lernen möchten.

var http = require('http');
var qs = require('querystring');
var formOutput="<html><body>"
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;
http.createServer(function (request, response) {
  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
      response.end();
    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }
  } else if(request.method === "POST") {
    if (request.url === "/inbound") {
      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });
    } else {
      response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
      response.end('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
    }
  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

Und nun zur Aufschlüsselung, die erklärt, warum ich die Dinge getan habe, die ich getan habe.

var http = require('http');
var qs = require('querystring');

Zuerst fügen Sie das integrierte „querystring“-Modul von Node hinzu, um die eigentlichen Formulardaten zu parsen.

var formOutput="<html><body>"
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="/inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;

Ich habe die Formularausgabe nach oben über unseren Server/Routing/Formular-Handling-Mechanismus verschoben, weil die Logik dann viel einfacher zu lesen ist. Ich habe auch die Server-Listening-Port-Informationen hier nach oben verschoben, weil Sie sie dann nur an einer Stelle ändern müssen, anstatt an vielen darunter.

http.createServer(function (request, response) {

(Normalerweise kürze ich die Parameter dieser Funktion auf „req“ und „res“, aber das ist nur meine Präferenz.)

  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write(notFound);
      response.end();

Hier habe ich ein einfaches Routing-Beispiel eingefügt. In diesem Fall lassen wir unseren Server Anfragen für „favicon.ico“ abhören – eine Anfrage, die zusammen mit fast allen anfänglichen Anfragen für eine Webseite von allen gängigen Browsern gestellt wird. Diese Datei ist das kleine Symbol, das Sie in den Registerkarten jeder besuchten Webseite sehen können. Für unsere Zwecke müssen wir kein Favicon bereitstellen, aber wir werden eingehende Anfragen bearbeiten, um einige grundlegende Routing-Mechanismen zu zeigen.

    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }

Wenn Ihre Besucher ihren Browser mit der standardmäßigen GET-Methode auf eine beliebige andere Ressource auf Ihrem Server verweisen (neben dem oben behandelten „favicon.ico“), werden wir ihnen das Formular zustellen.

  } else if(request.method === "POST") {

Andernfalls ist es sehr wahrscheinlich, dass Ihre Besucher, wenn sie einen POST auf Ihren Server verweisen, das Formular gesendet haben, das sie mit der vorherigen GET-Anforderung abgerufen haben.

    if (request.url === "/inbound") {

Hier hören wir auf eingehende Anfragen mit dem Namen „/inbound“, was – wenn Sie das kleine Detail oben verstanden haben – die „Aktion“ unseres HTML-Formulars ist. Wie Sie vielleicht wissen, teilt die “Aktion” des Formulars dem Browser mit, wohin die Formulardaten gesendet werden sollen.

      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);

Das mag ein wenig verwirrend aussehen, aber ich verspreche, dass es das nicht ist. POST-Anforderungen können als mehrteilige Nachrichten vom Client-Browser gesendet werden. Bei etwas so Kleinem wie ein paar Variablen in einem Formular werden Sie dies wahrscheinlich nie sehen, aber wenn Sie die von Ihnen verarbeitete Datenmenge skalieren, werden Sie dies sehen. Wenn Sie aufmerksam sind, werden Sie auch die sehen if() Anweisung, die nach der Länge der POST-Daten fragt. Eine böswillige Person kann Ihren Server töten, indem sie eine endlose Datei hochlädt, aber nicht, wenn wir etwas unternehmen. Dadurch wird der POST-Datenkörper auf etwa zehn Megabyte begrenzt, Sie sollten dies jedoch entsprechend anpassen. Das Wissen um diese Dinge verhindert zukünftige Kopfschmerzen, und ich möchte nicht, dass Sie Kopfschmerzen haben.

        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });

Und hier verwenden wir die Formulardaten. Aufgrund der Beschaffenheit von Javascript wird bei diesen Variablennamen zwischen Groß- und Kleinschreibung unterschieden (z. B. “Benutzername” anstelle von “Benutzername”). Natürlich können Sie mit diesen Daten alles machen, was Sie wollen (unter Berücksichtigung der Ereignisschleife und der asynchronen Natur von Node).

    }
    response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>404</title></head><body>413: Request Entity Too Large</body></html>');

Um mit unserem Routing-Beispiel fortzufahren, haben wir hier ein Catch-All unter dem eingefügt if() -Anweisung, die dem Client eine generische 404-„Not Found“-Antwort auf jede POST-Anforderung sendet, die wir noch nicht verarbeitet haben.

  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

Und jetzt haben wir gerade den Code fertiggestellt, einschließlich ein wenig Code, um Anfragen mit seltsamen Methoden zu verarbeiten. Es gibt ein paar Dinge, die ich nicht angesprochen habe (Funktionsstruktur, leere Formulardaten usw.), aber es gibt tatsächlich viele Möglichkeiten, Ihre Ziele zu erreichen. Wie einer meiner CS-Professoren einmal vor vielen Jahren sagte, gibt es so viele Möglichkeiten, ein Programm zu programmieren, dass man leicht erkennen kann, wer schummelt, indem er seine Hausaufgaben teilt.

Ich hoffe, dass Sie (und alle anderen) erkennen können, dass es kein esoterischer oder sogar etwas schwieriger Prozess ist, Dinge in Node mit seinen integrierten Modulen zu erledigen, anstatt sich auf externe Bibliotheken von Drittanbietern wie Express zu verlassen. Diese Bibliotheken haben ihren Platz in der Welt, aber folgen Sie nicht der Herde: Treffen Sie eine fundierte Entscheidung über Ihren Code, denn am Ende des Tages sind Sie derjenige, der dafür verantwortlich ist (nicht einige Leute auf Stack Overflow).

  • Es ist der Gedanke der zählt. Vielen Dank! 🙂

    – L0j1k

    10. März 2014 um 21:57 Uhr

  • Was ist mit mehrteiligen Formulardaten?

    – Quentin Engles

    27. Mai 2014 um 10:13 Uhr

  • Entschuldigen Sie, dass ich Sie mit einer ein Jahr alten Antwort belästige, aber könnten Sie sie ein wenig erweitern, um den Umgang mit Routen abzudecken? Tolle Antwort, aber – gut geschrieben und auf den Punkt gebracht.

    – Nekoru

    5. November 2014 um 10:50 Uhr

  • Sicher! Ich habe der Antwort ein sehr einfaches Routing-Beispiel hinzugefügt. Außerdem sind mehrteilige Formulardaten etwas komplexer, daher denke ich, dass ein Beispiel dafür am besten in einer anderen Antwort gegeben werden sollte.

    – L0j1k

    5. November 2014 um 16:34 Uhr

  • Ich liebe diese Antwort. Leute, die sagen “benutze Express, es erspart dir die Mühe, irgendetwas zu wissen”, nerven mich wirklich. Es gibt mir das Gefühl, dass ich lerne, wie man mit einem Roboter herumspielt, anstatt den Roboter zu bauen.

    – DeepS1X

    10. Mai 2017 um 20:51 Uhr

1245870cookie-checkUmgang mit POST-Anforderungen in node.js

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy