Respuestas:
Si usa Express (desarrollo web de alto rendimiento y alta 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>
Cliente API:
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: {
name: "John",
email: "john@example.com"
}
})
});
Node.js: (desde 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());
.
Puedes usar el 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.
});
}
}
Ahora, por ejemplo, si tiene un input
campo con nombre age
, puede acceder a él utilizando la variable post
:
console.log(post.age);
var POST = qs.parse(body); // use POST
solo para novatos como yo: cuando el nombre del campo de texto de entrada es "usuario", Post.user
mostrará los datos de ese campo. por ejemploconsole.log(Post.user);
readable
devolución de llamada en lugar de construir los datos en una cadena de cuerpo. Una vez que se dispara, el cuerpo está disponible a través derequest.read();
req.connection.destroy();
no impide que se ejecuten las devoluciones de llamada! Por ejemplo, la devolución de llamada "al final" se ejecutará con el cuerpo truncado. Esto probablemente no es lo que quiere ...
¡Asegúrate de cerrar 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
});
}
}
var POST = qs.parse(body); // use POST
solo para novatos: cuando el nombre del campo de texto de entrada es "usuario", Post.user mostrará los datos de ese campo. eg console.log (Post.user);
Muchas de las respuestas aquí ya no son buenas prácticas o no explican nada, así que por eso estoy escribiendo esto.
Cuando se llama a la devolución de llamada de http.createServer, es cuando el servidor ha recibido todos los encabezados de 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 de http.IncomingMessage) es en realidad una secuencia legible . En transmisiones legibles cada vez que llega un fragmento de datos, se emite un evento (suponiendo que haya registrado una devolución de llamada) y cuando todos los fragmentos han llegado se emite un evento. Aquí hay un ejemplo de cómo escuchas los 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)
Si intenta esto, notará que los trozos son amortiguadores . Si no está tratando con datos binarios y necesita trabajar con cadenas, sugiero usar el método request.setEncoding que hace que la secuencia emita cadenas interpretadas con la codificación dada y maneja los caracteres de varios bytes correctamente.
Ahora 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 usa Buffer.concat , que simplemente concatena todos los buffers y devuelve un gran buffer. 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 el envío POST de formularios HTML sin archivos o si está recibiendo llamadas jQuery ajax con el tipo de contenido predeterminado, entonces el tipo de contenido es application/x-www-form-urlencoded
con uft-8
codificación. 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 en lugar de qs.parse .
Si está tratando con archivos o manejando un tipo de contenido multiparte, entonces en ese caso, debe usar algo como formidable que elimine todo el dolor de lidiar con él. Eche un vistazo a esta otra respuesta mía donde publiqué enlaces y módulos útiles para contenido de varias partes.
Si no desea analizar el contenido, sino pasarlo a otro lugar, por ejemplo, envíelo a otra solicitud http como datos o guárdelo en un archivo, sugiero canalizarlo en lugar de almacenarlo en el búfer, ya que será menos código, maneja mejor la contrapresión, tomará menos memoria y en algunos casos más rápido.
Entonces, si desea guardar el contenido en un archivo:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Como otras respuestas han señalado, tenga en cuenta que los clientes malintencionados pueden enviarle una gran cantidad de datos para bloquear su aplicación o llenar su memoria, para protegerlo y asegurarse de que descarta las solicitudes que emiten datos que pasan un cierto límite. Si no usa una biblioteca para manejar los datos entrantes. Sugeriría usar algo como el medidor de flujo que puede cancelar 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)), ...);
Si bien describí anteriormente cómo puede usar el cuerpo de solicitud HTTP, simplemente para almacenar en búfer y analizar el contenido, sugiero usar uno de estos módulos en lugar de implementarlo por su cuenta, ya que probablemente manejarán mejor los casos extremos. Para expresar, sugiero usar body-parser . Para koa, hay un módulo similar .
Si no usa un marco, el cuerpo es bastante bueno.
request
se reutilice y request.on('end')
se invoque varias veces? ¿Cómo puedo evitar eso?
request.on('end', ...)
se llamará.
Aquí hay un contenedor sin marco 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);
response.post
más lógico request.post
. Actualicé la publicación.
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));
});
}
}
qs.parse()
, JSON.parse()
convirtió el cuerpo en algo utilizable. Ejemplo:, var post = JSON.parse(body);
luego acceda a los datos con post.fieldname
. (Moraleja de la historia, si estás confundido acerca de lo que estás viendo, ¡no te olvides typeof
!)
request.setEncoding
para que esto funcione correctamente; de lo contrario, es posible que no maneje caracteres no ASCII correctamente.
Para cualquiera que se pregunte cómo hacer esta tarea trivial sin instalar un marco web, logré hacer esto juntos. Apenas listo para la producción 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 del 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);
})
Puede encontrar más documentación aquí.
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
});
Aquí es cómo puede hacerlo si usa formidable de nodo :
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
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}`);
});
1) Instalar 'body-parser'
desde npm.
2) Luego en tu app.ts
var bodyParser = require('body-parser');
3) entonces necesitas escribir
app.use(bodyParser.json())
en el módulo app.ts
4) ten en cuenta que incluyes
app.use(bodyParser.json())
en la parte superior o antes de cualquier declaración de módulo.
Ex:
app.use(bodyParser.json())
app.use('/user',user);
5) Luego use
var postdata = req.body;
Si no desea agrupar sus datos junto con la data
devolución de llamada, siempre puede usar la readable
devolución de llamada de esta manera:
// 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 termine su respuesta, la solicitud será recolectada de basura, 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.
request
es una secuencia normal de node.js, por lo que puede verificar la request.headers
longitud del cuerpo y cancelar la solicitud si es necesario.
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 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/
Debe recibir los POST
datos en fragmentos utilizandorequest.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 como lo sugiere jh .
setTimeout
que finalice la conexión después de un cierto período de tiempo, si la solicitud completa no se recibe dentro de esa ventana.
Si está utilizando Express.js , antes de poder acceder a req.body, debe agregar el middleware bodyParser:
app.use(express.bodyParser());
Entonces puedes pedir
req.body.user
Y si no desea utilizar todo el marco como Express, pero también necesita diferentes tipos de formularios, incluidas las cargas, entonces la formalina puede ser una buena opción.
Está listado en los módulos Node.js
Encontré un video que explica cómo lograr esto: https://www.youtube.com/watch?v=nuw48-u3Yrg
Utiliza el módulo predeterminado "http" junto con los módulos "querystring" y "stringbuilder". 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);
Para aquellos que usan carga POST binaria sin codificar, pueden 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!");
});
});
Puede usar el middleware express , que ahora tiene incorporado un analizador de cuerpo. Esto significa que todo lo que necesita hacer es lo siguiente:
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)
})
Ese ejemplo de código es ES6 con Express 4.16.x
puede extraer el parámetro de publicación sin usar express.
1: nmp install multiparty
2: importar multiparte. 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: y HTML FORM IS.
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
Espero que esto funcione para tí. Gracias.
Limite el tamaño de la POST para evitar inundar su aplicación de nodo. Hay un excelente módulo de cuerpo sin procesar , adecuado tanto para Express como para Connect, que puede ayudarlo a limitar la solicitud por tamaño y longitud.
Si implica la carga de un archivo, el navegador generalmente lo envía como un "multipart/form-data"
tipo de contenido. Puedes usar esto en tales casos
var multipart = require('multipart');
multipart.parse(req)
En campos de formulario como estos
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="myemail@somewherefarfar.com">
algunas de las respuestas anteriores fallarán porque solo admiten datos planos.
Por ahora estoy usando la respuesta Casey Chu pero con el "qs" en lugar del módulo "querystring". Este es también el módulo que utiliza "body-parser" . Entonces, si desea datos anidados, debe 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.
});
}
}
Puede enviar y obtener fácilmente la respuesta de la solicitud POST utilizando "Solicitud - Cliente HTTP simplificado" y Promesa 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);
}
});
});
}
Debe usar bodyParser () si desea que los datos del formulario estén disponibles en req.body. body-parser analiza su solicitud y la convierte a un formato desde el cual puede extraer fácilmente la información relevante que pueda necesitar.
Por ejemplo, supongamos que tiene un formulario de registro en su interfaz. Lo está completando y solicita al servidor que guarde los detalles en alguna parte.
Extraer el nombre de usuario y la contraseña de su solicitud es tan simple como a continuación si usa body-parser.
…………………………………………………….
var loginDetails = {
username : request.body.username,
password : request.body.password
};
ONE LINER sin MIDDLEWARE
Si publica los siguientes datos, 'name':'ABC'
puede analizarlos utilizando el siguiente liner,
require('url').parse(req.url, true).query.name