2

This question is very similar to How to disable Express BodyParser for file uploads (Node.js). The answer they have provided is for Express3 and I have tried the solution with the updated Express 4 and it does not seem to work.

I'm using Node.js + Express to build a web application. I am using another library,BodyParser,to parse post parameters. However, I would like to have more granular access to multipart form-data POSTS as they come - I need to pipe the input stream to another server, and want to avoid downloading the whole file first.

All file uploads are parsed automatically and uploaded and available using "request.files" before they ever get to any of my functions.

Is there a way for me to disable the BodyParser for multipart formdata posts without disabling it for everything else?

This is my app.js file. In here I am defining an authentication route which shouldn't except any files just a token (POST parameter). I am also defining another route called upload. This route accepts a file and also POST parametes (form-data). This route only gets called if the authentication route allows it. So in the authetnication route I don't want form-data to be allowed, but in the upload route I do. So when I get a request to uplaod something it will go through the auth route and then the upload route. Due to this I need to allow the auth route to allow files (form-data) which I do not want. So I want bodyparser to work in the auth route while I use mutler (another library) in my upload path to parse my upload files. In my real application though of course I have many more routes and would like to code it as cleanly as I can with the least amount of redundancy.

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


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


var route_auth = require('./routes/auth');
app.use('/api/post/*', route_auth);
var route_upload = require('./routes/post/upload');
app.use('/api/post/upload', route_upload );


app.listen(3000, function() {
    console.log('Server listening on port 3000!')
});

My auth route looks something like this:

router.post("/", function(req, res, next) {
       if(everythingiscool){
            return next()
        }
           next(err);
});

My upload route looks like this:

var express = require('express');
var router = express.Router();
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' });

router.post("/", upload.single('avatar'), function(req, res, next) {
         //work with req.file
});
Community
  • 1
  • 1
user2924127
  • 6,034
  • 16
  • 78
  • 136
  • Please show us the code you're using for body-parser because you can enable it only for certain content types or certain routes so we need to see what you're doing. – jfriend00 Mar 21 '17 at 02:52
  • One solution would be to place the upload handler BEFORE the body-parser middleware. So the upload route is processed before the body-parser middleware and thus it never even sees the request. Handlers (either middleware or route handlers) are procesed in the order defined. Another solution would be to separate out the upload handlers into their own router that has the only the upload middleware on it. – jfriend00 Mar 21 '17 at 03:43
  • WIth the first suggestion if I did this wouldn't the authentication route not work then. If the order was auth route -> bodyParser declaration -> upload route then wouldn't his not work because the auth route needs the body parser. In regards to the second solution, sorry I am not quite sure what you mean? – user2924127 Mar 21 '17 at 03:49
  • @jfriend00 I just tried to implement the first solution it to test. It does not work, the auth route never gets called because it first finds the upload route since it is above the bodyparser and the auth is below the bodyparser. – user2924127 Mar 21 '17 at 04:11

2 Answers2

4

Wrap the bodyParse middleware in a function that checks if the request body's Content-Type is multipart or not:

var isMultipart = /^multipart\//i;
var bodyParser = require('body-parser');
var urlencodedMiddleware = bodyParser.urlencoded({ extended: true });
app.use(function (req, res, next) {
  var type = req.get('Content-Type');
  if (isMultipart.test(type)) return next();
  return urlencodedMiddleware(req, res, next);
});
idbehold
  • 16,833
  • 5
  • 47
  • 74
0

Instead of disabling, why not enable the middleware on the routes/routers where you need it?

For individual routes, you can just add it as another argument before your actual route handler, for example:

app.post('/upload', bodyParser, (req, res) => {
  // route logic here
});
mscdex
  • 104,356
  • 15
  • 192
  • 153
  • I have a setup that every route goes first through an authentication route before any other routes can be accessed. I do not want this route to accept files only text. The auth route has the next() function which passes the request onto the next route if authentication is successful. So if the route goes auth route -> upload route the auth route would need to accept form-data because in the original request the file/image would be part of it. – user2924127 Mar 21 '17 at 02:47