2013-03-15 16 views
39

Sto provando a gestire una richiesta di posta inviata al mio server node.js. Il file JavaScript con un nome server.js visualizza un modulo sul browser. Voglio accedere ai valori del modulo dopo che sono stati inviati al backend node.js.Come gestire la richiesta POST in node.js

Il modulo contiene un nome utente, un repository e una diramazione. Quando viene inviato il modulo, voglio visualizzare nuovamente questi dati all'utente.

Il codice server.js:

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/'); 
+12

Consiglio vivamente di utilizzare un framework (anche di basso livello) per la creazione di app con nodo. Personalmente uso Express (http://expressjs.com/), tuttavia ci sono altre opzioni se si sceglie. Tra le altre cose ti consentirà di gestire facilmente diversi tipi di richieste e percorsi, oltre a contenuti statici. –

+0

Vedere http://stackoverflow.com/questions/6158933/http-post-request-in-node-js – user568109

+0

È possibile visualizzare un semplice esempio su come gestire HTTP POST con Express.js nel mio blog http: // hectorcorrea .com/blog/introduction-to-node-js –

risposta

129

ho intenzione di utilizzare il codice che hai fornito, e di fornire una risposta più approfondita di ciò che è coperto nella sua domanda per ospitare persone in un lontano futuro. Fornirò anche una risposta che usa "Vanilla JS" (http://www.vanilla-js.com/) perché penso che molti hipsters dicano "usa un framework" quando stai cercando di capire come funziona. Penso che la ragione per cui lo fanno è perché qualcuno ha detto loro di "usare un framework" quando stavano imparando come funziona. Poiché non sono hacker, non si sono preoccupati di cercare di capire il processo, quindi molto spesso molti di loro non capiscono come farlo da soli, senza un framework (da qui l'onnipresente "usa un framework"). Diventerai un hacker migliore comprendendo cosa sta succedendo sotto il cofano e spero che questa risposta ti aiuti in tal senso.

Ora che desideri accettare i dati POST (modulo) tramite il modulo che stai emettendo, è necessario fornire un meccanismo di routing nel server. Ciò significa che dovrai dire al tuo server di fornire il modulo alle persone che visitano il tuo sito, ma se l'utente invia un modulo, il nodo indirizzerà i dati POST a una piccola funzione di elaborazione. Ho fornito la risposta completa per prima e poi sezionata più in basso, per accogliere le persone che vogliono imparare dal codice.

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

E ora per la ripartizione che spiega perché ho fatto le cose che ho fatto.

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

In primo luogo, si sta andando ad aggiungere del Nodo built-in '' querystring modulo per analizzare i dati del modulo effettivi.

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; 

ho spostato l'uscita di modulo sopra il nostro server/routing/meccanismo di modulo di gestione, perché la logica è quindi molto più facile da leggere. Ho anche spostato le informazioni sulla porta di ascolto del server quassù, perché in quel caso devi solo modificarlo in un posto anziché in molti.

http.createServer(function (request, response) { 

(io di solito accorciare i parametri di questa funzione su "req" e "res", ma questo è solo la mia preferenza.)

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

Qui ho incluso un esempio di routing semplice. In questo caso, stiamo facendo in modo che il nostro server ascolti le richieste di "favicon.ico": una richiesta fatta insieme a quasi tutte le richieste iniziali di una pagina Web da parte di tutti i principali browser. Questo file è la piccola icona che puoi vedere nelle schede di ogni pagina web che stai visitando. Per i nostri scopi, non abbiamo bisogno di servire una favicon, ma gestiremo le richieste in entrata per mostrare alcuni meccanismi di routing di base.

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

Se i visitatori puntano il browser per qualsiasi altra risorsa sul server con il metodo di default GET (oltre al "favicon.ico" abbiamo appena maneggiato sopra), serviremo loro la forma.

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

In caso contrario, se i visitatori stanno indicando un posto presso il server, è molto probabile che hanno inviato il modulo hanno recuperato con la precedente richiesta GET.

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

Qui siamo in ascolto per le richieste in entrata chiamate "/ inbound", che - se hai preso il piccolo dettaglio in precedenza - è l ' "azione" della nostra forma HTML. Come forse saprai, l '"azione" del modulo indica al browser dove inviare i dati del modulo.

Questo potrebbe sembrare un po 'confuso, ma prometto che non lo è. Le richieste POST possono essere inviate come messaggi multiparte dal browser client. Con qualcosa di piccolo come poche variabili in un modulo, probabilmente non lo vedrai mai, ma man mano che riduci la quantità di dati che gestisci, vedrai questo. Se sei osservante, vedrai anche la dichiarazione if() che chiede la lunghezza dei dati POST. Una persona malintenzionata può uccidere il tuo server caricando un file infinito, ma non se interveniamo. Ciò limita il corpo dei dati POST a circa dieci megabyte, ma è necessario regolare di conseguenza. Conoscere queste cose impedisce un mal di testa futuro, e non voglio che tu abbia un mal di testa.

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

E qui è dove utilizziamo i dati del modulo. A causa della natura di Javascript, questi nomi di variabili sono CASE SENSITIVE (come "UserName" invece di "username"). Naturalmente, puoi fare tutto ciò che vuoi con questi dati (tenendo presente il ciclo degli eventi del nodo e la natura asincrona).

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

Per continuare il nostro esempio di routing, quello che abbiamo fatto qui è incluso un catch-all di sotto della dichiarazione if(), che invia al client un generico 404 "Not Found" rispondere a qualsiasi richiesta POST non abbiamo già maneggiato.

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

E ora abbiamo appena terminato il codice, incluso un po 'di codice per gestire le richieste con strani metodi. Ci sono alcune cose che non ho affrontato (struttura delle funzioni, dati di moduli vuoti, ecc.), Ma ci sono davvero molti modi per raggiungere i tuoi obiettivi. Come disse una volta uno dei miei professori di CS molti anni fa, ci sono tanti modi per programmare un programma che è facile vedere chi sta barando condividendo i compiti.

Spero che tu (e chiunque altro) possa vedere che non è un processo esoterico o anche leggermente difficile fare cose in Nodo usando i suoi moduli integrati invece di affidarsi a librerie esterne di terze parti come Express. Queste biblioteche hanno il loro posto nel mondo, ma non seguono la mandria: prendi una decisione informata sul tuo codice, perché alla fine della giornata sei tu l'unico responsabile (non alcune persone su Stack Overflow).

+13

Perché non posso revocare questo voto per 10 volte?;) – Mixthos

+3

È il pensiero che conta. Grazie! :) – L0j1k

+3

Wow, ottima risposta! Eccellente per startes :) grazie! – Martin

Problemi correlati