Как получить доступ к телу запроса при POSTing с использованием Node.js и Express?

175

У меня есть следующий код Node.js:

var express = require('express');
var app = express.createServer(express.logger());
app.use(express.bodyParser());

app.post('/', function(request, response) {
    response.write(request.body.user);
    response.end();
});

Теперь, если я отправлю что-то вроде:

curl -d user=Someone -H Accept:application/json --url http://localhost:5000

Я получаю, Someoneкак ожидалось. А что если я хочу получить полное тело запроса? Я попытался сделать, response.write(request.body)но Node.js выдает исключение, говорящее « первый аргумент должен быть строкой или буфером », затем переходит в «бесконечный цикл» с исключением, которое говорит: « Невозможно установить заголовки после их отправки. »; это также верно, даже если бы я var reqBody = request.body;и тогда писал response.write(reqBody).

В чем здесь проблема?

Кроме того, я могу просто получить необработанный запрос без использования express.bodyParser()?

TheBlueSky
источник
Кажется, есть что-то с response.write(reqBody); когда я использую response.send(reqBody)вещи работают нормально ... и да, я использую response.endпосле response.write.
TheBlueSky

Ответы:

161

Экспресс 4.0 и выше:

$ npm install --save body-parser

И тогда в вашем приложении узла:

const bodyParser = require('body-parser');
app.use(bodyParser);

Экспресс 3.0 и ниже:

Попробуйте передать это в вашем вызове cURL:

--header "Content-Type: application/json"

и убедитесь, что ваши данные в формате JSON:

{"user":"someone"}

Также вы можете использовать console.dir в вашем коде node.js, чтобы увидеть данные внутри объекта, как в следующем примере:

var express = require('express');
var app = express.createServer();

app.use(express.bodyParser());

app.post('/', function(req, res){
    console.dir(req.body);
    res.send("test");
}); 

app.listen(3000);

Этот другой вопрос также может помочь: Как получить JSON в экспресс-запросе node.js POST?

Если вы не хотите использовать bodyParser, проверьте этот другой вопрос: https://stackoverflow.com/a/9920700/446681

Гектор Корреа
источник
Я пытался использовать, curl -d {"user":"Someone"} -H "Content-Type: application/json" --url http://localhost:5000но он выдавал мне ошибку " Неожиданный токен u ", поэтому я переключился на упомянутый вызов в своем исходном сообщении.
TheBlueSky
Я
отмечаю
40
express.bodyParser()не рекомендуется в Express 4.x. Вместо этого используйте npmjs.org/package/body-parser .
Люк
@TheBlueSky причина, по которой вы получили «Неожиданный токен», заключалась в том, что оболочка потребляла ваши двойные кавычки. То же самое происходит, если вы делаете echo any"thing". Данные, которые вы публикуете, должны быть в кавычках, чтобы этого не происходило.
Том Фенек
11
Начиная с версии 4.16.0 или выше, можно использовать express.json () в app.use () следующим образом => app.use (express.json ());
Митро
187

Начиная с Express v4.16 нет необходимости в дополнительных модулях, просто используйте встроенное промежуточное ПО JSON :

app.use(express.json())

Как это:

const express = require('express')

app.use(express.json())    // <==== parse request body as JSON

app.listen(8080)

app.post('/test', (req, res) => {
  res.json({requestBody: req.body})  // <==== req.body will be a parsed JSON object
})

Примечание - body-parserот которого это зависит, уже включено в экспресс.

Также не забудьте прислать шапку Content-Type: application/json

rustyx
источник
14
Спасибо, тогда это лучший ответ для 4.16+. Никаких других зависимостей и работает как шарм!
Codepleb
1
Лучшее / единственное решение, которое я смог найти, которое не нуждается в парсере тела
Mote
41

Начиная с Express 4, следующий код, кажется, делает свое дело. Обратите внимание, что вам нужно установить body-parserс помощью npm.

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


app.listen(8888);

app.post('/update', function(req, res) {
    console.log(req.body); // the posted data
});
Уолтер Роман
источник
29
Для разбора тел json необходимо добавить следующую строкуapp.use(bodyParser.json())
Camilo Silva
1
@ cml.co есть ли какая-либо причина app.use(bodyParser.urlencoded({ extended: true }), также требуется? Я размещаю довольно сложный документ как JSON в запросе, и extended: falseон не работает. Только когда я установил значение true, запрос будет правильно проанализирован.
Веб-пользователь
3
Просто записка. Пришлось использовать app.use(bodyParser.urlencoded({ extended: true }));AND app.use(bodyParser.json())для получения данных json на сервере AWS Linux с NodeJS и Express.
Дэвид
24
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())

