Express.js req.body невизначений


292

У мене це конфігурація мого сервера 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());

Але все ж, коли я прошу req.body.somethingв своїх маршрутах, я отримую деяку помилку, яка вказує на це body is undefined. Ось приклад маршруту, який використовує req.body:

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

Я читав, що ця проблема викликана відсутністю, app.use(express.bodyParser());але, як ви бачите, я називаю її перед маршрутами.

Якась підказка?

Відповіді:


296

Ви повинні переконатися, що ви визначили всі конфігурації перед тим, як визначити маршрути. Якщо ви це зробите, можете продовжувати користуватися express.bodyParser().

Приклад такий:

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
Це працювало для мене. Примітка. На жаль, у деяких навчальних посібниках там люди (як я) ставлять маршрути перед app.configure (). У моєму випадку це було у формі app.get / post тощо, і вимагати (), включаючи їх.
Бендман

1
Дякую, я цілий день вирішував цю проблему.
jfplataroti

11
станом на експрес 4, app.use (app.router) видаляється. перегляньте документи github.com/visionmedia/express/wiki/New-features-in-4.x
Джонатан Онг

15
станом на експрес 4, середні програми, такі як bodyParser, більше не постачаються в пакеті Express і повинні встановлюватися окремо. Додаткову інформацію можна знайти тут: github.com/senchalabs/connect#middleware .
andrea.rinaldi

2
Дякую. Цій відповіді більше 2 років і досі продовжують допомагати людям у біді :)
Лоренцо Маркон

275

Останні версії Express (4.x) відокремили проміжне програмне забезпечення від основної бази. Якщо вам потрібен аналізатор тіла, вам потрібно встановити його окремо

npm install body-parser --save

а потім зробіть це у своєму коді

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
Я нещодавно оновив, щоб виразити 4.x. Спочатку, коли я намагався зареєструвати req.body, це показувало мене невизначеним. Після того, як я встановив і використав тест-аналізатор, він дає мені очікувані значення req.body. :)
Alok Adhao

Я вважаю це корисним при спробі з’ясувати, чому мої POST-запити не працюють з json-сервером.
freethebees

Врятував мій день, особливо частину "app.use (bodyParser.json ())". Дякую брате! : D
neaGaze

Це має бути прийнятою відповіддю, оскільки це повністю працює для Express 4! Дякую вам сер!
Поєднайте

2
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()) врятував мене !!
Прамеш Байрачаря

71

Ні. Вам потрібно скористатися app.use(express.bodyParser())раніше app.use(app.router). Насправді, це app.use(app.router)повинно бути останнє, що ви телефонуєте.


