Express.js wymaga.body undefined

291

Mam to jako konfigurację mojego serwera Express

app.use(app.router); 
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());

Ale wciąż, gdy pytam o to req.body.somethingna moich trasach, pojawia się błąd, który to wskazuje body is undefined. Oto przykład trasy, która wykorzystuje req.body:

app.post('/admin', function(req, res){
    console.log(req.body.name);
});

Czytam, że ten problem jest spowodowany brakiem, app.use(express.bodyParser());ale jak widać nazywam go przed trasami.

Jakieś wskazówki?

Masiar
źródło

Odpowiedzi:

296

Musisz upewnić się, że zdefiniowałeś wszystkie konfiguracje PRZED zdefiniowaniem tras. Jeśli to zrobisz, możesz nadal korzystać express.bodyParser().

Przykład jest następujący:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

app.configure(function(){
  app.use(express.bodyParser());
  app.use(app.router);
});

app.listen(port);

app.post("/someRoute", function(req, res) {
  console.log(req.body);
  res.send({ status: 'SUCCESS' });
});
Mark Bonano
źródło
9
To zadziałało dla mnie. Uwaga: Niestety, w niektórych samouczkach ludzie (jak ja) wyznaczają trasy przed app.configure (). W moim przypadku było to w postaci app.get / post itp., W tym także request ().
bendman
1
Bardzo dziękuję, rozwiązałem ten problem przez cały dzień.
jfplataroti
11
od express 4, app.use (app.router) jest usuwany. zobacz dokumentację github.com/visionmedia/express/wiki/New-features-in-4.x
Jonathan Ong
15
od wersji ekspresowej 4, oprogramowanie pośrednie, takie jak bodyParser, nie jest już dostarczane w pakiecie z Express i należy je instalować osobno. Więcej informacji można znaleźć tutaj: github.com/senchalabs/connect#middleware .
andrea.rinaldi
2
Dzięki. Ta odpowiedź ma ponad 2 lata i wciąż pomaga ludziom w tarapatach :)
Lorenzo Marcon
275

Najnowsze wersje Express (4.x) uwolniły oprogramowanie pośrednie od podstawowej struktury. Jeśli potrzebujesz parsera treści, musisz zainstalować go osobno

npm install body-parser --save

a następnie zrób to w swoim kodzie

var bodyParser = require('body-parser')
var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
Sójka
źródło
2
Niedawno zaktualizowałem do wyrażenia 4.x. Początkowo, gdy próbowałem zalogować się na żądanie, to pokazywało mnie niezdefiniowane. Kiedy już zainstaluję i użyję parsera body, daje mi oczekiwane wartości wymaganego ciała. :)
Alok Adhao
Przydało mi się to, gdy próbowałem dowiedzieć się, dlaczego moje żądania POST nie działają z serwerem json.
freethebees
Zapisałem mój dzień, zwłaszcza część „app.use (bodyParser.json ())”. Dzięki stary ! : D
neaGaze
To powinna być zaakceptowana odpowiedź, ponieważ działa ona całkowicie dla Express 4! Dziękuję Panu!
Połącz
2
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()) uratował mnie !!
Pramesh Bajracharya
71

Nie. Musisz użyć app.use(express.bodyParser())wcześniej app.use(app.router). W rzeczywistości app.use(app.router)powinna to być ostatnia rzecz, do której dzwonisz.

