corps vide sur les messages

257

Tout d'un coup, cela s'est produit pour tous mes projets.

Chaque fois que je fais un post dans nodejs en utilisant express et body-parser req.bodyest un objet vide.

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

Via ajax et postman c'est toujours vide.

Cependant via curl

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

cela fonctionne comme prévu.

J'ai essayé de régler manuellement Content-type : application/jsonl'ancien, mais je reçois toujours400 bad request

Cela m'a rendu fou.

Je pensais que c'était quelque chose mis à jour dans l'analyseur corporel mais j'ai rétrogradé et cela n'a pas aidé.

Toute aide appréciée, merci.

Joseph Dailey
la source
16
Vous avez donc essayé de définir explicitement le Content-Typepostman? Sinon, vous pouvez essayer cela, car j'ai déjà eu des problèmes avec le facteur qui n'envoie pas de Content-Type.
mscdex
Oui je l'ai fait. c'est alors que j'ai reçu 400: json invalide
Joseph Dailey
@mscdex - merci, je n'ai pas défini content-tupe dans le facteur et devenais fou :)
Muzafar Ali
Pour les personnes qui viennent ici parce qu'elles souhaitent envoyer / télécharger des fichiers à partir de leurs API et doivent donc utiliser des données de formulaire. Vous avez besoin de quelque chose pour gérer les données du formulaire: npmjs.com/package/multer est un package assez populaire.
bhaskar
Quoi qu'il en soit, postman ne gère pas très bien les entiers et les valeurs flottantes. Si vous avez des valeurs entières ou flottantes, assurez-vous de tout mettre entre guillemets, clés et valeurs
anabeto93

Réponses:

272

Dans Postman des 3 options disponibles pour le type de contenu, sélectionnez "X-www-form-urlencoded" et cela devrait fonctionner.

Aussi pour se débarrasser du message d'erreur, remplacez:

app.use(bodyParser.urlencoded())

Avec:

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

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

Le middleware 'body-parser' ne gère que les données JSON et urlencodées, pas les parties multiples

Mick Cullen
la source
Cela a fonctionné pour le facteur, je ne sais pas pourquoi cela fonctionne avec ajax car je n'ai rien changé.
Joseph Dailey
Pour une raison quelconque, les publications http via Angular n'avaient pas besoin d'être encodées en URL, mais les appels ajax l'ont fait. Quelqu'un sait pourquoi?
youngrrrr
Cela a fonctionné pour moi, pourquoi ne fonctionnait-il pas avec du codage brut?
Daniel Kobe
9
maintenant l'analyseur de corps est intégré avec express.js, utilisez simplementapp.use(express.json());
Sujeet Agrahari
Merci beaucoup! Malgré le temps qu'il a fallu pour y répondre, c'est toujours d'actualité.
Spray'n'Pray
218

Avec Postman, pour tester les actions de publication HTTP avec une charge utile de données JSON brutes, sélectionnez l' rawoption et définissez les paramètres d'en-tête suivants:

Content-Type: application/json

Veillez également à encapsuler toutes les chaînes utilisées comme clés / valeurs dans votre charge utile JSON entre guillemets.

Le body-parserpaquet analysera très bien les charges utiles JSON brutes sur plusieurs lignes.

{
    "foo": "bar"
}

Testé dans Chrome v37 et v41 avec l'extension Postman v0.8.4.13 ( body-parserv1.12.2 et expressv4.12.3) avec la configuration ci-dessous:

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

Postman raw json payload

sirthud
la source
Oh mec, comment ai-je pu manquer d'avoir collé un objet JS littéral plutôt qu'un objet JSON correctement formaté ...: -S ... merci mon ami!
Wes Johnson
Envelopper toutes les chaînes utilisées comme clés / valeurs entre guillemets ... Facile à manquer, mais une rupture totale sinon! Je vous remercie.
loxyboi
Bonne utilisation des captures d'écran.
Xan-Kun Clark-Davis
Lors de l'utilisation form-datadans Postman pour publier les données, je reçois toujours le {}dans le corps de la demande. Dois-je définir l' Content-Typeoption?
mingchau
56

J'ai fait une erreur vraiment stupide et j'ai oublié de définir les nameattributs des entrées dans mon fichier html.

Donc au lieu de

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

