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.


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


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


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


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.


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/


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.


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


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.


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.


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

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


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

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.


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

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

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


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


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


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


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.


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


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.