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

Joseph Dailey
źródło
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

Mick Cullen
źródło
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

sirthud
źródło
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' }

Jason Kim
źródło
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.

Xan-Kun Clark-Davis
źródło
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/

złóg
źródło
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”.

Tuan
źródło
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.

placet
źródł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.

Shaggie
źródło
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.

Mohammad Haque
źródło
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){});
Henry Ollarves
źródło
2

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

strona
źródło
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)
});
Tsando
źródło
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ć.

Phi
źródło
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">
Luke McCormick
źródło
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));
        }
    });
}
Achilles Ram Nakirekanti
źródło
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

winiet
źródło
0

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

server.use(restify.bodyParser());
Prabhat
źródło
0

Wierzę, że to może rozwiązać app.use(express.json());

Cleber Carvalho
źródło
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 :-)

Abhijith Brumal
źródło
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 ...

musiquarc
źródł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.

kaushalpranav
źródło
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!

Tushar Kudal
źródło