Beaucoup de réponses ici ne sont plus de bonnes pratiques ou n'expliquent rien, c'est pourquoi j'écris ceci.
Les bases
Lorsque le rappel de http.createServer est appelé, c'est lorsque le serveur a effectivement reçu tous les en-têtes de la demande, mais il est possible que les données n'aient pas encore été reçues, nous devons donc l'attendre. L' objet de requête http (une instance http.IncomingMessage) est en fait un flux lisible . Dans les flux lisibles chaque fois qu'un bloc de données arrive, un événement est émis (en supposant que vous y avez enregistré un rappel) et lorsque tous les blocs sont arrivés, un événement est émis. Voici un exemple sur la façon dont vous écoutez les événements:data
end
http.createServer((request, response) => {
console.log('Now we have a http message with headers but no data yet.');
request.on('data', chunk => {
console.log('A chunk of data has arrived: ', chunk);
});
request.on('end', () => {
console.log('No more data');
})
}).listen(8080)
Conversion de tampons en chaînes
Si vous essayez ceci, vous remarquerez que les morceaux sont des tampons . Si vous ne traitez pas avec des données binaires et devez travailler avec des chaînes à la place, je suggère d'utiliser la méthode request.setEncoding qui provoque l'émission de chaînes interprétées avec le codage donné et gère correctement les caractères multi-octets.
Morceaux tampons
Maintenant, vous n'êtes probablement pas intéressé par chaque morceau par lui-même, donc dans ce cas, vous voulez probablement le tamponner comme ceci:
http.createServer((request, response) => {
const chunks = [];
request.on('data', chunk => chunks.push(chunk));
request.on('end', () => {
const data = Buffer.concat(chunks);
console.log('Data: ', data);
})
}).listen(8080)
Ici Buffer.concat est utilisé, qui concatène simplement tous les tampons et retourne un gros tampon. Vous pouvez également utiliser le module concat-stream qui fait de même:
const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
concat(request, data => {
console.log('Data: ', data);
});
}).listen(8080)
Analyse du contenu
Si vous essayez d'accepter la soumission POST de formulaires HTML sans fichier ou de passer des appels jQuery ajax avec le type de contenu par défaut, le type de contenu est application/x-www-form-urlencoded
avec uft-8
codage. Vous pouvez utiliser le module querystring pour le désérialiser et accéder aux propriétés:
const http = require('http');
const concat = require('concat-stream');
const qs = require('querystring');
http.createServer((request, response) => {
concat(request, buffer => {
const data = qs.parse(buffer.toString());
console.log('Data: ', data);
});
}).listen(8080)
Si votre type de contenu est JSON à la place, vous pouvez simplement utiliser JSON.parse au lieu de qs.parse .
Si vous traitez des fichiers ou manipulez un type de contenu en plusieurs parties, alors dans ce cas, vous devez utiliser quelque chose comme formidable qui enlève toute la douleur de le traiter. Jetez un oeil à cette autre réponse à moi où j'ai publié des liens et des modules utiles pour le contenu en plusieurs parties.
Tuyauterie
Si vous ne voulez pas analyser le contenu mais plutôt le transmettre ailleurs, par exemple l'envoyer à une autre requête http en tant que données ou l'enregistrer dans un fichier, je suggère de le canaliser plutôt que de le mettre en mémoire tampon, car ce sera moins code, gère mieux la contre-pression, cela prendra moins de mémoire et dans certains cas plus rapidement.
Donc, si vous souhaitez enregistrer le contenu dans un fichier:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Limiter la quantité de données
Comme d'autres réponses l'ont noté, gardez à l'esprit que les clients malveillants peuvent vous envoyer une énorme quantité de données pour bloquer votre application ou remplir votre mémoire afin de vous assurer que vous supprimez les demandes qui émettent des données dépassent une certaine limite. Si vous n'utilisez pas de bibliothèque pour gérer les données entrantes. Je suggère d'utiliser quelque chose comme stream-meter qui peut abandonner la demande s'il atteint la limite spécifiée:
limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);
ou
request.pipe(meter(1e7)).pipe(createWriteStream(...));
ou
concat(request.pipe(meter(1e7)), ...);
Modules NPM
Alors que j'ai décrit ci-dessus comment utiliser le corps de la requête HTTP, pour simplement mettre en mémoire tampon et analyser le contenu, je suggère d'utiliser l'un de ces modules plutôt que de l'implémenter par vous-même car ils traiteront probablement mieux les cas marginaux. Pour exprimer, je suggère d'utiliser l' analyseur corporel . Pour koa, il existe un module similaire .
Si vous n'utilisez pas de framework, le corps est assez bon.