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?

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

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

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.


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

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

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.


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


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

20

Dodaj w swoim app.js

przed wywołaniem routera

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

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 .


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

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.




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

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


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.


5

w Express 4 jest to naprawdę proste

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

app.use(express.json()) 

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

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


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

3

Rozwiązałem to za pomocą:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});

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

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

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

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

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

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 )


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


Ten pomógł mi, pracowałem z Listonoszem, dzięki kolego.
R. Gurung

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.