Danmactough
źródło
Nawet poruszanie się app.use(app.router)pod .userozmowami nie rozwiązuje problemu :(.
Masiar
Ok po odrobinie walki rozwiązałem go za pomocą app.use(require('connect').bodyParser());zamiast app.use(express.bodyParser());.
Masiar
tak, odpowiedź jest prawdziwa, nawet przy użyciu var router=express.Router();
Istiaque Ahmed,
1
Nieznaczny dodatek, powinieneś nadal wywoływać oprogramowanie pośredniczące do obsługi błędów po app.router
craft
Błogosław ten komentarz
Ke Ke
40

Najpierw upewnij się, że zainstalowałeś moduł npm o nazwie „body-parser”, wywołując:

npm install body-parser --save

Następnie upewnij się, że podałeś następujące linie, zanim zadzwonisz na trasy

var express = require('express');
var bodyParser = require('body-parser');
var app = express();

app.use(bodyParser.json());
Ankit kaushik
źródło
Jeśli korzysta z express.json, to po co importować body-parser?
SanSolo,
38

Express 4, ma wbudowany parser treści. Nie trzeba instalować osobnego parsera treści. Więc poniżej będzie działać:

export const app = express();
app.use(express.json());
TechTurtle
źródło
37

Nagłówek Content-Type w żądaniu jest naprawdę ważny, szczególnie gdy publikujesz dane z curl lub innych narzędzi.

Upewnij się, że używasz czegoś takiego jak application / x-www-form-urlencoded, application / json lub innych, to zależy od twoich danych postu. Pozostaw to pole puste, pomyli Express.

Kevin Xue
źródło
12
+1 To był dla mnie problem. Użyłem Postmana do Chrome, aby przetestować interfejs API JSON wbudowany w REST, ale obiekt otrzymany przez Express był pusty za każdym razem. Okazuje się, że Listonosz domyślnie nie dodaje automatycznie nagłówka „Content-Type: application / json”, nawet jeśli wybierzesz raw> json.
Jordan
@Jordan +1 Dziękujemy za zwrócenie na to uwagi. Rzeczywiście właśnie sprawdziłem nagłówki i widzę, że nadal jest ustawiony na „tekst / zwykły”, mimo że wybrałem „json”.
Inżynier
Ugh ... 7 lat później i to wciąż mnie
denerwuje
33

Jak już napisano pod jednym komentarzem, rozwiązałem go za pomocą

app.use(require('connect').bodyParser());

zamiast

app.use(express.bodyParser());

Nadal nie wiem, dlaczego to proste express.bodyParser()nie działa ...

Masiar
źródło
1
@Masiar To nie działa dla mnie. używam expressjs 4 i pojawia się taki błąd. Błąd: Nie można znaleźć modułu „połącz”
Jeyarathnem Jeyachanthuru
1
@ Kopalnia JeyTheva to dość stare rozwiązanie, dlatego w międzyczasie wszystko mogło się zmienić. Sugeruję, aby spróbować zainstalować connectmoduł przez npm install connecti spróbuj ponownie. To jedyna rzecz, o której mogę pomyśleć, czytając wyjście twojego błędu.
Masiar
4
Oto najnowsza dokumentacja dotycząca rozwiązania tego problemu: npmjs.com/package/body-parser Dla innych osób, które doświadczają tego problemu „post express 4”, działało dla mnie ustawienie Content-Typenagłówka na application/json.
Grant Eagon
3
Oto najnowsza dokumentacja dotycząca rozwiązania tego problemu: npmjs.com/package/body-parser Po zainstalowaniu parsera ciała nadal nie działał. Pracowałem nad ustawieniem Content-Typenagłówka, application/jsonkiedy robiłem moją prośbę.
Grant Eagon
1
application/jsonvs text/jsonw żądaniu działa, jak sugeruje @GrantEagon.
strider
21
// Require body-parser (to receive post data from clients)

var bodyParser = require('body-parser');

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

// parse application/json

app.use(bodyParser.json())
ASHISH RANJAN
źródło
20

Dodaj w swoim app.js

przed wywołaniem routera

const app = express();
app.use(express.json());
abdesselam
źródło
2
uratowałeś mi dzień! Kluczem jest dodanie linii przed routerem połączeń
ubaldisney
Ta rzecz mnie uratowała. Dzięki :)
Farrukh Faizy,
12

Wygląda na to, że parser body nie jest już wysyłany ekspresowo. Może być konieczne zainstalowanie go osobno.

var express    = require('express')
var bodyParser = require('body-parser')
var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!

