req.body пусті на дописи


255

Раптом це сталося з усіма моїми проектами.

Щоразу, коли я створю повідомлення в nodejs, використовуючи експрес та тест-парсер req.body, це порожній об'єкт.

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

Через ajax та листоноші він завжди порожній.

Однак за допомогою завивки

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

він працює за призначенням.

Я намагався налаштувати вручну Content-type : application/jsonв колишньому, але потім завжди отримую400 bad request

Це зводило мене з розуму.

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

Будь-яка допомога вдячна, дякую.


16
Отже, ви намагалися явно встановити Content-Typeв листоноші? Якщо ні, то ви можете спробувати це, оскільки у мене були проблеми з тим, що листонош не надсилав Content-Type.
mscdex

так. саме тоді я отримав 400: недійсний json
Джозеф Дейлі

@mscdex - дякую, що я не встановив контент-туп у листоноші і
зліз з

Для тих людей, які приїжджають сюди, тому що хочуть надсилати / завантажувати файли зі своїх API, і тому вони повинні використовувати форми-дані. Вам потрібно щось для обробки даних форми: npmjs.com/package/multer - досить популярний пакет.
бхаскар

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

Відповіді:


272

У Postman з 3 варіантів, доступних для типу вмісту, виберіть "X-www-form-urlencoded", і він повинен працювати.

Також щоб позбутися заміни повідомлення про помилку:

app.use(bodyParser.urlencoded())

З:

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

Дивіться https://github.com/expressjs/body-parser

Проміжне програмне забезпечення "тіло-аналізатор" обробляє лише JSON та дані, кодовані урленом, а не багаточастинні


Це працювало для листоноші, я не впевнений, чому це працює з ajax, оскільки я нічого не змінив.
Джозеф Дейлі

Чомусь повідомлення в http через Angular не потрібно було кодувати URL-адресами, але дзвінки Ajax робили. Хтось знає, чому?
youngrrrr

Це працювало для мене, чому ж не було роботи з сировинним кодуванням?
Даніель Кобе

9
тепер body-parser вбудований у express.js просто використовуйтеapp.use(express.json());
Sujeet Agrahari

Дуже дякую! Незважаючи на довгий час відповіді на це, він все ще актуальний.
Spray'n'Pray

217

З Postman, щоб перевірити дії HTTP-публікації з необробленою навантаженням даних JSON, виберіть rawпараметр і встановіть такі параметри заголовка:

Content-Type: application/json

Також обов'язково загортайте будь-які рядки, які використовуються як ключі / значення у вашому навантаженні JSON, подвійними лапками.

У body-parserпакеті буде проаналізовано багаторядкові сирі навантаження JSON.

{
    "foo": "bar"
}

Тестовано в Chrome v37 та v41 з розширенням Postman v0.8.4.13 ( body-parserv1.12.2 та expressv4.12.3) із налаштуваннями нижче:

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

Коричне навантаження пошти json


О людино, як я пропустив, що я вставив об'єкт JS буквально, а не правильно відформатований об'єкт JSON ...: -S ... дякую друже!
Уес Джонсон

Встановлення будь-яких рядків, що використовуються як ключ / значення, у подвійних лапках ... Легко пропустити, але інакше загальний вимикач угод! Дякую.
loxyboi

Гарне використання скріншотів.
Ксан-Кун Кларк-Девіс

Коли я використовую form-dataу Postman для розміщення даних, я завжди отримую {}теки у req.body. Чи варто встановити Content-Typeваріант?
мінчау

56

Я зробив дійсно тупу помилку і забув визначити nameатрибути для входів у своєму HTML-файлі.

Тож замість

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

У мене це є.

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

Зараз request.bodyзаселено так:{ password: 'hhiiii' }


1
Бам. У цьому і була проблема. Дякую!
Метт Вест

Це була саме моя проблема: введення форми без значень імен витрачало години, намагаючись розібратися в цьому. Дякую.
karensantana

37

Я виявив, що він працює при надсиланні з типом вмісту

"додаток / json"

у поєднанні з сервером

app.use(bodyParser.json());

Тепер я можу відправити через

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

і результат доступний request.body.nameна сервері.


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

це відповідь!
Гель

У моєму випадку мені довелося змінити це наxmlHttp.send(JSON.stringify(data));
endo64

18

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

Я дотримувався підручника BeerLocker тут: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/


2
у мене було те саме питання. маючи заголовок "не відмічено" (і пропав сірим кольором) було недостатньо, мені довелося повністю його видалити. незважаючи на те, що кнопка джерела "</>" показує, що я не надсилав цей заголовок, коли тип вмісту перебуває в неперевіреному стані, його все одно потрібно було повністю видалити.
theRemix

Я не можу зрозуміти, як видалити заголовки за замовчуванням у розширенні хроністи листоноші ... Ви, можливо, використовуєте додаток?
WestleyArgentum

О, я встановив додаток, і він працює набагато краще, ніж розширення. Вибачте за шум.
WestleyArgentum

12

