Search code examples
javascriptexpressmiddleware

Express middleware error


I'm making an API that accepts a video and uploads it to cloudinary. Meta data about the upload is then returned to the user. The problem that I am having occurs when I try to handle the video in middleware. I'm not sure why I keep getting this error.

The error:

/Users/name/test/cloudinary_upload/node_modules/express/lib/router/route.js:196
        throw new Error(msg);
        ^

Error: Route.post() requires callback functions but got a [object Object]
    at Route.(anonymous function) [as post] (/Users/name/test/cloudinary_upload/node_modules/express/lib/router/route.js:196:15)
    at Function.proto.(anonymous function) [as post] (/Users/name/test/cloudinary_upload/node_modules/express/lib/router/index.js:510:19)
    at Object.<anonymous> (/Users/name/test/cloudinary_upload/routes.js:8:8)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)

PROJECT CODE BELOW:

app.js

'use strict';

var express = require('express');
var formidable = require('express-formidable');
var port = process.env.PORT || 3000;
var routes = require('./routes');
var app = express();

// Parse incoming request
app.use(formidable());

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

// Catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// Error handler
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.json({
    error: {
      message: err.message
    }
  });
});


app.listen(port, function() {
  console.log('Express server is listening on port ' + port);
});

routes.js

'use strict';

var express = require('express');
var createThumbnail = require('./middleware/generatevideothumbnail');
var uploadToCloudinary = require('./middleware/uploadtocloudinary');
var router = express.Router();

router.post('/upload', uploadToCloudinary, createThumbnail, function(req, res, next) {
  console.log(req.cloudinaryObject);
  console.log(req.videoThumbnail);
  res.json(req.cloudinaryObject);
});

module.exports = router;

uploadtocloudinary.js

'use strict';

var cloudinary = require('../cloudinary_config.js').cloudinary;

/************************************************************
MIDDLEWARE: Accepts the request object. Uploads the video
file to cloudinary. Passes the video's public id, version, file
type, time of upload, file size and url to the next middleware
on the request object.
 ************************************************************/
function uploadToCloudinary(req, res, next) {
  cloudinary.uploader.upload(req.files.fileToUpload.path, function(resultOfUpload) {
    var cloudinaryObject = {
       public_id: resultOfUpload.public_id,
       version: resultOfUpload.version,
       typeOfFile: resultOfUpload.format, // Type of file
       uploadTime: resultOfUpload.created_at, // Upload time
       fileSize: resultOfUpload.bytes, // File size
       videoUrl: resultOfUpload.secure_url // Video URL
     }

    req.cloudinaryObject = cloudinaryObject;

    next();
  }, {
    resource_type: "video"
  });
}

module.exports.uploadToCloudinary = uploadToCloudinary;

generatevideothumbnail.js

'use strict';

/************************************************************
MIDDLEWARE: Accepts the request object. Use the version and
public id of video to create thumbnail url string. Pass
thumbnail url to next middleware on the request object.
 ************************************************************/
 function generateVideoThumbnail(req, res, next) {
  req.videoThumbnail = "https://res.cloudinary.com/xxxxxxxxx/video/upload/v"
                       + req.cloudinaryObject.version
                       + "/"
                       + req.cloudinaryObject.public_id
                       + ".jpg";

  next()
}

module.exports.generateThumbnail = generateVideoThumbnail;

Solution

  • There are a few different choices of what to send with your required file when you use module.exports. You can send an entire object, or you can send specific functions.

    With module.exports.uploadToCloudinary= and module.exports.generateThumbnail= you're sending an object that includes the functions uploadToCloudinary and generateThumbnail. When you require it with, for example,

    var createThumbnail = require('./middleware/generatevideothumbnail'); 
    

    you are able to use the function generateThumbnail on the object you're exporting. In other words, to access the function you want, you'd have to write:

     createThumbnail.generateThumbnail
    

    If you just want to be able to use only one specific function when you bring in the required file, just give the name of the function to module.exports, like this:

    module.exports = generateVideoThumbnail;
    

    Reference: https://www.sitepoint.com/understanding-module-exports-exports-node-js/ and https://nodejs.org/api/modules.html

    Let me know if this makes sense.