Więcej informacji i przykładów można znaleźć na stronie git https://github.com/expressjs/body-parser .

Praneesh
źródło
1
Wygląda na to, że jest to nowy format Express 4.x i działał dla mnie. Funkcja express.bodyParser () wymieniona w innych odpowiedziach nie działa w wersji 4.x.
DustinB
10

Na wypadek, gdyby ktoś napotkał ten sam problem, który miałem; Używam przedrostka adresu URL jak

http://example.com/api/

który został skonfigurowany z routerem

app.use('/api', router); 

a potem miałem następujące

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

Tym, co naprawiło mój problem, było umieszczenie konfiguracji bodyparsera powyżej app.use('/api', router);

Finał

// setup bodyparser
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
    app.use('/api', router); 
Jeff Beagley
źródło
9

express.bodyParser () musi zostać poinformowany, jaki typ treści jest analizowany. Dlatego musisz upewnić się, że wykonując żądanie POST, dołączasz nagłówek „Content-Type”. W przeciwnym razie bodyParser może nie wiedzieć, co zrobić z treścią żądania POST.

Jeśli używasz curl do wykonania żądania POST zawierającego jakiś obiekt JSON w ciele, wyglądałoby to mniej więcej tak:

curl -X POST -H "Content-Type: application/json" -d @your_json_file http://localhost:xxxx/someRoute

Jeśli używasz innej metody, pamiętaj, aby ustawić to pole nagłówka za pomocą odpowiedniej konwencji.

ab107
źródło
8

Użyj app.use (bodyparser.json ()); przed routingiem. //. app.use („/ api”, trasy);

użytkownik1614168
źródło
7

Możesz spróbować dodać ten wiersz kodu u góry (po żądaniu instrukcji):

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

Jeśli chodzi o powody, dla których to działa, sprawdź dokumenty: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions

Anthony Cantellano
źródło
Twoja odpowiedź jest poprawna, ale nie różni się niczym od innych.
dwjohnston
7

Przez większość czasu wymaganie body jest niezdefiniowane z powodu braku parsera JSON

const express = require('express');
app.use(express.json());

może brakować parsera ciała

const bodyParser  = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

a czasem jest niezdefiniowany ze względu na pochodzenie krzyżowe, więc dodaj je

const cors = require('cors');
app.use(cors())
król neo
źródło
5

To zdarzyło mi się dzisiaj. Żadne z powyższych rozwiązań nie działa dla mnie. Ale trochę googlowania pomogło mi rozwiązać ten problem. Koduję do serwera zewnętrznego firmy Wechat.

Sprawy stają się nieco bardziej skomplikowane, gdy aplikacja node.js wymaga odczytu strumieniowych danych POST, takich jak żądanie klienta REST. W takim przypadku właściwość żądania „czytelny” zostanie ustawiona na wartość true, a dane POST muszą zostać odczytane we fragmentach, aby zebrać całą zawartość.

http://www.primaryobjects.com/CMS/Article144

spikeyang
źródło
w poście wspomniano o przesłaniu formularza HTML jako różnym od żądania klienta REST. czy oba żądania HTTP nie są? więc POST jest jedynym przypadkiem, który wymaga przesyłania strumieniowego?
j10
5

Zmarnowałem dużo czasu:

W zależności od Content-Type w Twoim kliencie życzenie serwer powinien mieć różne, jedną z poniżej app.use ():

app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))

Źródło: https://www.npmjs.com/package/body-parser#bodyparsertextoptions

Przykład:

Dla mnie po stronie klienta miałem poniższy nagłówek:

Content-Type: "text/xml"

Po stronie serwera użyłem:

app.use(bodyParser.text({type: 'text/xml'}));

Następnie wymagane jest, aby ktoś działał dobrze.

Manohar Reddy Poreddy
źródło
5

w Express 4 jest to naprawdę proste

const app = express()
const p = process.env.PORT || 8082

app.use(express.json()) 
Gerardo Bautista
źródło
4

