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.


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


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


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' }


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.


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/


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'.


¿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ó.


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í.


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.


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){});

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


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)
});

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.


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">

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));
        }
    });
}

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í


0

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

server.use(restify.bodyParser());


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:-)


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ó ...


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.


0

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


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 ...!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.