req.body vacío en publicaciones

256

De repente, esto ha estado sucediendo a todos mis proyectos.

Cada vez que hago una publicación en nodejs usando express y body-parser req.bodyes un objeto vacío.

var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())

// parse application/json
app.use(bodyParser.json())

app.listen(2000);

app.post("/", function (req, res) {
  console.log(req.body) // populated!
  res.send(200, req.body);
});

A través de ajax y cartero siempre está vacío.

Sin embargo a través de curl

$ curl -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:2000/

Funciona según lo previsto.

Traté de configurar manualmente Content-type : application/jsonen el primero pero siempre obtengo400 bad request

Esto me ha estado volviendo loco.

Pensé que era algo actualizado en el analizador del cuerpo, pero lo degradé y no ayudó.

Cualquier ayuda apreciada, gracias.

Joseph Dailey
fuente
16
¿Entonces trataste de configurar explícitamente el Content-Typecartero? Si no, puede intentarlo, ya que he tenido problemas antes con el cartero no enviando un Content-Type.
mscdex
Sí, lo hice. fue cuando recibí 400: json inválido
Joseph Dailey
@mscdex: gracias, no configuré content-tupe en cartero y me estaba volviendo loco :)
Muzafar Ali
Para aquellas personas que vienen aquí porque desean enviar / cargar archivos desde sus API y, por lo tanto, tienen que usar datos de formulario. Necesita algo para manejar los datos del formulario: npmjs.com/package/multer es un paquete bastante popular.
bhaskar
Pase lo que pase, el cartero no trata muy bien los enteros y los valores flotantes. Si tiene valores enteros o flotantes, asegúrese de hacer una doble cita de todo, tanto las claves como los valores
anabeto93

Respuestas:

272

En Cartero de las 3 opciones disponibles para el tipo de contenido, seleccione "X-www-form-urlencoded" y debería funcionar.

También para deshacerse del mensaje de error, reemplace:

app.use(bodyParser.urlencoded())

Con:

app.use(bodyParser.urlencoded({
  extended: true
}));

Ver https://github.com/expressjs/body-parser

El middleware 'body-parser' solo maneja datos JSON y urlencoded, no multiparte

Mick Cullen
fuente
Eso funcionó para el cartero, no estoy seguro de por qué funciona con ajax ya que no cambié nada.
Joseph Dailey
Por alguna razón, las publicaciones http a través de Angular no tenían que estar codificadas en URL, pero las llamadas ajax sí. Alguien sabe por qué?
youngrrrr
Esto funcionó para mí, ¿por qué no funcionaba con codificación sin procesar?
Daniel Kobe
99
ahora body-parser está incorporado con express.js solo usoapp.use(express.json());
Sujeet Agrahari
Muchas gracias! A pesar del largo tiempo que esto ha sido respondido, sigue siendo relevante.
Spray'n'Pray
218

Con Postman, para probar las acciones de publicación HTTP con una carga de datos JSON sin procesar, seleccione la rawopción y configure los siguientes parámetros de encabezado:

Content-Type: application/json

Además, asegúrese de ajustar las cadenas utilizadas como claves / valores en su carga útil JSON entre comillas dobles.

El body-parserpaquete analizará las cargas útiles JSON crudas de varias líneas muy bien.

{
    "foo": "bar"
}

Probado en Chrome v37 y v41 con la extensión Postman v0.8.4.13 ( body-parserv1.12.2 y expressv4.12.3) con la siguiente configuración:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// ... Your routes and methods here

Cartero raw json payload

sirthud
fuente
Oh hombre, ¿cómo extrañé que pegué un objeto JS literal en lugar de un objeto JSON formateado correctamente ...: -S ... gracias amigo!
Wes Johnson
Envolviendo cualquier cadena utilizada como clave / valor en comillas dobles ... ¡Fácil de perder pero de lo contrario es un factor decisivo! Gracias.
loxyboi
Buen uso de capturas de pantalla.
Xan-Kun Clark-Davis
Cuando uso form-dataen Postman para publicar los datos, siempre obtengo el {}en el req.body. ¿Debo establecer la Content-Typeopción?
mingchau
56

Cometí un error realmente tonto y olvidé definir nameatributos para las entradas en mi archivo html.

Entonces en lugar de

<input type="password" class="form-control" id="password">

Tengo esto.

<input type="password" class="form-control" id="password" name="password">

Ahora request.bodyse rellena así:{ password: 'hhiiii' }

