Search code examples
javascriptnode.jsexpressmiddlewarebody-parser

Express Body Parser with both JSON and binary data passing capability


In my express app router, I've routes for accepting POST request of JSON data as well as binary data. The problem is when I use body parser for passing JSON data, it also considers the binary data as JSON and gives error while POSTing binary data. i.e. when I use:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));

And When I remove this, It only works for binary data. Following is my route for POSTing binary file.

router.post('/file', function (req, res) {
    var gridfs = app.get('gridfs');
    var writeStream = gridfs.createWriteStream({
        filename: 'file_name_here'
    });
    writeStream.on('close', function (file) {
        res.send(`File has been uploaded ${file._id}`);
    });
    req.pipe(writeStream);
});

I've also tried moving this file route to other router. In that case, when I don't set anything regarding body parser, it still gives the same error.

One fix that works correctly is placing this file route in my main app.js prior to setting body parser. But I think this would not be good approach. I want these routes to be in separate files.

So what I'm missing here? Any alternatives will also be appreciated.

EDIT

As per the answer, I've first separated out my routers which requires body parsing and which do not. Also removed the bodu parser from my main app.use() Now in the router in which, I need body parser, I've added those 2 lines. But the behavior is same.

When I add those 2 lines, only JSON reqquest works and when I remove, only binary POST req. works.

Here is my updated code:

app.js

    const express = require('express');
const app = module.exports = express();
const bodyParser = require('body-parser');

const port = 8080;


// //parsing incoming requests using body-parser middlewares
// app.use(bodyParser.json());
// app.use(bodyParser.urlencoded({ extended: false}));


//adding routes
app.use(require('./routes/additionRouter'));
app.use(require('./routes/mediaRouter'));

//catch 404 file not found here
app.use((req, res, next) => {
    const err = new Error('Page Not Found');
    err.status = 404;
    next(err);
});

//Error Handler
app.use((err, req, res, next) => {
    res.status(err.status || 500);
    res.send(err.message);
});

app.listen(port, () => {console.log('Server listening on port: ' + port)});

additionRouter.js

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

var exported = require('../config/dbConnection');

 const bodyParser = require('body-parser');

 // parsing incoming requests using body-parser middlewares
 router.use(bodyParser.json());
 router.use(bodyParser.urlencoded({ extended: false}));

//Endpoint for adding new challenge
router.post('/endpoint1', (req, res, next) => {

});

module.exports = router; 

and mediaRouter.js

    const express = require('express');
const mediaRouter = express.Router();
const exported = require('../config/dbConnection');

exported.cb((gridfs) => {
    //For adding media files to database named 'mediadb'
    //POST http://localhost:8080/file
    mediaRouter.post('/file', function (req, res) {
        // var gridfs = app.get('gridfs');
        var writeStream = gridfs.createWriteStream({
            filename: 'file_name_here'
        });
        writeStream.on('close', function (file) {
            res.send(`File has been uploaded ${file._id}`);
        });
        req.pipe(writeStream);
    });

    //GET http://localhost:8080/file/[mongo_id_of_file_here]
    mediaRouter.get('/file/:fileId', function (req, res) {
        // var gridfs = app.get('gridfs');
        gridfs.createReadStream({
            _id: req.params.fileId // or provide filename: 'file_name_here'
        }).pipe(res);
    });

});


module.exports = mediaRouter;

Solution

  • By specifying

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false}));
    

    your entire app uses the body parser middleware. You could create another middleware to handle whether or not the body parser is used. For example:

    const bodyParse = bodyParser.json();
    app.use((req, res, next) => {
        if(req.originalUrl == "restOfUrl/file") next();
        else bodyParse(req, res, next);
    });