Aby pracować, musisz app.use (app.router) po app.use (express.bodyParser ()) w następujący sposób :

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);
HenioJR
źródło
1
Twój komentarz i fragment kodu są sprzeczne. Najpierw trzeba powiedzieć, trzeba użyć app.usena app.routerprzed express.bodyParserale kod wyraźnie wskazuje, że po. Więc co to jest?
Levi Roberts,
1
Przepraszam stary. Musisz użyć app.router po express.bodyParser.
HenioJR
1
Dziękuję @LeviRoberts
HenioJR
4
var bodyParser = require('body-parser');
app.use(bodyParser.json());

To uratowało mi dzień.

isdot
źródło
4

Przyczyną tego problemu może być to, że nie użyłeś parsera ciała ( link )

var express = require('express');
var bodyParser  = require('body-parser');

var app = express();
app.use(bodyParser.json());
Arindam
źródło
3

Rozwiązałem to za pomocą:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});
Kkkk Kkkk
źródło
3

Jest to również jedna możliwość : upewnij się, że powinieneś napisać ten kod przed trasą w pliku app.js (lub index.js).

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Inamur Rahman
źródło
2

Możesz użyć ekspresowego parsera treści.

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
Kuldeep Mishra
źródło
2

Najnowsza wersja Express ma już wbudowany parser treści. Możesz więc użyć:

const express = require('express);
... 
app.use(express.urlencoded({ extended: false }))
.use(express.json());
LEMUEL ADANE
źródło
1

W przypadku opublikowania komunikatu SOAP należy użyć analizatora składni treści:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

app.use(bodyParser.raw({ type: 'text/xml' }));
opewix
źródło
1

Opierając się na @ kevin-xue powiedział, typ zawartości musi zostać zadeklarowany. W moim przypadku miało to miejsce tylko w IE9, ponieważ XDomainRequest nie ustawia typu zawartości , więc bodyparser i expressjs ignorowały treść żądania.

Obejrzałem to, ustawiając jawnie typ zawartości przed przekazaniem żądania do parsera treści, w następujący sposób:

app.use(function(req, res, next) {
    // IE9 doesn't set headers for cross-domain ajax requests
    if(typeof(req.headers['content-type']) === 'undefined'){
        req.headers['content-type'] = "application/json; charset=UTF-8";
    }
    next();
})
.use(bodyParser.json());
purpletonic
źródło
1

Kredyt dla @spikeyang za wielki odpowiedzi (podane poniżej). Po przeczytaniu sugerowanego artykułu dołączonego do postu postanowiłem podzielić się moim rozwiązaniem.

Kiedy użyć?

Rozwiązanie wymagało użycia routera ekspresowego, aby cieszyć się nim. Więc: Jeśli próbujesz użyć zaakceptowanej odpowiedzi bez powodzenia, po prostu użyj tej funkcji kopiuj i wklej:

function bodyParse(req, ready, fail) 
{
    var length = req.header('Content-Length');

    if (!req.readable) return fail('failed to read request');

    if (!length) return fail('request must include a valid `Content-Length` header');

    if (length > 1000) return fail('this request is too big'); // you can replace 1000 with any other value as desired

    var body = ''; // for large payloads - please use an array buffer (see note below)

    req.on('data', function (data) 
    {
        body += data; 
    });

    req.on('end', function () 
    {
        ready(body);
    });
}

i nazwij to tak:

bodyParse(req, function success(body)
{

}, function error(message)
{

});

UWAGA: W przypadku dużych ładunków - użyj bufora macierzy ( więcej @ MDN )

ymz
źródło
pakiet bodyParser jest powszechnie używany i tłumaczy ładunek na obiekt treści. jak podano w innych odpowiedziach
Schuere
1

Jeśli używasz jakiegoś zewnętrznego narzędzia do wysłania żądania, pamiętaj o dodaniu nagłówka:

Content-Type: application/json

Inc33
źródło
Ten pomógł mi, pracowałem z Listonoszem, dzięki kolego.
R. Gurung