node.js - headers - req body node js
¿Cómo se extraen los datos POST en Node.js? (23)
¿Cómo extrae los datos del formulario ( form[method="post"]
) y las cargas de archivos enviadas desde el método HTTP POST
en Node.js ?
He leído la documentación, he buscado en Google y no he encontrado nada.
function (request, response) {
//request.post????
}
¿Hay una biblioteca o un hack?
- Instalar
''body-parser''
desde npm. - luego abra
app.ts
-> write ->var bodyParser = require(''body-parser'');
- entonces necesitas escribir
app.use(bodyParser.json())
en el móduloapp.ts
tenga en cuenta que incluye
app.use(bodyParser.json())
en la parte superior o antes de cualquier declaración de módulo. Ej:app.use(bodyParser.json()) app.use(''/user'',user);
Luego usa
var postdata = req.body;
¡Asegúrate de eliminar la conexión si alguien intenta inundar tu 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
});
}
}
Aquí es cómo puede hacerlo si usa un node-formidable :
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
Aquí hay un contenedor no-framework muy simple basado en las otras respuestas y artículos publicados aquí:
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();
}
}
Ejemplo 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);
Debe recibir los datos POST
en trozos utilizando request.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)
Debería considerar agregar un límite de tamaño en la posición indicada según lo sugerido .
En campos de formulario como estos
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="[email protected]">
Algunas de las respuestas anteriores fallarán porque solo admiten datos planos.
Por ahora estoy usando la respuesta de Casey Chu pero con el módulo "qs" lugar del módulo "cadena de consulta". Este es el módulo que "body-parser" usa también. Entonces si quieres datos anidados tienes que instalar qs.
npm install qs --save
Luego reemplace la primera línea 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.
});
}
}
Encontré un video que explica cómo lograrlo: https://www.youtube.com/watch?v=nuw48-u3Yrg
Utiliza el módulo predeterminado "http" junto con los módulos de "cadena de consulta" y "constructor de cadenas". La aplicación toma dos números (usando dos cuadros de texto) de una página web y al enviarlos, devuelve la suma de esos dos (junto con la persistencia de los valores en los cuadros de texto). Este es el mejor ejemplo que pude encontrar en cualquier otro lugar.
Código fuente 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);
Hay múltiples formas de hacerlo. Sin embargo, la forma más rápida que conozco es usar la biblioteca Express.js con body-parser.
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);
Eso puede funcionar para cadenas, pero cambiaría bodyParser.urlencoded a bodyParser.json en cambio si los datos POST contienen una matriz JSON.
Más información: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/
Limite el tamaño de POST para evitar inundar su aplicación de nodo. Hay un gran módulo de raw-body , adecuado tanto para Express como para Connect, que puede ayudarlo a limitar la solicitud por tamaño y longitud.
Muchas respuestas aquí ya no son buenas prácticas o no explican nada, por eso escribo esto.
Cuando se llama a la devolución de llamada de http.createServer, es cuando el servidor realmente ha recibido todos los encabezados para la solicitud, pero es posible que los datos aún no se hayan recibido, por lo que tenemos que esperar. El objeto de solicitud http (una instancia http.IncomingMessage) es en realidad una stream readable . En las secuencias legibles siempre que llega un fragmento de datos, se emite un evento de data
(suponiendo que haya registrado una devolución de llamada) y cuando todos los fragmentos hayan llegado, se emitirá un evento end
. Aquí hay un ejemplo de cómo escuchas los eventos:
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)
Si lo intentas, notarás que los trozos son buffers . Si no está tratando con datos binarios y necesita trabajar con cadenas, en su lugar, le sugiero que utilice el método request.setEncoding , que hace que las secuencias de secuencias interpretadas con la codificación dada manejen correctamente los caracteres de varios bytes.
Probablemente no esté interesado en cada fragmento por sí mismo, por lo que en este caso probablemente desee almacenarlo de la siguiente manera:
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)
Aquí se utiliza Buffer.concat , que simplemente concatena todos los búferes y devuelve un búfer grande. También puede usar el módulo concat-stream que hace lo mismo:
const http = require(''http'');
const concat = require(''concat-stream'');
http.createServer((request, response) => {
concat(request, data => {
console.log(''Data: '', data);
});
}).listen(8080)
Si está intentando aceptar formularios HTML con envío POST sin archivos o entregando llamadas ajax jQuery con el tipo de contenido predeterminado, entonces el tipo de contenido es application/x-www-form-urlencoded
con codificación uft-8
. Puede usar el módulo de cadena de consulta para deserializarlo y acceder a las propiedades:
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 su tipo de contenido es JSON, simplemente puede usar JSON.parse lugar de qs.parse .
Si está tratando con archivos o manejando el tipo de contenido multiparte, entonces, en ese caso, debe usar algo como formidable que elimina todo el dolor de tratar con él. Eche un vistazo a esta otra respuesta mía en la que he publicado enlaces y módulos útiles para contenido de varias partes.
Si no desea analizar el contenido, sino transferirlo a otro lugar, por ejemplo, envíelo a otra solicitud http como datos o guárdelo en un archivo. Le sugiero que lo canalice en lugar de almacenarlo en búfer, ya que será menos Código, maneja mejor la contrapresión, tomará menos memoria y, en algunos casos, más rápido.
Así que si quieres guardar el contenido en un archivo:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream(''./request''));
}).listen(8080)
Como han señalado otras respuestas, tenga en cuenta que los clientes malintencionados pueden enviarle una gran cantidad de datos para bloquear su aplicación o llenar su memoria para proteger y asegurarse de eliminar las solicitudes que emiten datos que pasan un cierto límite. Si no utiliza una biblioteca para manejar los datos entrantes. Sugeriría usar algo como stream-meter que pueda abortar la solicitud si alcanza el límite especificado:
limitedStream = request.pipe(meter(1e7));
limitedStream.on(''data'', ...);
limitedStream.on(''end'', ...);
o
request.pipe(meter(1e7)).pipe(createWriteStream(...));
o
concat(request.pipe(meter(1e7)), ...);
También intente utilizar los módulos npm en lugar de implementarlos por su cuenta, ya que probablemente manejarán mejor los casos de borde. Para expreso te sugiero usar body-parser . Para koa, hay un módulo similar .
Si no usas un marco, el body es bastante bueno.
Para aquellos que utilizan la carga POST binario sin procesar y sin sobrecarga de codificación, puede 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!");
});
});
Para cualquiera que se pregunte cómo hacer esta tarea trivial sin instalar un marco web, logré hacer esto juntos. Apenas la producción está lista pero 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);
})
}
}
Puede usar body-parser
, el middleware de análisis de cuerpo de Node.js.
Primera carga body-parser
$ npm install body-parser --save
Algún código de ejemplo
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);
})
Más documentación se puede encontrar here
Puede utilizar el módulo de querystring
:
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.
});
}
}
Ahora, por ejemplo, si tiene un campo de input
con la age
nombre, podría acceder a él usando la variable post
:
console.log(post.age);
Referencia: 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
});
Se puede extraer el parámetro post sin usar expreso.
1: nmp install multiparty
2: import multiparty. como var 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: y el formato HTML es.
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
Espero que esto funcione para tí. Gracias.
Será más limpio si codifica sus datos a JSON y luego los envía a 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));
});
}
}
Si está utilizando Express.js , antes de poder acceder a req.body, debe agregar middleware bodyParser:
app.use(express.bodyParser());
Entonces puedes pedir
req.body.user
Si no desea agrupar sus datos junto con la devolución de llamada de data
, siempre puede utilizar la devolución de llamada readable
así:
// 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
});
Este enfoque modifica la solicitud entrante, pero tan pronto como finalice su respuesta, la solicitud se recogerá, por lo que no debería ser un problema.
Un enfoque avanzado sería verificar primero el tamaño del cuerpo, si tienes miedo de los cuerpos enormes.
Si prefiere usar Node.js puro, puede extraer datos POST como se muestra a continuación:
// 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}`);
});
Si se trata de una carga de archivos, el navegador generalmente lo envía como un tipo de contenido "multipart/form-data"
. Puedes usar esto en tales casos.
var multipart = require(''multipart'');
multipart.parse(req)
Si usa Express (desarrollo web de alto rendimiento y clase para Node.js), puede hacer esto:
HTML:
<form method="post" action="/">
<input type="text" name="user[name]">
<input type="text" name="user[email]">
<input type="submit" value="Submit">
</form>
JavaScript:
app.use(express.bodyParser());
app.post(''/'', function(request, response){
console.log(request.body.user.name);
console.log(request.body.user.email);
});
ACTUALIZADO el 1 / junio / 2016:
El método anterior está obsoleto ahora:
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)
});
Y si no desea utilizar todo el marco como Express, pero también necesita diferentes tipos de formularios, incluidas las subidas, entonces la formaline puede ser una buena opción.
Está listado en los módulos de Node.js.