Ви повинні перевірити, чи встановлено проміжне програмне забезпечення для аналізатора тіл відповідно до типу запиту (json, urlencoded).

Якщо ви встановили,

app.use(bodyParser.json());

то в листоноші вам доведеться надсилати дані як необроблені.

https://i.stack.imgur.com/k9IdQ.png скріншот листоноші

Якщо ви встановили,

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

тоді слід вибрати опцію 'x-www-form-urlencoded'.


а як мати їх обох? (bodyParser.urlencoded та bodyParser.json ()) ... який я можу використовувати у листоноші?
TommyLeong

9

Моя проблема полягала в тому, що я створив маршрут спочатку

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

та реєстрація проміжного програмного забезпечення після маршруту

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

завдяки структурі додатків та копіюванню та склеюванню проекту разом із прикладів.

Після того, як я зафіксував замовлення на реєстрацію проміжного програмного забезпечення перед маршрутом, все працювало.


спасибі фіат, з правильним замовленням та використанням сирого вкладки він працював нарешті для мене
Олексій

4

Навіть коли я вперше вчився node.js, коли я почав його вивчати через веб-додаток, я все це робив добре в моїй формі, я все ще не міг отримувати значення в запиті після публікації. Після тривалої налагодження я дізнався, що в тому вигляді, який я надав, enctype="multipart/form-data"завдяки якому я не зміг отримати значення. Я просто її зняв, і це працювало на мене.


так, це також працювало, щоб отримати тіло форми, але потім спричинило ще одну проблему з моєю формою - в основному файл не вдалося завантажити, як цього потрібноenctype="multipart/form-data"
tsando,

btw, лише щоб додати до мого вище коментаря, мені вдалося налагодити цю роботу multer- дивіться документацію на npmjs.com/package/multer
tsando

3

Здається, якщо ви не використовуєте жоден encType (типовим є application/x-www-form-urlencoded), ви отримуєте поля для введення тексту, але ви не отримаєте файл.

Якщо у вас є форма, де ви хочете розмістити текст і файл, тоді використовуйте multipart/form-dataтип кодування, а на додаток до цього використовуйте multerпроміжне програмне забезпечення. Multer проаналізує об’єкт запиту та підготує req.fileдля вас, і всі інші вхідні поля будуть доступні через req.body.


1
дякую - multerсправді було вирішенням моєї проблеми. Було б добре, якщо ви можете додати приклад того, як це використовувати як частину вашої відповіді
tsando,

2

Подібна проблема трапилася і зі мною, я просто змішав порядок парами зворотного виклику. Переконайтесь, що ви налаштовуєте функції зворотного дзвінка у правильному порядку. Принаймні для тих, хто має таку ж проблему.

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

2

Переконайтесь, що ["key": "type", "value": "json"] & ["key": "Content-Type", "value": "application / x-www-form-urlencoded"] є у вашому заголовки запиту листоноші


2

Я вирішив це, multerяк було запропоновано вище, але вони пропустили повний робочий приклад, як це зробити. В основному це може статися, коли у вас є група форм enctype="multipart/form-data". Ось HTML для форми, яку я мав:

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

Ось як можна multerотримати значення та назви цієї форми за допомогою Express.jsта 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

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

Єдине, що я зробив - це оновлення версії Node JS, я не знав, що оновлення може чимось вплинути, але це зробило.

Я встановив версію Node JS 10.15.0(остання версія), я повернувся до 8.11.3і все зараз працює. Можливо, body-parserмодуль повинен виправити це.


1

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

Відповідь, яку я використав Джейсон Кім:

Тож замість

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

У мене це є

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

1

вам не слід робити це JSON.stringify(data)під час надсилання через AJAX, як показано нижче.

Це НЕ правильний код:

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

Правильний код:

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

Ключова річ, яку тут слід зазначити, - це те, що типово переконайтесь, що ви використовуєте великі літери "POST". Я бачив випадки, коли саме використання "поста" призвело до порожнього req.body.
Метт К.

1

Якщо ви працюєте з листоношею, підтвердьте ці матеріали, коли ви запитуєте API

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


0

Я використовував restify замість express і зіткнувся з тією ж проблемою. Рішення було зробити:

server.use(restify.bodyParser());


0

Змініть app.use(bodyParser.urlencoded());свій код на

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

і в листоноші, у Content-Typeзначенні зміни заголовка з application/x-www-form-urlencodedнаapplication/json

Та :-)


0

Дякую всім за чудові відповіді! Довгий час я шукав рішення, і на моєму боці я робив елементарну помилку: мені дзвонив bodyParser.json()зсередини функції:

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

Мені просто потрібно було це зробити, app.use(['/password'], bodyParser.json())і це спрацювало ...


0

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

Content-Length : <calculated when request is sent>

Цей заголовок був за замовчуванням (разом із 5 іншими), який я відключив. Увімкніть це, і ви отримаєте орган запиту.


0

Моя проблема полягала в створенні маршруту спочатку, require("./routes/routes")(app); я перемістив його до кінця коду раніше, app.listen і він працював!

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