Навіть переїзд app.use(app.router)під .useдзвінками не вирішує питання :(.
Масіар

Ок після трохи зусиль я вирішив це, використовуючи app.use(require('connect').bodyParser());замість app.use(express.bodyParser());.
Масіар

так, відповідь вірна навіть при використанні var router=express.Router();
Істіаке Ахмед

1
Невеликий додаток, ви все ще повинні зателефонувати з проміжним програмним забезпеченням помилок після app.router
крафт

БЛАГИЙ ЦЕ КОМЕНТАР
Ke Ke

40

Спочатку переконайтесь, що ви встановили модуль npm під назвою 'body-parser', зателефонувавши:

npm install body-parser --save

Потім переконайтеся, що ви включили наступні рядки перед тим, як викликати маршрути

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

app.use(bodyParser.json());

Якщо він використовує express.json, то навіщо імпортувати тіло-парсер?
SanSolo

38

Експрес 4, має вбудований аналізатор тіла Не потрібно встановлювати окремий аналізатор тіла Отже нижче буде працювати:

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

37

Тип вмісту в заголовку запиту дійсно важливий, особливо коли ви публікуєте дані з curl або будь-яких інших інструментів.

Переконайтеся, що ви використовуєте якусь річ, наприклад application / x-www-form-urlencoded, application / json або інші, це залежить від ваших даних публікації. Залиште це поле порожнім, переплутайте Експрес.


12
+1 Ця проблема була для мене. Я використовував Postman для Chrome для тестування JSON-api, вбудованого в REST, але об'єкт, отриманий Express, кожного разу порожній. Виявляється, Postman за замовчуванням не додає автоматично заголовок "Content-Type: application / json", навіть якщо ви вибрали raw> json.
Йорданія

@Jordan +1 Дякуємо, що вказали на це. Дійсно, я просто перевірив свої заголовки, і я бачу, що він все ще встановлений на "text / plain", хоча я вибрав "json".
Інженер

Тьфу ... Через 7 років, і це все ще мене
підштовхує

33

Як уже було розміщено під одним коментарем, я вирішив це за допомогою

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

замість

app.use(express.bodyParser());

Я досі не знаю, чому просто express.bodyParser()не працює ...


1
@Masiar Це не працює для мене. Я використовую expressjs 4 і я отримую помилку, як це. Помилка: не вдалося знайти модуль 'connect'
Jeyarathnem Jeyachanthuru

1
@JeyTheva шахта є досить старим рішенням, тому в середньому все може змінитися. Я пропоную вам спробувати встановити connectмодуль через npm install connectта повторити спробу. Це єдине, що я можу придумати, читаючи висновок вашої помилки.
Масіар

4
Ось остання документація щодо вирішення цього питання: npmjs.com/package/body-parser Для інших, хто відчуває цю проблему "пост експрес 4", те, що для мене працювало, було встановити Content-Typeзаголовок application/json.
Грант Егон

3
Ось остання документація щодо вирішення цього питання: npmjs.com/package/body-parser Після встановлення аналізатора тіла він все ще не працював. Що робив, це налаштування Content-Typeзаголовка, application/jsonколи я робив моє прохання.
Грант Егон

1
application/jsonvs text/jsonу запиті працює, як запропонував @GrantEagon.
стридер

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

Додайте у свій app.js

до виклику Маршрутизатора

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

2
ти врятував мій день людини! Ключ - додавання рядка перед маршрутизатором виклику
ubaldisney

Ця річ врятувала мене. Дякуємо :)
Farrukh Faizy

12

Схоже, аналізатор тіла більше не постачається з експресом. Можливо, доведеться встановити його окремо.

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!

Докладнішу інформацію та приклади див. На сторінці git https://github.com/expressjs/body-parser .


1
Схоже, це новий формат Express 4.x і працював для мене. Express.bodyParser (), згаданий в інших відповідях, не працює в 4.x.
ДастінБ

10

У випадку, якщо хтось зіткнеться з тією ж проблемою, що у мене був; Я використовую префікс на зразок URL

http://example.com/api/

яка була налаштована за допомогою маршрутизатора

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

і тоді у мене було таке

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

Що вирішило мою проблему - розміщення конфігурації bodyparser вище app.use('/api', router);

Фінал

// 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 () потрібно повідомити, який саме тип вмісту він аналізує. Тому вам потрібно переконатися, що під час виконання запиту POST, ви включаєте заголовок "Тип вмісту". В іншому випадку bodyParser може не знати, що робити з тілом вашого запиту POST.

Якщо ви використовуєте curl для виконання POST-запиту, що містить деякий об'єкт JSON в тілі, це буде виглядати приблизно так:

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

Якщо ви використовуєте інший метод, просто не забудьте встановити це поле заголовка, використовуючи будь-яку умову.



7

Ви можете спробувати додати цей рядок коду вгорі (після необхідних заяв):

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

Щодо причин того, чому це працює, ознайомтесь із документами: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions


Я маю на увазі, ваша відповідь правильна, але вона не відрізняється від інших.
dwjohnston

7

Більшу частину часу req.body не визначено через відсутній аналізатор JSON

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

може бути відсутнім для аналізатора тіла

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

а іноді це не визначено через походження крос, тому додайте їх

const cors = require('cors');
app.use(cors())

5

Це сталося зі мною сьогодні. Жодне з перерахованих вище рішень для мене не працює. Але трохи гугл допоміг мені вирішити це питання. Я кодую сервер сторонніх сторін wechat.

