req.body pusty w postach


255

Nagle stało się tak ze wszystkimi moimi projektami.

Ilekroć piszę w nodejs za pomocą express i body-parser, req.bodyjest to pusty obiekt.

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

Przez ajax i listonosz jest zawsze pusty.

Jednak poprzez zwijanie

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

działa zgodnie z przeznaczeniem.

Próbowałem ręcznie ustawić Content-type : application/jsonw tym pierwszym, ale zawsze otrzymuję400 bad request

Doprowadzało mnie to do szału.

Myślałem, że to coś zaktualizowanego w parserze ciała, ale obniżyłem ocenę i to nie pomogło.

Dziękujemy za pomoc, dziękuję.


16
Więc próbowałeś jawnie ustawić Content-Typelistonosza w? Jeśli nie, możesz spróbować, ponieważ miałem wcześniej problemy z tym, że listonosz nie wysyła wiadomości Content-Type.
mscdex,

tak. wtedy otrzymałem 400: Nieprawidłowy Json
Joseph Dailey

@mscdex - dzięki, że nie ustawiłem content-tupe na listonoszu i oszalałem :)
Muzafar Ali

Dla osób, które tu przyjeżdżają, ponieważ chcą wysyłać / przesyłać pliki ze swoich interfejsów API, a zatem muszą korzystać z danych formularza. Potrzebujesz czegoś do obsługi danych formularza: npmjs.com/package/multer to dość popularny pakiet.
bhaskar

Bez względu na to, listonosz nie radzi sobie dobrze z liczbami całkowitymi i wartościami zmiennoprzecinkowymi. Jeśli masz wartości całkowite lub zmiennoprzecinkowe,
pamiętaj

Odpowiedzi:


272

W Postman z 3 dostępnych opcji typu zawartości wybierz „X-www-form-urlencoded” i powinno działać.

Aby pozbyć się komunikatu o błędzie, zamień:

app.use(bodyParser.urlencoded())

Z:

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

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

Oprogramowanie pośrednie „body-parser” obsługuje tylko JSON i dane zakodowane w url, nie wieloczęściowe


To działało dla listonosza, nie jestem pewien, dlaczego działa z ajaxem, ponieważ niczego nie zmieniłem.
Joseph Dailey

Z jakiegoś powodu posty http za pośrednictwem Angulara nie musiały być zakodowane w adresie URL, ale wywołania ajaxowe tak. Czy ktoś wie dlaczego?
youngrrrr

To działało dla mnie, dlaczego jednak nie działało z kodowaniem raw?
Daniel Kobe,

9
teraz body-parser jest wbudowany w express.js wystarczy użyćapp.use(express.json());
Sujeet Agrahari

Dziękuję bardzo! Pomimo długiego czasu odpowiedzi na to pytanie, jest on nadal aktualny.
Spray'n'Pray

217

Aby przetestować akcje post HTTP za pomocą surowego ładunku danych JSON, wybierz rawopcję i ustaw następujące parametry nagłówka:

Content-Type: application/json

Pamiętaj też, aby zawrzeć wszelkie ciągi używane jako klucze / wartości w ładunku JSON podwójnymi cudzysłowami.

body-parserPakiet będzie analizować kilka linii surowy JSON ładunki dobrze.

{
    "foo": "bar"
}

Testowane w Chrome v37 i v41 z rozszerzeniem Postman v0.8.4.13 ( body-parserv1.12.2 i expressv4.12.3) z poniższą konfiguracją:

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

Listonosz surowy ładunek Json


O rany, jak mi brakowało, że wkleiłem dosłownie obiekt JS zamiast poprawnie sformatowanego obiektu JSON ...: -S ... dzięki przyjacielu!
Wes Johnson

Zawijanie ciągów znaków używanych jako kluczowe / wartości w podwójnych cudzysłowach ... Łatwo przeoczyć, ale w przeciwnym razie całkowicie przełamie umowę! Dziękuję Ci.
loxyboi

Dobre wykorzystanie zrzutów ekranu.
Xan-Kun Clark-Davis

Kiedy korzystam form-dataz Postmana do publikowania danych, zawsze dostaję to {}na żądanie. Czy powinienem ustawić Content-Typeopcję?
mingchau