Jason Kim
fuente
1
Bam Ese fue el problema. ¡Gracias!
Matt West
Ese fue exactamente mi problema, una entrada de formulario sin valores de nombre, pasé horas tratando de resolverlo. Gracias.
karensantana 05 de
37

Descubrí que funciona al enviar con tipo de contenido

"aplicación / json"

en combinación con el lado del servidor

app.use(bodyParser.json());

Ahora puedo enviar vía

var data = {name:"John"}
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.send(data);

y el resultado está disponible en request.body.nameel servidor.

Xan-Kun Clark-Davis
fuente
Gracias por el voto a favor. Realmente creo que esta es la solución más limpia, aunque no la más simple, ya que de todos modos debe enviar el tipo de contenido correcto. Yo creo que.
Xan-Kun Clark-Davis
¡esta es la respuesta!
Gel
En mi caso tuve que cambiarlo axmlHttp.send(JSON.stringify(data));
endo64
18

¡Me encontré con este problema hoy, y lo que solucionó fue eliminar el encabezado de tipo contenido en Postman! Muy extraño. Agregándolo aquí en caso de que ayude a alguien.

Estaba siguiendo el tutorial de BeerLocker aquí: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

Roca
fuente
2
Tuve el mismo problema. tener el encabezado "desmarcado" (y atenuado) no fue suficiente, tuve que eliminarlo por completo. a pesar de que el botón de fuente "</>" muestra que no estaba enviando ese encabezado con el Tipo de contenido en el estado desmarcado, todavía necesitaba ser eliminado por completo.
theRemix
No puedo entender cómo eliminar los encabezados predeterminados en la extensión de Chrome para cartero ... ¿está utilizando la aplicación tal vez?
WestleyArgentum
Oh, instalé la aplicación y funciona mucho mejor que la extensión. Perdón por el ruido.
WestleyArgentum
12

Debe verificar si el middleware body-parser está configurado correctamente para el tipo de solicitud (json, urlencoded).

Si has establecido,

app.use(bodyParser.json());

entonces en cartero tienes que enviar los datos como sin procesar.

https://i.stack.imgur.com/k9IdQ.png captura de pantalla del cartero

Si has establecido,

app.use(bodyParser.urlencoded({
    extended: true
}));

entonces se debe seleccionar la opción 'x-www-form-urlencoded'.

Tuan
fuente
¿Qué hay de tener ambos? (bodyParser.urlencoded y bodyParser.json ()) ... ¿cuál puedo usar en cartero?
TommyLeong
9

Mi problema fue que estaba creando la ruta primero

// ...
router.get('/post/data', myController.postHandler);
// ...

y registrar el middleware después de la ruta

app.use(bodyParser.json());
//etc

debido a la estructura de la aplicación y copiar y pegar el proyecto juntos a partir de ejemplos.

Una vez que arreglé el pedido para registrar el middleware antes de la ruta, todo funcionó.

fíat
fuente
gracias fiat, con el orden correcto y usando la pestaña en bruto, me funcionó por fin
Alex
4

Incluso cuando estaba aprendiendo node.js por primera vez donde comencé a aprenderlo a través de la aplicación web, estaba haciendo todas estas cosas de manera correcta en mi forma, aún no podía recibir valores en la solicitud posterior. Después de una larga depuración, llegué a saber que en la forma que he proporcionado enctype="multipart/form-data"debido a que no pude obtener valores. Simplemente lo eliminé y funcionó para mí.

Shaggie
fuente
sí, esto también funcionó para obtener el cuerpo del formulario, pero luego causó otro problema con mi formulario, básicamente el archivo no se pudo cargar como se requiereenctype="multipart/form-data"
tsando el
por cierto, solo para agregar a mi comentario anterior, logré hacer que esto funcione multer- vea la documentación en npmjs.com/package/multer
tsando
3

Parece que si no usa ningún encType (el valor predeterminado es application/x-www-form-urlencoded), entonces obtiene campos de entrada de texto pero no obtendría el archivo.

Si tiene un formulario en el que desea publicar entradas de texto y archivos, use el multipart/form-datatipo de codificación y, además, use multermiddleware. Multer analizará el objeto de solicitud y se preparará req.filepara usted y todos los demás campos de entrada estarán disponibles a través de req.body.

Mohammad Haque
fuente
1
gracias - de multerhecho fue la solución a mi problema. Sería bueno si pudiera agregar un ejemplo sobre cómo usar esto como parte de su respuesta
tsando
2

