Respostas:
Se você usar o Express (desenvolvimento da Web de alto desempenho e classe para o Node.js), poderá fazer o seguinte:
HTML:
<form method="post" action="/">
<input type="text" name="user[name]">
<input type="text" name="user[email]">
<input type="submit" value="Submit">
</form>
Cliente da API:
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: {
name: "John",
email: "john@example.com"
}
})
});
Node.js: (desde o Express v4.16.0)
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
// Access the parse results as request.body
app.post('/', function(request, response){
console.log(request.body.user.name);
console.log(request.body.user.email);
});
Node.js: (para Express <4.16.0)
const bodyParser = require("body-parser");
/** bodyParser.urlencoded(options)
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
* and exposes the resulting object (containing the keys and values) on req.body
*/
app.use(bodyParser.urlencoded({
extended: true
}));
/**bodyParser.json(options)
* Parses the text as JSON and exposes the resulting object on req.body.
*/
app.use(bodyParser.json());
app.post("/", function (req, res) {
console.log(req.body.user.name)
});
app.use(express.bodyParser());
.
Você pode usar o querystring
módulo:
var qs = require('querystring');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// Too much POST data, kill the connection!
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6)
request.connection.destroy();
});
request.on('end', function () {
var post = qs.parse(body);
// use post['blah'], etc.
});
}
}
Agora, por exemplo, se você tiver um input
campo com nome age
, poderá acessá-lo usando a variável post
:
console.log(post.age);
var POST = qs.parse(body); // use POST
somente para noobs como eu: quando o nome do campo de texto de entrada for "usuário", Post.user
mostrará os dados desse campo. por exemploconsole.log(Post.user);
readable
retorno de chamada em vez de criar os dados em uma cadeia de caracteres do corpo. Uma vez que é acionado, o corpo está disponível atravésrequest.read();
req.connection.destroy();
não impede que os retornos de chamada sejam executados! Por exemplo, o retorno de chamada "on end" será executado com o corpo truncado! Isto provavelmente não é o que você quer ...
Certifique-se de matar a conexão se alguém tentar inundar sua RAM!
var qs = require('querystring');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6) {
// FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
request.connection.destroy();
}
});
request.on('end', function () {
var POST = qs.parse(body);
// use POST
});
}
}
var POST = qs.parse(body); // use POST
somente para noobs: quando o nome do campo de texto de entrada for "usuário", o Post.user mostrará os dados desse campo. por exemplo console.log (Post.user);
Muitas respostas aqui não são mais boas práticas ou não explicam nada, por isso estou escrevendo isso.
Quando o retorno de chamada de http.createServer é chamado, é quando o servidor realmente recebeu todos os cabeçalhos da solicitação, mas é possível que os dados ainda não tenham sido recebidos, por isso precisamos aguardar. O objeto de solicitação http (uma instância http.IncomingMessage) é na verdade um fluxo legível . Em fluxos legíveis sempre que um pedaço de dados chega, um evento é emitido (supondo que você tenha registrado um retorno de chamada) e quando todos os pedaços chegaram, um evento é emitido. Aqui está um exemplo de como você escuta os eventos: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)
Se você tentar isso, notará que os pedaços são buffers . Se você não está lidando com dados binários e precisa trabalhar com strings, sugiro usar o método request.setEncoding que faz com que o fluxo emita strings interpretadas com a codificação especificada e lida com caracteres de vários bytes corretamente.
Agora você provavelmente não está interessado em cada pedaço por si só, portanto, nesse caso, provavelmente você deseja armazená-lo da seguinte maneira:
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)
Aqui é usado o Buffer.concat , que simplesmente concatena todos os buffers e retorna um grande buffer. Você também pode usar o módulo concat-stream, que faz o mesmo:
const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
concat(request, data => {
console.log('Data: ', data);
});
}).listen(8080)
Se você está tentando aceitar HTML formulários de apresentação POST com nenhum arquivo ou distribuindo ajax jQuery chamadas com o tipo de conteúdo padrão, em seguida, o tipo de conteúdo é application/x-www-form-urlencoded
com uft-8
codificação. Você pode usar o módulo querystring para desserializá-lo e acessar as propriedades:
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)
Se o seu tipo de conteúdo for JSON, você poderá simplesmente usar JSON.parse em vez de qs.parse .
Se você estiver lidando com arquivos ou lidando com o tipo de conteúdo com várias partes, nesse caso, você deve usar algo como formidável, que remove toda a dor de lidar com ele. Dê uma olhada nesta outra resposta minha, onde eu postei links e módulos úteis para conteúdo de várias partes.
Se você não deseja analisar o conteúdo, mas passá-lo para outro lugar, por exemplo, envie-o para outra solicitação http como dados ou salve-o em um arquivo. Sugiro canalizá-lo em vez de armazená- lo em buffer, pois será menos código, lida melhor com a contrapressão, será preciso menos memória e, em alguns casos, mais rápido.
Então, se você deseja salvar o conteúdo em um arquivo:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Como outras respostas observadas, lembre-se de que clientes mal-intencionados podem enviar uma quantidade enorme de dados para travar seu aplicativo ou encher sua memória, de modo a proteger, a fim de proteger as solicitações que emitem dados que ultrapassam um determinado limite. Se você não usar uma biblioteca para manipular os dados recebidos. Eu sugeriria usar algo como medidor de fluxo que pode abortar a solicitação se atingir o limite especificado:
limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);
ou
request.pipe(meter(1e7)).pipe(createWriteStream(...));
ou
concat(request.pipe(meter(1e7)), ...);
Enquanto eu descrevi acima sobre como você pode usar o corpo da solicitação HTTP, para simplesmente armazenar em buffer e analisar o conteúdo, sugiro o uso de um desses módulos em vez de implementar por conta própria, pois eles provavelmente irão lidar melhor com casos extremos. Para expressar, sugiro usar o analisador de corpo . Para o koa, há um módulo semelhante .
Se você não usa uma estrutura, o corpo é muito bom.
request
é reutilizada e a request.on('end')
chamada várias vezes? Como posso evitar isso?
request.on('end', ...)
será chamado.
Aqui está um wrapper sem estrutura muito simples, com base nas outras respostas e artigos publicados aqui:
var http = require('http');
var querystring = require('querystring');
function processPost(request, response, callback) {
var queryData = "";
if(typeof callback !== 'function') return null;
if(request.method == 'POST') {
request.on('data', function(data) {
queryData += data;
if(queryData.length > 1e6) {
queryData = "";
response.writeHead(413, {'Content-Type': 'text/plain'}).end();
request.connection.destroy();
}
});
request.on('end', function() {
request.post = querystring.parse(queryData);
callback();
});
} else {
response.writeHead(405, {'Content-Type': 'text/plain'});
response.end();
}
}
Exemplo de uso:
http.createServer(function(request, response) {
if(request.method == 'POST') {
processPost(request, response, function() {
console.log(request.post);
// Use request.post here
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
});
} else {
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
}
}).listen(8000);
response.post
e não o mais lógico request.post
. Eu atualizei a postagem.
Será mais limpo se você codificar seus dados para JSON e enviá-los para Node.js.
function (req, res) {
if (req.method == 'POST') {
var jsonString = '';
req.on('data', function (data) {
jsonString += data;
});
req.on('end', function () {
console.log(JSON.parse(jsonString));
});
}
}
qs.parse()
, JSON.parse()
transformou o corpo em algo utilizável. Exemplo var post = JSON.parse(body);
:, acesse os dados com post.fieldname
. (Moral da história, se você está confuso sobre o que você está vendo, não se esqueça typeof
!)
request.setEncoding
fazer isso funcionar corretamente, caso contrário, ele pode não manipular caracteres não ascii corretamente.
Para quem quer saber como fazer essa tarefa trivial sem instalar uma estrutura da web, eu consegui resolver isso juntos. Dificilmente a produção está pronta, mas parece funcionar.
function handler(req, res) {
var POST = {};
if (req.method == 'POST') {
req.on('data', function(data) {
data = data.toString();
data = data.split('&');
for (var i = 0; i < data.length; i++) {
var _data = data[i].split("=");
POST[_data[0]] = _data[1];
}
console.log(POST);
})
}
}
Você pode usar body-parser
o corpo do Node.js para analisar o middleware.
Primeira carga body-parser
$ npm install body-parser --save
Algum código de exemplo
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(function (req, res) {
var post_data = req.body;
console.log(post_data);
})
Mais documentação pode ser encontrada aqui
Referência: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// at this point, `body` has the entire request body stored in it as a string
});
Aqui está como você pode fazer isso se usar o form-node :
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
Se você preferir usar o Node.js puro, poderá extrair dados do POST, como mostrado abaixo:
// Dependencies
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');
// Instantiate the HTTP server.
const httpServer = http.createServer((request, response) => {
// Get the payload, if any.
const decoder = new StringDecoder('utf-8');
let payload = '';
request.on('data', (data) => {
payload += decoder.write(data);
});
request.on('end', () => {
payload += decoder.end();
// Parse payload to object.
payload = JSON.parse(payload);
// Do smoething with the payload....
});
};
// Start the HTTP server.
const port = 3000;
httpServer.listen(port, () => {
console.log(`The server is listening on port ${port}`);
});
1) Instale a 'body-parser'
partir das npm.
2) Em seguida, no seu app.ts
var bodyParser = require('body-parser');
3) então você precisa escrever
app.use(bodyParser.json())
no módulo app.ts
4) lembre-se de incluir
app.use(bodyParser.json())
na parte superior ou antes de qualquer declaração de módulo.
Ex:
app.use(bodyParser.json())
app.use('/user',user);
5) Então use
var postdata = req.body;
Se você não deseja agrupar seus dados com o data
retorno de chamada, sempre poderá usá-lo da readable
seguinte maneira:
// Read Body when Available
request.on("readable", function(){
request.body = '';
while (null !== (request.body += request.read())){}
});
// Do something with it
request.on("end", function(){
request.body //-> POST Parameters as String
});
Essa abordagem modifica a solicitação recebida, mas assim que você terminar sua resposta, a solicitação será coletada como lixo, para que isso não seja um problema.
Uma abordagem avançada seria verificar primeiro o tamanho do corpo, se você tiver medo de corpos enormes.
request
é um fluxo node.js normal, para que você possa verificar o request.headers
comprimento do corpo e abortar a solicitação, se necessário.
Existem várias maneiras de fazer isso. No entanto, a maneira mais rápida que conheço é usar a biblioteca Express.js com o analisador de corpo.
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({extended : true}));
app.post("/pathpostdataissentto", function(request, response) {
console.log(request.body);
//Or
console.log(request.body.fieldName);
});
app.listen(8080);
Isso pode funcionar para seqüências de caracteres, mas eu mudaria bodyParser.urlencoded para bodyParser.json, se os dados POST contiverem uma matriz JSON.
Mais informações: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/
Você precisa receber os POST
dados em pedaços usandorequest.on('data', function(chunk) {...})
const http = require('http');
http.createServer((req, res) => {
if (req.method == 'POST') {
whole = ''
req.on('data', (chunk) => {
# consider adding size limit here
whole += chunk.toString()
})
req.on('end', () => {
console.log(whole)
res.writeHead(200, 'OK', {'Content-Type': 'text/html'})
res.end('Data received.')
})
}
}).listen(8080)
Você deve adicionar um limite de tamanho na posição indicada, como sugerido pelo jh .
setTimeout
que encerre a conexão após um certo período de tempo, se a solicitação completa não for recebida nessa janela.
Se você estiver usando o Express.js , antes de poder acessar o req.body, adicione o middleware bodyParser:
app.use(express.bodyParser());
Então você pode pedir
req.body.user
E se você não quiser usar toda a estrutura, como o Express, mas também precisar de diferentes tipos de formulários, incluindo uploads, a formalina pode ser uma boa escolha.
Ele está listado nos módulos Node.js.
Encontrei um vídeo que explica como conseguir isso: https://www.youtube.com/watch?v=nuw48-u3Yrg
Ele usa o módulo "http" padrão juntamente com os módulos "querystring" e "stringbuilder". O aplicativo pega dois números (usando duas caixas de texto) de uma página da Web e, após o envio, retorna a soma desses dois (juntamente com a persistência dos valores nas caixas de texto). Este é o melhor exemplo que eu poderia encontrar em qualquer outro lugar.
Código fonte relacionado:
var http = require("http");
var qs = require("querystring");
var StringBuilder = require("stringbuilder");
var port = 9000;
function getCalcHtml(req, resp, data) {
var sb = new StringBuilder({ newline: "\r\n" });
sb.appendLine("<html>");
sb.appendLine(" <body>");
sb.appendLine(" <form method='post'>");
sb.appendLine(" <table>");
sb.appendLine(" <tr>");
sb.appendLine(" <td>Enter First No: </td>");
if (data && data.txtFirstNo) {
sb.appendLine(" <td><input type='text' id='txtFirstNo' name='txtFirstNo' value='{0}'/></td>", data.txtFirstNo);
}
else {
sb.appendLine(" <td><input type='text' id='txtFirstNo' name='txtFirstNo' /></td>");
}
sb.appendLine(" </tr>");
sb.appendLine(" <tr>");
sb.appendLine(" <td>Enter Second No: </td>");
if (data && data.txtSecondNo) {
sb.appendLine(" <td><input type='text' id='txtSecondNo' name='txtSecondNo' value='{0}'/></td>", data.txtSecondNo);
}
else {
sb.appendLine(" <td><input type='text' id='txtSecondNo' name='txtSecondNo' /></td>");
}
sb.appendLine(" </tr>");
sb.appendLine(" <tr>");
sb.appendLine(" <td><input type='submit' value='Calculate' /></td>");
sb.appendLine(" </tr>");
if (data && data.txtFirstNo && data.txtSecondNo) {
var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo);
sb.appendLine(" <tr>");
sb.appendLine(" <td>Sum: {0}</td>", sum);
sb.appendLine(" </tr>");
}
sb.appendLine(" </table>");
sb.appendLine(" </form>")
sb.appendLine(" </body>");
sb.appendLine("</html>");
sb.build(function (err, result) {
resp.write(result);
resp.end();
});
}
function getCalcForm(req, resp, data) {
resp.writeHead(200, { "Content-Type": "text/html" });
getCalcHtml(req, resp, data);
}
function getHome(req, resp) {
resp.writeHead(200, { "Content-Type": "text/html" });
resp.write("<html><html><head><title>Home</title></head><body>Want to some calculation? Click <a href='/calc'>here</a></body></html>");
resp.end();
}
function get404(req, resp) {
resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" });
resp.write("<html><html><head><title>404</title></head><body>404: Resource not found. Go to <a href='/'>Home</a></body></html>");
resp.end();
}
function get405(req, resp) {
resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" });
resp.write("<html><html><head><title>405</title></head><body>405: Method not supported</body></html>");
resp.end();
}
http.createServer(function (req, resp) {
switch (req.method) {
case "GET":
if (req.url === "/") {
getHome(req, resp);
}
else if (req.url === "/calc") {
getCalcForm(req, resp);
}
else {
get404(req, resp);
}
break;
case "POST":
if (req.url === "/calc") {
var reqBody = '';
req.on('data', function (data) {
reqBody += data;
if (reqBody.length > 1e7) { //10MB
resp.writeHead(413, 'Request Entity Too Large', { 'Content-Type': 'text/html' });
resp.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
}
});
req.on('end', function () {
var formData = qs.parse(reqBody);
getCalcForm(req, resp, formData);
});
}
else {
get404(req, resp);
}
break;
default:
get405(req, resp);
break;
}
}).listen(port);
Para aqueles que usam o upload binário bruto do POST sem sobrecarga de codificação, você pode usar:
cliente:
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
var blob = new Uint8Array([65,72,79,74]); // or e.g. recorder.getBlob()
xhr.send(blob);
servidor:
var express = require('express');
var router = express.Router();
var fs = require('fs');
router.use (function(req, res, next) {
var data='';
req.setEncoding('binary');
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
req.body = data;
next();
});
});
router.post('/api/upload', function(req, res, next) {
fs.writeFile("binaryFile.png", req.body, 'binary', function(err) {
res.send("Binary POST successful!");
});
});
Você pode usar o middleware expresso , que agora possui um analisador de corpo incorporado. Isso significa que tudo que você precisa fazer é o seguinte:
import express from 'express'
const app = express()
app.use(express.json())
app.post('/thing', (req, res) => {
console.log(req.body) // <-- this will access the body of the post
res.sendStatus(200)
})
Esse exemplo de código é ES6 com o Express 4.16.x
você pode extrair o parâmetro post sem usar o express.
1: nmp install multiparty
2: importar multipartidário. Comovar multiparty = require('multiparty');
3: `
if(req.method ==='POST'){
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
console.log(fields['userfile1'][0]);
});
}
4: e HTML FORM IS.
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
Espero que isso funcione para você. Obrigado.
Limite o tamanho do POST para evitar inundar o aplicativo do nó. Existe um ótimo módulo de corpo bruto , adequado tanto para expresso quanto para conexão, que pode ajudá-lo a limitar a solicitação por tamanho e comprimento.
Se envolver um upload de arquivo, o navegador normalmente o envia como um "multipart/form-data"
tipo de conteúdo. Você pode usar isso nesses casos
var multipart = require('multipart');
multipart.parse(req)
Em campos de formulário como estes
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="myemail@somewherefarfar.com">
algumas das respostas acima falharão porque suportam apenas dados simples.
Por enquanto, estou usando a resposta Casey Chu, mas com o "qs" em vez do módulo "querystring". Este é o módulo "body-parser" também usa. Portanto, se você quiser dados aninhados, precisará instalar o qs.
npm install qs --save
Em seguida, substitua a primeira linha como:
//var qs = require('querystring');
var qs = require('qs');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// Too much POST data, kill the connection!
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6)
request.connection.destroy();
});
request.on('end', function () {
var post = qs.parse(body);
console.log(post.user.name); // should work
// use post['blah'], etc.
});
}
}
Você pode enviar e obter facilmente a resposta da solicitação POST usando "Solicitação - cliente HTTP simplificado" e Promessa Javascript.
var request = require('request');
function getData() {
var options = {
url: 'https://example.com',
headers: {
'Content-Type': 'application/json'
}
};
return new Promise(function (resolve, reject) {
var responseData;
var req = request.post(options, (err, res, body) => {
if (err) {
console.log(err);
reject(err);
} else {
console.log("Responce Data", JSON.parse(body));
responseData = body;
resolve(responseData);
}
});
});
}
Você precisa usar bodyParser () se quiser que os dados do formulário estejam disponíveis em req.body. O analisador de corpo analisa sua solicitação e a converte em um formato do qual você pode extrair facilmente as informações relevantes necessárias.
Por exemplo, digamos que você tenha um formulário de inscrição no seu front-end. Você está preenchendo e solicitando ao servidor que salve os detalhes em algum lugar.
Extrair o nome de usuário e a senha da sua solicitação é tão simples quanto abaixo se você usar o analisador de corpo.
…………………………………………………….
var loginDetails = {
username : request.body.username,
password : request.body.password
};
ONE LINER sem MIDDLEWARE
Se você publicar os seguintes dados, 'name':'ABC'
poderá analisá-los usando o seguinte liner,
require('url').parse(req.url, true).query.name