Expressjs сырое тело

Как я могу получить доступ к сырому телу объекта запроса, переданного мне expressjs?

var express = require('./node_modules/express');
var app = express.createServer();
app.post('/', function(req, res)
{
    console.log(req.body); //says 'undefined'
});
app.listen(80);

12 ответов

Решение

По умолчанию express не буферизует данные, пока вы не добавите промежуточное программное обеспечение для этого. Простое решение состоит в том, чтобы следовать примеру в ответе @Stewe ниже, который просто объединит все данные самостоятельно. например

var concat = require('concat-stream');
app.use(function(req, res, next){
  req.pipe(concat(function(data){
    req.body = data;
    next();
  }));
});

Недостатком этого является то, что вы теперь переместили все содержимое тела POST в оперативную память как непрерывный блок, который может не потребоваться. Другой вариант, который стоит рассмотреть, но зависит от того, сколько данных вам нужно обработать в теле сообщения, - вместо этого обрабатывать данные в виде потока.

Например, с XML вы можете использовать синтаксический анализатор XML, который поддерживает синтаксический анализ XML, так как он поступает в виде кусков. Одним из таких парсеров будет XML Stream. Вы делаете что-то вроде этого:

var XmlStream = require('xml-stream');

app.post('/', function(req, res) {
  req.setEncoding('utf8');
  var xml = new XmlStream(req);
  xml.on('updateElement: sometag', function(element) {
    // DO some processing on the tag
  });
  xml.on('end', function() {
    res.end();
  });
});

Примерно так должно работать:

var express = require('./node_modules/express');
var app = express.createServer();
app.use (function(req, res, next) {
    var data='';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { 
       data += chunk;
    });

    req.on('end', function() {
        req.body = data;
        next();
    });
});

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

С использованием bodyParser.text() промежуточное ПО поместит текстовое тело в req.body,

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

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

app.use('/routes/to/save/text/body/*', bodyParser.text({type: 'text/plain'})); //this type is actually the default
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

Если вы хотите сырье Buffer, ты можешь использовать bodyParse.raw(),

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

Примечание: этот ответ был проверен на узле v0.12.7, экспресс 4.13.2 и body-parser 1.13.3.

Поместите следующее промежуточное ПО перед промежуточным программным обеспечением bodyParser. Он будет собирать необработанные данные тела в request.rawBody и не будет мешать bodyParser.

app.use(function(req, res, next) {
    var data = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { 
        data += chunk;
    });
    req.on('end', function() {
        req.rawBody = data;
        next();
    });
});
app.use(express.bodyParser());
app.use(bodyParser.json({
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));
app.use(bodyParser.urlencoded({
    extended: false,
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));

Таким образом, похоже, что bodyParser Express анализирует только входящие данные, если content-type устанавливается на одно из следующих:

  1. application/x-www-form-urlencoded
  2. application/json
  3. multipart/form-data

Во всех других случаях это даже не беспокоит чтение данных.

Вы можете изменить строку №. 92 из экспресс /node_modules/connect/lib/middleware/bodyParser.js из

} else {
        next();
}

Для того, чтобы:

} else {
        var data='';
        req.setEncoding('utf8');
        req.on('data', function(chunk) { 
           data += chunk;
        });

        req.on('end', function() {
            req.rawBody = data;
            next();
        });
}

А потом прочитайте req.rawBody из вашего кода.

Все ответы кажутся устаревшими, если кто-то все еще борется с этим, то экспресс имеет встроенное промежуточное ПО Express .

Это промежуточное ПО доступно в версии Express v4.16.0 и выше. Это встроенная промежуточная функция в Express. Он анализирует входящие запросы с полезными данными JSON и основан на анализаторе тела.

      var express = require("express");
var app = express();

app.use(express.raw({ type: "*/*" }))

app.post("/", (req, res) => {
  // req.body = JSON.parse(req.body); // To parse JSON if needed (in-case)
  console.log(req.body);
  res.end();
});

app.listen(3000, (err) => {
if(!err) console.log("App running!!")
});

Если вы хотите тело в качестве буфера:

var rawParser = function(req, res, next) {
    var chunks = [];
    req.on('data', function(chunk) { 
        chunks.push(chunk)
    });
    req.on('end', function() {
        req.body = Buffer.concat(chunks);
        next();
    });
}

или же

var rawParser = bodyParser.raw({type: '*/*'});

а потом:

app.put('/:name', rawParser, function(req, res) {
  console.log('isBuffer:', Buffer.isBuffer(req.body));
})

или для всех маршрутов:

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

Кажется, теперь стало намного проще!

Модуль body-parser теперь может анализировать необработанные и текстовые данные, что делает задачу одной строкой:

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

ИЛИ ЖЕ

app.use(bodyParser.raw({type: 'application/binary'}))

Обе строки просто заполняют body свойство, поэтому получите текст с res.body,bodyParser.text() даст вам строку UTF8 в то время как bodyParser.raw() дам тебе

Это полный код для текстовых / простых данных:

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

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

app.post('/', function (req, res, next) {
    console.log('body:\n' + req.body)

    res.json({msg: 'success!'})

    next()
})

Смотрите здесь для полной документации: https://www.npmjs.com/package/body-parser

Я использовал Express 4.16 и Body-Parser 1.18

Если у вас возникли проблемы с вышеуказанными решениями, мешающими обычным почтовым запросам, может помочь что-то вроде этого:

app.use (function(req, res, next) {
    req.rawBody = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { req.rawBody += chunk });
});

Дополнительная информация и источник: https://github.com/visionmedia/express/issues/897

БУДЬТЕ ОСТОРОЖНЫ с этими другими ответами, так как они не будут правильно работать с bodyParser, если вы хотите также поддерживать json, urlencoded и т. Д. Чтобы заставить его работать с bodyParser, вы должны обработать ваш обработчик только для регистрации на Content-Type Заголовки, которые вас интересуют, как и сам bodyParser.

Чтобы получить необработанное содержание тела запроса с Content-Type: "text/xml" в req.rawBody ты можешь сделать:

app.use(function(req, res, next) {
  var contentType = req.headers['content-type'] || ''
    , mime = contentType.split(';')[0];

  if (mime != 'text/xml') {
    return next();
  }

  var data = '';
  req.setEncoding('utf8');
  req.on('data', function(chunk) {
    data += chunk;
  });
  req.on('end', function() {
    req.rawBody = data;
    next();
  });
});

При отправке запроса обязательно добавьте этот заголовок:

      'Content-Type': 'application/json'
Другие вопросы по тегам