56

Popełniłem naprawdę głupi błąd i zapomniałem zdefiniować name atrybuty danych wejściowych w moim pliku HTML.

Więc zamiast

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

Mam to.

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

Teraz request.bodyjest wypełnione w następujący sposób:{ password: 'hhiiii' }


1
Bam To był problem. Dzięki!
Matt West

To był dokładnie mój problem, formularz wejściowy bez wartości nazw, spędziłem godziny próbując go rozgryźć. Dzięki.
karensantana

37

Odkryłem, że działa podczas wysyłania z typem zawartości

„application / json”

w połączeniu z serwerem

app.use(bodyParser.json());

Teraz mogę wysłać przez

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

a wynik jest dostępny request.body.namena serwerze.


Dzięki za głos. Naprawdę uważam, że jest to najczystsze, choć nie najprostsze rozwiązanie, ponieważ i tak powinieneś wysłać poprawny typ zawartości. Myślę.
Xan-Kun Clark-Davis

to jest odpowiedź!
Gel

W moim przypadku musiałem to zmienić naxmlHttp.send(JSON.stringify(data));
endo64

18

Zetknąłem się dzisiaj z tym problemem i naprawiłem to, usuwając nagłówek typu zawartości w Postman! Bardzo dziwny. Dodanie go tutaj na wypadek, gdyby komuś pomogło.

Śledziłem samouczek BeerLocker tutaj: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/


2
miałem ten sam problem. posiadanie nagłówka „niezaznaczonego” (i wyszarzonego) nie było wystarczające, musiałem go całkowicie usunąć. nawet jeśli przycisk źródłowy „</>” pokazuje, że nie wysyłałem tego nagłówka, gdy Content-Type jest w niezaznaczonym stanie, nadal trzeba go całkowicie usunąć.
theRemix

Nie mogę wymyślić, jak usunąć domyślne nagłówki w rozszerzeniu chrome listonosza ... może używasz aplikacji?
WestleyArgentum

Och, zainstalowałem aplikację i działa ona znacznie lepiej niż rozszerzenie. Przepraszam za hałas.
WestleyArgentum

12

Musisz sprawdzić, czy oprogramowanie pośredniczące analizatora ciała jest ustawione poprawnie na typ żądania (json, urlencoded).

Jeśli ustawiłeś,

app.use(bodyParser.json());

następnie w listonoszu musisz wysłać dane jako surowe.

https://i.stack.imgur.com/k9IdQ.png zrzut ekranu listonosza

Jeśli ustawiłeś,

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

następnie należy wybrać opcję „x-www-form-urlencoded”.


co z posiadaniem ich obu? (bodyParser.urlencoded i bodyParser.json ()) ... którego można użyć w listonoszu?
TommyLeong

9

Mój problem polegał na tym, że najpierw tworzyłem trasę

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

i rejestrowanie oprogramowania pośredniego po trasie

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

ze względu na strukturę i kopiowanie aplikacji oraz wklejanie projektu razem z przykładów.

Gdy ustaliłem kolejność rejestrowania oprogramowania pośredniego przed trasą, wszystko działało.


dzięki fiat, z odpowiednią kolejnością i przy użyciu surowej zakładki to w końcu dla mnie zadziałało
Alex

4

Nawet kiedy uczyłem się node.js po raz pierwszy, kiedy zacząłem uczyć się go za pomocą aplikacji internetowej, wszystko to robiłem dobrze w mojej formie, nadal nie byłem w stanie odbierać wartości w odpowiedzi na żądanie. Po długim debugowaniu dowiedziałem się, że w formie, którą podałem, enctype="multipart/form-data"dzięki czemu nie byłem w stanie uzyskać wartości. Po prostu go usunąłem i zadziałało dla mnie.


tak, to również działało, aby uzyskać enctype="multipart/form-data"
treść

btw, tylko aby dodać do powyższego komentarza, udało mi się uzyskać z tym pracować multer- patrz dokumentacja na npmjs.com/package/multer
tsando

3

Wygląda na to, że nie używasz żadnego encType (domyślnie jest to application/x-www-form-urlencoded ), dostaniesz pola wprowadzania tekstu, ale nie dostaniesz pliku.