J'ai ceci.

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

Maintenant request.bodyest rempli comme ceci:{ password: 'hhiiii' }

Jason Kim
la source
1
Bam. C'était ça le problème. Merci!
Matt West
C'était exactement mon problème, une entrée de formulaire sans valeur de nom, a passé des heures à essayer de le comprendre. Merci.
karensantana
37

J'ai découvert que cela fonctionne lors de l'envoi avec un type de contenu

"application / json"

en combinaison avec côté serveur

app.use(bodyParser.json());

Maintenant, je peux envoyer via

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

et le résultat est disponible request.body.namesur le serveur.

Xan-Kun Clark-Davis
la source
Merci pour le vote positif. Je pense vraiment que c'est la solution la plus propre, mais pas la plus simple, car vous devez de toute façon envoyer le type de contenu correct. Je pense.
Xan-Kun Clark-Davis
c'est la réponse!
Gel
Dans mon cas, j'ai dû le remplacer parxmlHttp.send(JSON.stringify(data));
endo64
18

J'ai rencontré ce problème aujourd'hui, et ce qui l'a résolu, c'était de supprimer l'en-tête de type de contenu dans Postman! Très étrange. L'ajouter ici au cas où cela aiderait quelqu'un.

Je suivais le tutoriel BeerLocker ici: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

calcul
la source
2
J'ai eu le même problème. avoir l'en-tête "décoché" (et grisé) ne suffisait pas, j'ai dû le retirer complètement. même si le bouton source "</>" montre que je n'envoyais pas cet en-tête avec le Content-Type étant dans l'état non contrôlé, il devait encore être complètement supprimé.
theRemix
Je ne sais pas comment supprimer les en-têtes par défaut dans l'extension chrome de postman ... utilisez-vous peut-être l'application?
WestleyArgentum
Oh, j'ai installé l'application et cela fonctionne beaucoup mieux que l'extension. Désolé pour le bruit.
WestleyArgentum
12

Vous devez vérifier si le middleware body-parser est correctement configuré pour le type de requête (json, urlencoded).

Si vous avez défini,

app.use(bodyParser.json());

dans postman, vous devez envoyer les données sous forme brute.

https://i.stack.imgur.com/k9IdQ.png capture d'écran du facteur

Si vous avez défini,

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

alors l'option 'x-www-form-urlencoded' doit être sélectionnée.

Tuan
la source
qu'en est-il d'avoir les deux? (bodyParser.urlencoded et bodyParser.json ()) ... lequel puis-je utiliser dans postman?
TommyLeong
9

Mon problème était que je créais d'abord l'itinéraire

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

et enregistrer le middleware après l'itinéraire

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

en raison de la structure de l'application et copiez et collez le projet ensemble à partir d'exemples.

Une fois que j'ai corrigé l'ordre d'enregistrer le middleware avant l'itinéraire, tout a fonctionné.

décret
la source
merci fiat, avec le bon ordre et en utilisant l'onglet brut, cela a enfin fonctionné pour moi
Alex
4

Même lorsque j'apprenais node.js pour la première fois où je commençais à l'apprendre via une application Web, je faisais bien toutes ces choses dans mon formulaire, mais je ne pouvais toujours pas recevoir de valeurs en post-demande. Après un long débogage, j'ai appris que, sous la forme que j'ai fournie, je n'ai enctype="multipart/form-data"pas pu obtenir de valeurs. Je l'ai simplement retiré et cela a fonctionné pour moi.

Shaggie
la source
oui, cela a également fonctionné pour obtenir le corps du formulaire, mais a ensuite causé un autre problème avec mon formulaire - fondamentalement, le fichier n'a pas pu être téléchargé car cela nécessiteenctype="multipart/form-data"
tsando
btw, juste pour ajouter à mon commentaire ci-dessus, j'ai réussi à faire fonctionner cela multer- voir la documentation sur npmjs.com/package/multer
tsando
3

Il semble que si vous n'utilisez pas d'encType (la valeur par défaut est application/x-www-form-urlencoded), vous obtenez des champs de saisie de texte mais vous n'obtiendrez pas de fichier.

