14

I am creating a web API using Express. The feature is to allow API users to send a file to the server.

Here's my app setup code:

var express = require('express');
var path = require('path');
// ...
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

// API routes
var images = require('./routes/api/img');

var app = express();

app.use(bodyParser.raw());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/api', images);

// ...

module.exports = app;

Please notice that I am using app.use(bodyParser.raw());.

How do I get the raw bytes from POST requests?

const express = require('express');
const router = express.Router();

/* POST api/img */
router.post('/img', function(req, res, next) {

  // how do I get the raw bytes?

});

module.exports = router;
Believe2014
  • 3,894
  • 2
  • 26
  • 46
  • Please consider narrowing down your code example to only the parts relevant to your question. In this case I think only some of the app.use lines and the second code snippet are really necessary. – Squirrel Jul 19 '16 at 21:41

3 Answers3

10

if you want to send a raw data and get with body parser you just configure this way:

app.use(bodyParser.raw({ inflate: true, limit: '100kb', type: 'text/xml' }));

That behavior doesn't corrupt the body content.

joelton
  • 153
  • 2
  • 9
  • 5
    The important thing is to add the **type** parameter. The default behavior if **type** is omitted is to check against type "application/octet-stream", as can be seen [here](https://github.com/expressjs/body-parser/blob/bd386d3a7d540bac90bbdaff88f653414f6647fc/lib/types/raw.js#L39) (and is probably unexpected for most users of the library). To match against any content type, use `type: "*/*"`. – Odysseas Feb 26 '19 at 16:33
  • @Odysseas saying 'checks against' is misleading. The correct word is 'defaults to'. Thanks for the link. `var type = opts.type || "application/octet-stream"` – Gilbert Sep 03 '21 at 19:21
8

To parse all content types I use:

app.use(
  express.raw({
    inflate: true,
    limit: '50mb',
    type: () => true, // this matches all content types
  })
);

To get the raw body in just a single route:

app.put('/upload', express.raw({ inflate: true, limit: '50mb', type: () => true }), async (req, res) => {
  res.json({ bodySize: req.body.length });
});

In that case note that the previously app.use()'d body parsers (json for example) are executed first - so check that req.body is indeed a Buffer, otherwise a malicious caller could send something like {"length":9999999} with Content-Type: application/json.

Moritz
  • 1,590
  • 13
  • 8
3

The parsed body should be set on req.body.

Keep in mind that middleware is applied in the order you set it with app.use, my understanding is that applying the bodyParser multiple times as you have will attempt to parse the body in that order, leaving you with the result of the last middleware to operate on req.body, i.e. since both bodyParser.json() and bodyParser.raw() both accept any inputs, you will actually end up attempting to parse everything from a Buffer into JSON.

Squirrel
  • 231
  • 2
  • 9
  • Is there any way for limiting the `bodyParser.raw()` middleware to only certain `Content-Type`? – Believe2014 Jul 19 '16 at 21:49
  • 2
    Excellent question, apparently there is! From the docs[1](https://www.npmjs.com/package/body-parser#bodyparserrawoptions) The raw function takes an option options object that may contain any of the following keys: The type option is used to determine what media type the middleware will parse. This option can be a function or a string... It even accepts wildcards for the mime types, so that should let you get as granular as you need. – Squirrel Jul 20 '16 at 17:02
  • Let me expand then, could you parse only some router endpoints as raw and leave the rest as json? – Peter Poliwoda Apr 17 '20 at 09:59