var port = 9000;

app.post('/post/data', function(req, res) {
    console.log('receiving data...');
    console.log('body is ',req.body);
    res.send(req.body);
});

// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);

Это поможет вам. Я полагаю, вы отправляете тело в JSON.

Гаутама
источник
Я всегда забываю добавить bodyParser.json () bit x_x спасибо!
Джонни Асмар
14

Для 2019 года вам не нужно устанавливать body-parser.

Ты можешь использовать:

var express = require('express');
var app = express();
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.listen(8888);
app.post('/update', function(req, res) {
    console.log(req.body); // the posted data
});
Шивам Гупта
источник
8

Это может быть достигнуто без body-parserзависимости , а также, слушать request:dataи request:endи возвращать ответ на конец запроса см ниже примере кода. ссылка: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/#request-body

var express = require('express');
var app = express.createServer(express.logger());

app.post('/', function(request, response) {

    // push the data to body
    var body = [];
    request.on('data', (chunk) => {
      body.push(chunk);
    }).on('end', () => {
      // on end of data, perform necessary action
      body = Buffer.concat(body).toString();
      response.write(request.body.user);
      response.end();
    });
});
Manivannan
источник
3

Попробуй это:

response.write(JSON.stringify(request.body));

Это возьмет bodyParserсозданный для вас объект, превратит его обратно в строку и запишет в ответ. Если вы хотите , точное тело запроса (с тем же пробелом, и т.д.), вы будете нуждаться , dataи endслушатели прилагается к запросу до и создать строковый кусок на кусок , как вы можете видеть в JSON источника синтаксического анализа кода от подключения .

Питер Лайонс
источник
1

Вы утверждаете, что «пытались делать» именно то, что написали в коде, который работает «как положено», когда вы вызываете его с помощью curl.

Ошибка, которую вы получаете, похоже, не связана с каким-либо кодом, который вы нам показали.

Если вы хотите , чтобы получить сырье запроса, установить обработчик на requestдля dataи endсобытий (и, конечно, удалить инвокации express.bodyParser()). Обратите внимание, что dataсобытия будут происходить в чанках, и если вы не установите кодировку для dataсобытия, эти чанки будут буферами, а не строками.

ebohlman
источник
это была ошибка копирования-вставки; Я имел ввиду request.bodyи нет request.body.user, и я исправил это сейчас. Кстати, это var reqBody = request.body;было и остается правильным, и когда вы попробуете это, вы получите ошибку, которую я получаю. В любом случае, не могли бы вы привести пример установки обработчика request; Я не нахожу это в экспресс-руководстве.
TheBlueSky
1

Если вы достаточно ленивы, чтобы читать куски данных поста. Вы можете просто вставить строки ниже, чтобы прочитать JSON.

Ниже для TypeScript подобное можно сделать и для JS.

app.ts

 import bodyParser from "body-parser";
 // support application/json type post data
 this.app.use(bodyParser.json());
 // support application/x-www-form-urlencoded post data
 this.app.use(bodyParser.urlencoded({ extended: false }));

В любом вашем контроллере, который получает вызов POST, используйте, как показано ниже

userController.ts

 public async POSTUser(_req: Request, _res: Response) {
   try {
          const onRecord = <UserModel>_req.body;
           /* Your business logic */
           _res.status(201).send("User Created");
        }
    else{
           _res.status(500).send("Server error");
           }        
   };

_req.body должен анализировать данные JSON в вашей модели TS.

Шуджаат Хан
источник
1
Я не уверен, пытаетесь ли вы поощрять или отговаривать людей использовать ваш ответ, называя их ленивыми :)
TheBlueSky
1

Я абсолютно новичок в JS и ES, но мне кажется, что это работает так:

JSON.stringify(req.body)

Дайте мне знать, если что-то не так с этим!

balintn
источник
именно то, что мне было нужно
Джозеф Хенн
0

Установите парсер тела командой ниже

$ npm install --save body-parser

Настройте парсер тела

const bodyParser = require('body-parser');
app.use(bodyParser);
app.use(bodyParser.json()); //Make sure u have added this line
app.use(bodyParser.urlencoded({ extended: false }));
Арун Абиманью
источник
-3

Вы используете следующий код для регистрации данных поста:

router.post("/users",function(req,res){
    res.send(JSON.stringify(req.body, null, 4));
});
Чандра Кумар
источник
2
Данный ответ является неполным без включения модуля body-parser.
Грамча