Si vous avez un formulaire où vous souhaitez publier une entrée de texte et un fichier, utilisez le multipart/form-datatype de codage et en plus de cela, utilisez un multermiddleware. Multer analysera l'objet de demande et se préparera req.filepour vous et tous les autres champs de saisie seront disponibles via req.body.

Mohammad Haque
la source
1
merci - multerétait en effet la solution à mon problème. Ce serait bien si vous pouviez ajouter un exemple sur la façon de l'utiliser dans le cadre de votre réponse
tsando
2

Un problème similaire m'est arrivé, j'ai simplement mélangé l'ordre des paramètres de rappel. Assurez-vous que vous configurez les fonctions de rappel dans le bon ordre. Au moins pour toute personne ayant le même problème.

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

Assurez-vous que ["key": "type", "value": "json"] & ["key": "Content-Type", "value": "application / x-www-form-urlencoded"] est dans votre en-têtes de demande de facteur

vpage
la source
2

J'ai résolu cela en utilisant multercomme suggéré ci-dessus, mais ils ont manqué de donner un exemple de travail complet, sur la façon de le faire. Fondamentalement, cela peut se produire lorsque vous avez un groupe de formulaires avec enctype="multipart/form-data". Voici le HTML du formulaire que j'avais:

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

Et voici comment utiliser multerpour obtenir les valeurs et les noms de ce formulaire avec Express.jset 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
la source
1

J'ai eu le même problème il y a quelques minutes, j'ai essayé tout ce qui était possible dans les réponses ci-dessus, mais aucune n'a fonctionné.

La seule chose que j'ai faite, c'est la mise à niveau de la version Node JS, je ne savais pas que la mise à niveau pouvait affecter quelque chose, mais elle l'a fait.

J'ai installé la version Node JS 10.15.0(dernière version), je suis revenu sur 8.11.3et tout fonctionne maintenant. Peut-être que le body-parsermodule devrait corriger cela.

Phi
la source
1

Je n'avais pas le nom dans mon entrée ... ma demande était vide ... heureux que cela soit terminé et je peux continuer à coder. Merci tout le monde!

Réponse que j'ai utilisée par Jason Kim:

Donc au lieu de

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

J'ai ceci

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

vous ne devriez pas faire JSON.stringify(data)lors de l'envoi via AJAX comme ci-dessous.

Ce n'est PAS un code correct:

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

Le bon code est:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}
Achilles Ram Nakirekanti
la source
une chose clé à noter ici est que dans le type, assurez-vous de mettre en majuscule "POST". J'ai vu des cas où le simple fait d'utiliser "post" a conduit à une requête vide.
Matt C.
1

Si vous faites avec le facteur, veuillez confirmer ces choses lorsque vous demandez une API

entrez la description de l'image ici

vignesh
la source
0

J'utilisais restify au lieu d'exprimer et j'ai rencontré le même problème. La solution était de faire:

server.use(restify.bodyParser());
Prabhat
la source
0

Je crois que cela peut résoudre app.use(express.json());

Cleber Carvalho
la source
0

Changez app.use(bodyParser.urlencoded());votre code en

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

et dans postman, dans l'en-tête, changez la Content-Typevaleur de application/x-www-form-urlencodedenapplication/json

Ta :-)

Abhijith Brumal
la source
0

Merci à tous pour vos bonnes réponses! J'ai passé pas mal de temps à chercher une solution, et de mon côté je faisais une erreur élémentaire: j'appelais bodyParser.json()depuis la fonction:

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

J'avais juste besoin de faire app.use(['/password'], bodyParser.json())et ça a marché ...

musiquarc
la source
0

Dans Postman, même après avoir suivi la réponse acceptée, je recevais un corps de demande vide. Le problème s'est avéré ne pas passer un en-tête appelé

Content-Length : <calculated when request is sent>

Cet en-tête était présent par défaut (avec 5 autres) que j'ai désactivé. Activez-le et vous recevrez le corps de la demande.

kaushalpranav
la source
0

Mon problème était de créer l'itinéraire d'abord, require("./routes/routes")(app); je l'ai déplacé à la fin du code avant app.listen et cela a fonctionné!

Tushar Kudal
la source
0

Déjà résolu le problème, mais peut aider quelqu'un.

Assurez-vous que chacun de vos éléments de formulaire est associé à un nom. C'était l'erreur que je faisais ...!

Ensoleillé
la source