Node.js - отримати необроблене тіло запиту за допомогою Express


Відповіді:


89

Редагування 2: Випуск 1.15.2 модуля парсера тіла вводить режим raw , який повертає тіло як буфер . За замовчуванням він також автоматично обробляє дефляцію та декомпресію gzip. Приклад використання:

var bodyParser = require('body-parser');
app.use(bodyParser.raw(options));

app.get(path, function(req, res) {
  // req.body is a Buffer object
});

За замовчуванням optionsоб’єкт має такі параметри за замовчуванням:

var options = {
  inflate: true,
  limit: '100kb',
  type: 'application/octet-stream'
};

Якщо ви хочете, щоб сирий синтаксичний аналізатор проаналізував інші типи MIME, крім application/octet-stream, вам потрібно буде змінити його тут. Він також підтримуватиме підстановку символів підстановки, таких як */*або */application.


Примітка: Наступна відповідь стосується версій до Express 4, де проміжне програмне забезпечення все ще було в комплекті з фреймворком. Сучасним еквівалентом є модуль парсеру тіла , який повинен бути встановлений окремо.

rawBodyНерухомість Експрес коли - то була доступна, але видалені , починаючи з версії 1.5.1. Щоб отримати необроблене тіло запиту, перед використанням bodyParser потрібно додати проміжне програмне забезпечення. Ви також можете прочитати обговорення GitHub про це тут .

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  req.on('end', function() {
    next();
  });
});
app.use(express.bodyParser());

Це проміжне програмне забезпечення зчитує з фактичного потоку даних і зберігає його у rawBodyвластивості запиту. Потім ви можете отримати доступ до сирого тіла таким чином:

app.post('/', function(req, res) {
  // do something with req.rawBody
  // use req.body for the parsed body
});

Редагувати: Здається, цей метод і bodyParser відмовляються співіснувати, оскільки один споживатиме потік запитів перед іншим, приводячи до того, який із секунд ніколи не запускатиметься end, таким чином ніколи не викликатиме next()і не повіситиме вашу програму.

Найпростішим рішенням було б, швидше за все, змінити джерело bodyParser, яке ви знайдете в рядку 57 парсера JSON Connect. Ось як би виглядала змінена версія.

var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function() {
  req.rawBody = buf;
  var first = buf.trim()[0];
  ...
});

Ви знайдете файл у цьому місці:

/node_modules/express/node_modules/connect/lib/middleware/json.js.


Здається, ми не можемо цього зробити. Якщо я додав цей код, події в \ node_modules \ express \ node_modules \ connect \ lib \ middleware \ urlencoded.js не запускатимуться. req.on ("дані"), req.on ("кінець") не запущено .
haitao_wu

Після додавання вашого коду я обробляю свою публікацію, використовуючи цей код app.post ("/ ajax", function (req, res) {res.send ('hello world, post');}); коли тип вмісту мого запиту - application / x-www-form-urlencoded, сервер не буде відповідати "привіт світ, допис"
haitao_wu

розташування файлу в моєму випадку неправильне .. У мене немає модуля підключення в node_modules express (> 4.0.0), ще не знайдено нове місце розташування
Сем Влобергс,

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

1
@hexacyanide Чи можете ви оновити свою відповідь та включити посилання на новітнє проміжне програмне забезпечення для синтаксичного аналізатора ? Модуль тепер включає проміжне програмне забезпечення синтаксичного аналізатора . Це може бути корисно для гуглерів, які шукають спосіб отримати сире тіло.
eAbi

47

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

app.use(bodyParser.json({
    verify: function(req, res, buf, encoding) {

        // sha1 content
        var hash = crypto.createHash('sha1');
        hash.update(buf);
        req.hasha = hash.digest('hex');
        console.log("hash", req.hasha);

        // get rawBody        
        req.rawBody = buf.toString();
        console.log("rawBody", req.rawBody);

    }
}));