Все стає дещо складнішим, коли ваша програма node.js вимагає зчитування потокових даних POST, наприклад запиту клієнта REST. У цьому випадку властивість запиту "читабельна" буде встановлена ​​в істину, а дані POST повинні бути прочитані фрагментами, щоб зібрати весь вміст.

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


публікація зазначає подання форми HTML, відмінну від запиту клієнта REST. не обидва запити http? Отже, POST - єдиний випадок, який вимагає потокової передачі?
j10

5

Витратили багато часу:

В залежності від Content-Type в вашому клієнтському запиті сервер повинен мати різні, один з нижче 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' }))

Джерело: https://www.npmjs.com/package/body-parser#bodyparsertextoptions

Приклад:

Для мене на стороні клієнта внизу був заголовок:

Content-Type: "text/xml"

Отже, на стороні сервера я використовував:

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

Тоді req.body працював чудово.



4

Для роботи вам потрібно застосувати app.use (app.router) після app.use (express.bodyParser ()) , наприклад:

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);

1
Ваш коментар та фрагмент коду суперечливі. Спочатку ви говорите , що ви повинні використовувати app.useна app.routerперед тим, express.bodyParserале ваш код явно вказує на те, що це після того, як . Так що це?
Леві Робертс

1
Вибач людина. Вам потрібно використовувати app.router після express.bodyParser.
HenioJR

1
Дякую @LeviRoberts
HenioJR

4
var bodyParser = require('body-parser');
app.use(bodyParser.json());

Це врятувало мені день.


4

Ця проблема може бути через те, що ви не використовуєте аналізатор тіла ( посилання )

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

var app = express();
app.use(bodyParser.json());

3

Я вирішив це за допомогою:

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

3

Це також одна можливість : переконайтеся, що ви повинні написати цей код перед маршрутом у вашому файлі app.js (або index.js).

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

2

Можна використовувати експрес-аналізатор тіла.

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

2

В останній версії Express вже вбудований аналізатор тіла. Отже, ви можете використовувати:

const express = require('express);
... 
app.use(express.urlencoded({ extended: false }))
.use(express.json());

1

Якщо ви розміщуєте SOAP-повідомлення, вам потрібно використовувати сирий аналізатор тіла:

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

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

1

На основі @ kevin-xue сказав, що тип контенту потрібно оголосити. У моєму випадку це траплялося лише з IE9, оскільки XDomainRequest не встановлює тип вмісту , тому bodyparser та expressjs ігнорували тіло запиту.

Я обійшов це, встановивши тип вмісту явно перед тим, як передати запит до парсера тіла, наприклад:

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

Кредит @spikeyang за великий відповідь (наводиться нижче). Прочитавши запропоновану статтю до публікації, я вирішив поділитися своїм рішенням.

Коли користуватися?

Рішення вимагало використовувати експрес-роутер, щоб насолоджуватися ним. Отже: Якщо ви намагалися невдало використовувати прийняту відповідь, просто скопіюйте та вставте цю функцію:

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

і називати це так:

bodyParse(req, function success(body)
{

}, function error(message)
{

});

ПРИМІТКА. Для великих корисних навантажень - будь ласка, використовуйте буфер масиву ( докладніше @ MDN )


пакет bodyParser зазвичай використовується і переводить корисне навантаження в об'єкт body. як це передбачено в інших відповідях
Шуер

1

Якщо ви використовуєте якийсь зовнішній інструмент для оформлення запиту, обов'язково додайте заголовок:

Content-Type: application/json


Цей мені допоміг, я працював з листоношею, дякую приятелю.
Р. Гурунг

1

Для тих, у кого жоден з вищезазначених відповідей не працював, я повинен був включити між собою між собою і експресом.

Ви можете це зробити:

  1. Завантаження та ввімкнення розширення CORS для вашого браузера, наприклад:

    https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=uk

    для Chrome,

або за

  1. Додавання рядків

    var cors=require('cors');
    
    app.use(cors());

на вашу експрес- app.jsсторінку. (Після npm install cors)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.