требуется пустое сообщение

257

Внезапно это произошло со всеми моими проектами.

Всякий раз, когда я делаю пост в nodejs, используя express и body-parser 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);
});

Через аякс и почтальона всегда пусто.

Однако через локон

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

это работает как задумано.

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

Это сводит меня с ума.

Я думал, что это было что-то обновлено в body-parser, но я понизил, и это не помогло.

Любая помощь приветствуется, спасибо.

Джозеф Дейли
источник
16
Так вы пробовали явно задавать Content-Typeв почтальоне? Если нет, вы можете попробовать это, так как у меня были проблемы с почтальоном, не отправляющим Content-Type.
mscdex
Да, я сделал. вот когда я получил 400: недействительный JSON
Джозеф Дейли
@mscdex - спасибо, я не установил content-tupe в почтальоне и сходил с ума :)
Muzafar Ali
Для тех людей, которые приходят сюда, потому что они хотят отправлять / выгружать файлы из своих API и, следовательно, должны использовать данные формы. Вам нужно что-то для обработки данных формы: npmjs.com/package/multer - довольно популярный пакет.
Бхаскар
Несмотря ни на что, почтальон не очень хорошо работает с целыми числами и значениями с плавающей точкой. Если у вас есть целочисленные значения или значения с плавающей запятой, убедитесь, что все, и ключи, и значения
заключены

Ответы:

272

В Почтальоне из 3 вариантов, доступных для типа контента, выберите «X-www-form-urlencoded», и он должен работать.

Также, чтобы избавиться от сообщения об ошибке, замените:

app.use(bodyParser.urlencoded())

С участием:

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

Смотрите https://github.com/expressjs/body-parser

Промежуточное программное обеспечение body-parser обрабатывает только данные в формате JSON и urlencoded, а не multipart

Мик Каллен
источник
Это работало на почтальона, я не уверен, почему это работает с ajax, поскольку я ничего не менял.
Джозеф Дейли
По какой-то причине http-сообщения через Angular не нужно кодировать URL-адресом, а ajax-вызовы. Кто-нибудь знает почему?
youngrrrr
Это сработало для меня, почему не работало с raw-кодировкой?
Даниэль Кобе
9
теперь body-parser app.use(express.json());
встроен в express.js,
Спасибо вам большое! Несмотря на то, что на это давно ответили, это все еще актуально.
Spray'n'Pray
218

С помощью 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 полезной нагрузки

sirthud
источник
О, боже, как я пропустил, что я вставил литерал объекта JS, а не правильно отформатированный объект JSON ...: -S ... спасибо, друг!
Уэс Джонсон
Оборачивать любые строки, используемые в качестве ключей / значений в двойные кавычки ... Легко пропустить, но в целом это нарушает условия сделки! Спасибо.
loxyboi
Хорошее использование скриншотов.
Ксан-Кун, Кларк-Дэвис,
Когда я использую form-dataPostman для публикации данных, я всегда получаю {}в 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
Bam. Это была проблема. Спасибо!
Мэтт Уэст
Это была именно моя проблема, ввод формы без значений имени, потраченные часы, пытаясь понять это. Спасибо.
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
Я не могу понять, как удалить заголовки по умолчанию в расширении "Почтальон Chrome" ... Возможно, вы используете приложение?
WestleyArgentum
О, я установил приложение, и оно работает намного лучше, чем расширение. Извините за шум.
WestleyArgentum
12

Вы должны проверить, правильно ли установлено промежуточное ПО body-parser для типа запроса (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

благодаря структуре приложения, копированию и вставке проекта из примеров.

Как только я исправил порядок регистрации промежуточного программного обеспечения перед маршрутом, все заработало.

указ
источник
спасибо Fiat, с правильным порядком и использованием сырых вкладок, это наконец-то сработало для меня
Alex
4

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

Shaggie
источник
да, это также сработало, чтобы получить тело формы, но затем вызвало еще одну проблему с моей формой - в основном файл не мог быть загружен, как это требуетсяenctype="multipart/form-data"
tsando
Кстати, просто чтобы добавить мой комментарий выше, мне удалось заставить это работать 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)
});
tsando
источник
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». Я видел случаи, когда простое использование «post» приводило к пустому req.body.
Мэтт С.
1

Если вы делаете с почтальоном, пожалуйста, подтвердите эти вещи, когда вы запрашиваете API

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

Вигнеш
источник
0

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

server.use(restify.bodyParser());
Prabhat
источник
0

Я верю, что это может решить app.use(express.json());

Клебер Карвалью
источник
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())и это сработало ...

musiquarc
источник
0

В почтальоне даже после получения принятого ответа я получал пустое тело запроса. Проблема оказалась не передавая заголовок под названием

Content-Length : <calculated when request is sent>

Этот заголовок присутствовал по умолчанию (вместе с 5 другими), который я отключил. Включите это, и вы получите тело запроса.

kaushalpranav
источник
0

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

Тушар Кудал
источник
0

Уже решил проблему, но может кому-то помочь.

Следите за тем, чтобы с каждым вашим элементом формы было связано какое-то имя. Это была ошибка, которую я делал ...!

Солнечно
источник