Jeśli masz formularz, w którym chcesz zaksięgować wprowadzanie tekstu i plik, użyj multipart/form-datatypu kodowania, a oprócz tego użyj multeroprogramowania pośredniego. Multer przeanalizuje obiekt żądania i przygotuje req.filedla ciebie, a wszystkie inne pola wejściowe będą dostępne za pośrednictwem req.body.


1
dzięki - multerrzeczywiście było rozwiązaniem mojego problemu. Byłoby dobrze, gdybyś mógł dodać przykład, w jaki sposób korzystać z tego w ramach swojej odpowiedzi
tsando

2

Podobny problem przydarzył mi się, po prostu wymieszałem kolejność parametrów wywołania zwrotnego. Upewnij się, że konfigurujesz funkcje oddzwaniania we właściwej kolejności. Przynajmniej dla każdego, kto ma ten sam problem.

router.post('/', function(req, res){});

2

Upewnij się, że [„klucz”: „typ”, „wartość”: „json”] i [„klucz”: „Typ zawartości”, „wartość”: „application / x-www-form-urlencoded”] nagłówki żądania listonosza


2

Rozwiązałem ten problem, multerjak wskazano powyżej, ale nie udało im się podać pełnego roboczego przykładu, jak to zrobić. Zasadniczo może się to zdarzyć, gdy masz grupę formularzy enctype="multipart/form-data". Oto kod HTML dla formularza, który miałem:

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

A oto jak używać multer aby uzyskać wartości i nazwy tego formularza za pomocą Express.jsi 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

Miałem ten sam problem kilka minut temu, próbowałem wszystkiego, co możliwe w powyższych odpowiedziach, ale żadna z nich nie zadziałała.

Jedyną rzeczą, którą zrobiłem, było uaktualnienie wersji Node JS, nie wiedziałem, że aktualizacja może mieć wpływ na coś, ale tak się stało.

Zainstalowałem wersję Node JS 10.15.0(najnowsza wersja), do której wróciłem 8.11.3i wszystko działa. Może body-parsermoduł powinien to naprawić.


1

Nie miałem nazwy w danych wejściowych ... moja prośba była pusta ... cieszę się, że została zakończona i mogę kontynuować kodowanie. Dziękuję wszystkim!

Odpowiedź, której użyłem Jason Kim:

Więc zamiast

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

Mam to

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

1

nie powinieneś tego robić JSON.stringify(data)podczas wysyłania przez AJAX jak poniżej.

To NIE jest poprawny kod:

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

Prawidłowy kod to:

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

Kluczową rzeczą, na którą należy tutaj zwrócić uwagę, jest to, że wpisujesz wielką literę „POST”. Widziałem przypadki, w których samo użycie „wysyłania” doprowadziło do pustego zapotrzebowania na osobę.
Matt C.

1

Jeśli robisz to z listonoszem, potwierdź te rzeczy, gdy prosisz o API

wprowadź opis zdjęcia tutaj


0

Używałem restify zamiast express i napotkałem ten sam problem. Rozwiązaniem było:

server.use(restify.bodyParser());


0

Zmień app.use(bodyParser.urlencoded());kod na

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

oraz w listonoszu, w nagłówku zmień Content-Typewartość z application/x-www-form-urlencodednaapplication/json

Ta :-)


0

Dziękujemy wszystkim za wspaniałe odpowiedzi! Spędziłem trochę czasu na poszukiwaniu rozwiązania, a ze swojej strony popełniłem podstawowy błąd: dzwoniłem bodyParser.json()z funkcji:

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

Po prostu musiałem to zrobić app.use(['/password'], bodyParser.json())i zadziałało ...


0

W listonoszu, nawet po otrzymaniu zaakceptowanej odpowiedzi, dostawałem puste ciało z prośbą. Problemem okazało się nie przekazywanie nagłówka o nazwie

Content-Length : <calculated when request is sent>

Ten nagłówek był domyślnie obecny (wraz z 5 innymi), które wyłączyłem. Włącz to, a otrzymasz treść żądania.


0

Mój problem polegał na tym, że najpierw utworzyłem trasę. require("./routes/routes")(app); Przesunąłem ją na koniec kodu app.listen i zadziałało!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.