Me ocurrió un problema similar, simplemente mezclé el orden de los parámetros de devolución de llamada. Asegúrese de configurar las funciones de devolución de llamada en el orden correcto. Al menos para cualquiera que tenga el mismo problema.

router.post('/', function(req, res){});
Henry Ollarves
fuente
2

Asegúrese de que ["key": "type", "value": "json"] & ["key": "Content-Type", "value": "application / x-www-form-urlencoded"] esté en su encabezados de solicitud de cartero

vpage
fuente
2

Resolví esto usando multercomo se sugirió anteriormente, pero no dieron un ejemplo de trabajo completo sobre cómo hacerlo. Básicamente esto puede suceder cuando tienes un grupo de formularios con enctype="multipart/form-data". Aquí está el HTML para el formulario que tenía:

<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file">
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
    <input type="submit" value="Get me the stats!" class="btn btn-default">            
  </div>
</form>

Y aquí se explica cómo usar multerpara obtener los valores y nombres de este formulario con Express.jsy node.js:

var multer  = require('multer')
var upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
   // req.file is the name of your file in the form above, here 'uploaded_file'
   // req.body will hold the text fields, if there were any 
   console.log(req.file, req.body)
});
tsando
fuente
1

Tuve el mismo problema hace unos minutos, intenté todo lo posible en las respuestas anteriores, pero ninguno de ellos funcionó.

Lo único que hice fue actualizar la versión Node JS, no sabía que la actualización podría afectar en algo, pero lo hizo.

He instalado la versión Node JS 10.15.0(última versión), regresé 8.11.3y ahora todo funciona. Tal vez el body-parsermódulo debería solucionarlo.

Fi
fuente
1

No tenía el nombre en mi entrada ... mi solicitud estaba vacía ... contento de que haya terminado y pueda seguir codificando. ¡Gracias a todos!

Respuesta que utilicé Jason Kim:

Entonces en lugar de

<input type="password" class="form-control" id="password">

tengo esto

<input type="password" class="form-control" id="password" name="password">
Luke McCormick
fuente
1

no debe hacer JSON.stringify(data)mientras envía a través de AJAX como a continuación

Este NO es el código correcto:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: JSON.stringify(data),
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}   

El código correcto es:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}
Achilles Ram Nakirekanti
fuente
Una cosa clave a tener en cuenta aquí es que, en tipo, asegúrese de poner en mayúscula "POST". He visto casos en los que solo usar "post" ha llevado a req.body en blanco.
Matt C.
1

Si lo está haciendo con el cartero, confirme estas cosas cuando solicite API

ingrese la descripción de la imagen aquí

vignesh
fuente
0

Estaba usando restify en lugar de express y me encontré con el mismo problema. La solución fue hacer:

server.use(restify.bodyParser());
Prabhat
fuente
0

Creo que esto puede resolver app.use(express.json());

Cleval Carvalho
fuente
0

Cambie app.use(bodyParser.urlencoded());su código a

app.use(bodyParser.urlencoded({extended : false}));

y en cartero, en el Content-Typevalor de cambio de encabezado de application/x-www-form-urlencodedaapplication/json

Ejército de reserva:-)

Abhijith Brumal
fuente
0

¡Gracias a todos por sus excelentes respuestas! Pasé bastante tiempo buscando una solución y, por mi parte, estaba cometiendo un error elemental: estaba llamando bodyParser.json()desde la función:

app.use(['/password'], async (req, res, next) => {
  bodyParser.json()
  /.../
  next()
})

Solo necesitaba hacerlo app.use(['/password'], bodyParser.json())y funcionó ...

musiquarc
fuente
0

En cartero, incluso después de seguir la respuesta aceptada, recibía un cuerpo de solicitud vacío. El problema resultó no ser pasar un encabezado llamado

Content-Length : <calculated when request is sent>

Este encabezado estaba presente por defecto (junto con otros 5) que he desactivado. Habilite esto y recibirá el cuerpo de la solicitud.

kaushalpranav
fuente
0

Mi problema fue crear la ruta primero. ¡ require("./routes/routes")(app); Lo cambié al final del código antes app.listen y funcionó!

Tushar Kudal
fuente
0

Ya resuelto el problema, pero puede ayudar a alguien.

Procure que cada uno de sus elementos de formulario tenga algún nombre asociado. Este fue el error que estaba cometiendo ...!

Soleado
fuente