Я новачок у Node.js та express.js (почався вчора, буквально!), Тому я хотів би почути коментарі щодо цього рішення.


3
Мені дуже подобається це рішення. Я просто включив req.rawBody = buf.toString();і вилучив решту з verifyфункції, тому що це було все, що мені потрібно, і це працювало чудово. Не потрібно міняти вихідний код bodyParser!
Грег,

+1, але моя проблема зараз полягає в тому, що мені потрібна функція асинхронізації, щоб підтвердити, чи був цей запит раніше відправлений чи ні: /
Ренато Гама

3
дуже мило. чи можу я запропонуватиreq.rawBody = buf.toString(encoding);
shaharsol

2
Це буде фіксувати лише application/jsonзапити
Павло Євстигнєєв

35

Це рішення спрацювало для мене:

var rawBodySaver = function (req, res, buf, encoding) {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || 'utf8');
  }
}

app.use(bodyParser.json({ verify: rawBodySaver }));
app.use(bodyParser.urlencoded({ verify: rawBodySaver, extended: true }));
app.use(bodyParser.raw({ verify: rawBodySaver, type: '*/*' }));

Коли я використовую рішення з req.on('data', function(chunk) { });ним, що не працює на шматок тіла запиту.


Це подбало про кожен основний сценарій вхідних даних у різних частинах запиту.
TWright

2
Я намагався перевірити hmac для веб-хука програми Shopify, і це спрацювало для мене. Я грубо наслідував цей приклад: gist.github.com/andjosh/5c4f0244914adfd312e4 .
Чад Джонсон,

29

Будьте обережні з тими іншими відповідями , оскільки вони не гратимуть правильно з bodyParser , якщо ви хочете , щоб також підтримка JSON, urlencoded і т.д. Для того, щоб отримати його на роботу з bodyParser ви повинні обумовлювати обробник тільки зареєструватися на Content-Typeзаголовку (и) ви дбати, як і сам bodyParser.

Щоб отримати необроблений вміст тіла запиту Content-Type: "text/plain"в, req.rawBodyви можете зробити:

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

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

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

3
+1. Я спробував одне з наведених вище рішень, і тоді всі мої публікації GET і json не працювали. Наведені вище рішення технічно правильні для запитання, але якщо ви обробляєте різноманітні запити з даними у кількох формах, вам це знадобиться.

Що тут дані? це змінна, яку ми надсилаємо з інтерфейсу користувача?
Saras Arya

app.use(bodyParser.urlencoded({limit: '80mb', extended: true})); app.use(bodyParser.json({limit: '80mb'})); app.use(bodyParser.raw({type: 'application/octet-stream'})) Це теж могло б зробитись.
Soumya Kanti

15

Це варіація відповіді на гексаціанід вище. Це проміжне програмне забезпечення також обробляє подію "data", але не чекає споживання даних, перш ніж викликати "next". Таким чином, і це проміжне програмне забезпечення, і bodyParser можуть співіснувати, паралельно споживаючи потік.

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  next();
});
app.use(express.bodyParser());


2
Здається, це не працює на довгих тілах, які рано відсікаються.
Адам Локхарт,

Працював ідеально, врятував мене. Дякую.
hakazvaka

Я підтверджую, що це працює і для великих файлів. Я спробував надіслати текстовий файл розміром 1,5 Мб, і всі дані були отримані належним чином. Дякую
ATOzTOA

@AdamLockhart - якого розміру були вирізані ваші запити?
UpTheCreek

@UpTheCreek, пройшов якийсь час. Не впевнений. Мої останні матеріали не використовують цей фрагмент, але якщо інші не повідомляють про проблеми, можливо, це була помилка, яку було виправлено.
Адам Локхарт,

-1

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

app.use(bodyParser.text());

app.use(bodyParser.urlencoded());

app.use(bodyParser.raw());

app.use(bodyParser.json());

тобто Якщо ви повинні отримати необроблений текстовий файл, запустіть .text().

Ось що в даний час підтримує парсер тіла

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