Express middleware error - javascript

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;

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.

Related

Why do I get this error when trying to use Multer for dynamic path?

app.post('/upload/image', multer({
dest: './public/users/',
changeDest: function(dest, req, res) {
var newDestination = dest ;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
throw new Error("directory cant be created");
}
return newDestination
}
}), function(req, res) {
res.send({"status":"success"})
});
I tried using this code so that I can dynamically set the path for multer to store the uploaded pictures from the client. But this code is giving me this error
throw new Error(msg);
^
Error: Route.post() requires a callback function but got a [object Object]
at Route.<computed> [as post] (/Volumes/MacExtnd/Programming/webshop/backend/node_modules/express/lib/router/route.js:202:15)
at Function.app.<computed> [as post] (/Volumes/MacExtnd/Programming/webshop/backend/node_modules/express/lib/application.js:482:19)
at Object.<anonymous> (/Volumes/MacExtnd/Programming/webshop/backend/server.js:733:5)
Please can anyone tell me how to solve this error?
multer(opts) return an object with properties like .single(), .none(). See docs here.
You are passing this object as an Express middleware function, which explains the error. You would want to chose the correct property and pass that instead.
Example from the docs:
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})

Express & Node.js Exception: 500 TypeError: fn is not a function

I created a Node.js project using Express and got this exception when using a customized routes.
500 TypeError: fn is not a function
at callbacks (/WallaceBot/WallaceBot/node_modules/express/lib/router/index.js:272:11)
at param (/WallaceBot/WallaceBot/node_modules/express/lib/router/index.js:246:11)
at pass (/WallaceBot/WallaceBot/node_modules/express/lib/router/index.js:253:5)
at Router._dispatch (/WallaceBot/WallaceBot/node_modules/express/lib/router/index.js:280:5)
at Object.Router.middleware [as handle] (/WallaceBot/WallaceBot/node_modules/express/lib/router/index.js:45:10)
at next (/WallaceBot/WallaceBot/node_modules/express/node_modules/connect/lib/http.js:204:15)
at Object.methodOverride [as handle] (/WallaceBot/WallaceBot/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js:35:5)
at next (/WallaceBot/WallaceBot/node_modules/express/node_modules/connect/lib/http.js:204:15)
at Object.bodyParser [as handle] (/WallaceBot/WallaceBot/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js:88:61)
at next (/WallaceBot/WallaceBot/node_modules/express/node_modules/connect/lib/http.js:204:15)
And I declare the routes in app.js by
var webhook = require('./routes/webhook.js');
app.get('/', routes.index);
app.get('/webhook', webhook);
And in my webhook.js,
/*
* GET Webhook.
*/
exports.webhook = function(req, res){
res.render('index', { title: 'Webhook' })
};
However, I use another way to declare the route in app.js, like
app.get('/webhook', function(req, res){
res.render('index', { title: 'Webhook' })
});
I don't get that exception.
Does anybody know why?
var webhook looks like this:
{
"webhook" : function(req, res) { ... }
}
So your route handler setup looks like this:
app.get('/webhook', {
"webhook" : function(req, res) { ... }
});
Which is invalid, because Express wants a function argument, not an object.
Instead, you want to use webhook property of the exported module object:
var webhook = require('./routes/webhook.js').webhook;
As an alternative solution to the other answer you may change your webhook.js file to look like this:
/*
* GET Webhook.
*/
exports = module.exports = function(req, res){
res.render('index', { title: 'Webhook' })
};

Can't get plotly + node.js to stream data coming through POST requests

I'm trying to get plotly to stream data received by my server through a POST request to http://localhost:3000/step.
Building on the rest-example.js in plotly-nodejs/examples, here's my server code (I've blurred out my username, apikey, and token):
'use strict';
var express = require('express');
var logger = require('morgan');
var bodyParser = require('body-parser');
var events = require('events');
var eventEmitter = new events.EventEmitter();
var app = express();
var server = require('http').Server(app);
var port = process.env.PORT || 3000;
server.listen(port);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/step', function(req, res) {
var data = req.body.data;
eventEmitter.emit('step', data);
res.end('ok');
});
var plotly = require('plotly')('username', 'apikey');
var token = 'token';
var dataInit = [{x:[], y:[], stream: { token: token, maxpoints: 10 } }];
var layout = {fileopt : "extend", filename : "REST-test"};
plotly.plot(dataInit, layout, function (err, msg) {
if(err) return console.error('step data error', err.stack);
var stream = plotly.stream(token, function() {});
eventEmitter.on('step', function(data) {
console.log('sending to plotly: ' + data + ' steps');
var streamObject = JSON.stringify({ x: getDateString(), y: data });
stream.write(streamObject+'\n');
});
});
function getDateString() {
var d = new Date();
return d.toLocaleString();
};
When I POST data using cURL, for example curl http://localhost:3000/step --data "data=5", I can see that the data reaches the callback inside the plotly.plot block, but plotly never starts up and streams the data.
In some slightly more complex server code I was working on earlier, I also get the error which may or may not be related and which always points to the beginning of the plotly.plot block.
cb(null, body);
^
SyntaxError: Unexpected end of input
This is the full error stack:
/home/plotly-testing/node_modules/plotly/index.js:305
cb(null, body);
^
SyntaxError: Unexpected end of input
at Object.parse (native)
at /home/plotly-testing/node_modules/plotly/index.js:72:25
at IncomingMessage.<anonymous> (/home/plotly-testing/node_modules/plotly/index.js:305:9)
at IncomingMessage.emit (events.js:129:20)
at _stream_readable.js:908:16
at process._tickCallback (node.js:355:11)
---------------------------------------------
at IncomingMessage.Readable.on (_stream_readable.js:671:33)
at parseRes (/home/plotly-testing/node_modules/plotly/index.js:304:9)
at ClientRequest.<anonymous> (/home/plotly-testing/node_modules/plotly/index.js:71:9)
at ClientRequest.emit (events.js:107:17)
at HTTPParser.parserOnIncomingClient (_http_client.js:426:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)
at TLSSocket.socketOnData (_http_client.js:317:20)
---------------------------------------------
at new ClientRequest (_http_client.js:93:10)
at Object.exports.request (http.js:49:10)
at Object.exports.request (https.js:136:15)
at Plotly.plot (/home/plotly-testing/node_modules/plotly/index.js:70:21)
at Object.<anonymous> (/home/plotly-testing/index.js:175:8)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
Line 305 of plotly/index.js points to the following method, which seems to indicate something was wrong in one of my callbacks, but I'm not sure.
// response parse helper fn
function parseRes (res, cb) {
var body = '';
if ('setEncoding' in res) res.setEncoding('utf-8');
res.on('data', function (data) {
body += data;
if (body.length > 1e10) {
// FLOOD ATTACK OR FAULTY CLIENT, NUKE REQ
res.connection.destroy();
res.writeHead(413, {'Content-Type': 'text/plain'});
res.end('req body too large');
return cb(new Error('body overflow'));
}
});
res.on('end', function () {
cb(null, body);
});
}
So I've modified the code to include a console.log inside the Plotly.plot callback.
See gist here:
https://gist.github.com/alexander-daniel/b36f9be78abbbaa4847e#file-index-js-L33
And that way we can see that Plotly returned a graph URL that we can look at.
https://gist.github.com/alexander-daniel/b36f9be78abbbaa4847e#file-console_output-L5
That should resolve the first issue.
As far as the second issue goes, it seems the problem is two fold:
- JSON.parse calls inside the library are not wrapped in try/catch, so it looks like if the stream-server returns anything that is not JSON, this will break.
We're looking into the streaming-server error returns, but I have opened this issue here re: the try/catch blocks in the API library.
github.com/plotly/plotly-nodejs/issues/37

TypeError: app.use() requires middleware functions

This is my server.js file and api.js file. I am getting an error in the sort function in which I intend to search the js objects according to their attributes.The event Schema has the attributes as name, location, price, rating. I tried to sort it according to their prices.
server.js
var express= require('express');
var bodyParser= require('body-parser');
var morgan = require('morgan');
var config=require('./config');
var app= express();
var mongoose=require('mongoose');
//var User=require('./database/user')
mongoose.connect('mongodb://localhost:27017/db',function(err){
if(err){
console.log(err);
}
else{
console.log("connected!");
}
});
app.use(bodyParser.urlencoded({extended: true })); //if false then parse only strings
app.use(bodyParser.json());
app.use(morgan('dev'));//log all the requests to the console
var api=require('./app/routes/api')(app,express);
app.use('/api',api);
app.get('*',function(req,res){
res.sendFile(__dirname + '/public/views/index.html');
}); // * means any route
app.listen(config.port,function(err){
if(err){enter code here
console.log(err);
}
else{
console.log("The server is running");
}
});
module.exports = router;
api.js
var User = require('../models/user');
var Event = require('../models/event');
var config = require('../../config');
var secret = config.secretKey;
module.exports = function (app, express) {
var api = express.Router();
app.use()
api.post('/signup', function (req, res) {
var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password
});
user.save(function (err) {
if (err) {
res.send(err);
return;
}
res.json({
message: 'User created!'
});
});
});
api.get('/users', function (req, res) {
User.find({}, function (err, users) {
if (err) {
res.send(err);
return;
}
res.json(users);
});
});
api.post('/eventfeed', function (req, res) {
var event = new Event({
name: req.body.name,
location: req.body.location,
description: req.body.description,
price: req.body.price,
rating: req.body.rating
});
event.save(function (err) {
if (err) {
res.send(err);
return;
}
res.json({
message: 'Event created!'
});
});
});
// utility function for sorting an array by a key in alpha order
api.get('/sortby_price', function (err) {
if (err) return err;
// utility function for sorting an array by a key in parsed numeric order
else {
function sortArrayNum(arr, key) {
arr.sort(function (a, b) {
return parseInt(a[key], 10) - parseInt(b[key], 10);
});
}
var dicts = EventSchema.saved;
for (var i = 0; i < dicts.length; i++) {
var terms = dicts[i].terms;
sortArrayNum(terms, "price");
}
}
return api;
});
}
This is my error. I am making a webpage for the first time using this. Kindly help me what does this error tells.
TypeError: app.use() requires middleware functions
at EventEmitter.use (c:\Users\MY APY\WebstormProjects\Main\node_modules\express\lib\application.js:209:11)
at module.exports (c:\Users\MY LAPY\WebstormProjects\Main\app\routes\api.js:10:9)
at Object. (c:\Users\MY LAPY\WebstormProjects\Main\server.js:20:36)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
I had this problem when I left out
module.exports = router;
in my Routes.js.We need to export all the routes.
In my server.js, I had
var mainRoutes = require('./Routes.js')
app.use(mainRoutes)
So check your 'app/routes/api' file to see if it has proper export.
Middleware is a function with access to the request object (req), the response object (res), and the next middleware in the application’s request-response cycle, commonly denoted by a variable named next.
Middleware can:
Execute any code.
Make changes to the request and the response objects.
End the request-response cycle.
Call the next middleware in the stack.
If the current middleware does not end the request-response cycle, it must call next() to pass control to the next middleware, otherwise the request will be left hanging.
In api.js line number 10 is invalid
app.use()
app.use must have a function with 3 params
// a middleware with no mount path; gets executed for every request to the app
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
if you want only few selected paths to use this middleware you can do something like this
// a middleware mounted on /user/:id; will be executed for any type of HTTP request to /user/:id
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// a route and its handler function (middleware system) which handles GET requests to /user/:id
app.get('/user/:id', function (req, res, next) {
res.send('USER');
});
Take a look at the expressjs documents it is pretty good.
http://expressjs.com/guide/using-middleware.html
You need to export your router in bottom of route file
like this module.exports = router;
and use in app.js file
const mainRoutes = require('./Routes.js')
app.use(mainRoutes)
Enjoy!
app.use requires that you pass it a function which is then used as middleware. You have two instances where you do not do this which will cause this error; both of which are in api.js.
api.js:10 app.use()
You do not pass a function to .use(), and so this will cause an error. This is the error you're seeing in your post.
However, you will get another error:
var api=require('./app/routes/api')(app,express);
app.use('/api',api);
This section attempts to mount the return value of your ./app/routes/api module function as a middleware. However, we can see inside your code that you do not actually return a value from the function in api.js; you instead return the router from inside a route handler..
// utility function for sorting an array by a key in alpha order
api.get('/sortby_price', function (err) {
if (err) return err;
// utility function for sorting an array by a key in parsed numeric order
else {
function sortArrayNum(arr, key) {
arr.sort(function (a, b) {
return parseInt(a[key], 10) - parseInt(b[key], 10);
});
}
var dicts = EventSchema.saved;
for (var i = 0; i < dicts.length; i++) {
var terms = dicts[i].terms;
sortArrayNum(terms, "price");
}
}
return api; // <- this will be returned inside the app.get call
});
You should instead move this out of the handler and to the end of your function.
The total amended code will look like this:
module.exports = function (app, express) {
var api = express.Router();
..omitted for brevity..
// utility function for sorting an array by a key in alpha order
api.get('/sortby_price', function (err) {
if (err) return err;
// utility function for sorting an array by a key in parsed numeric order
else {
function sortArrayNum(arr, key) {
arr.sort(function (a, b) {
return parseInt(a[key], 10) - parseInt(b[key], 10);
});
}
var dicts = EventSchema.saved;
for (var i = 0; i < dicts.length; i++) {
var terms = dicts[i].terms;
sortArrayNum(terms, "price");
}
}
});
return api;
}
I had this same issue recently. I exported the module as follows:
module.exports = { router };
Removing the curly braces fixed the error for me.
module.exports = router;

Node Js .get() requires callback functions

This is my server.js code
var express = require('express');
feeds = require('./routes/whatshappeningfeed');
var http = require('http');
var pathname = require('path');
// Test services - to be removed
courses = require('./routes/courses');
auth = require('./routes/auth');
token = require('./routes/token');
var app = express();
app.configure(function () {
app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser());
});
app.use(function (error, req, res, next) {
if (!error) {
next();
} else {
console.error(error.stack);
res.send(500);
}
});
app.get('/me/whatshappeningfeed',feeds.getfeeds);
app.get('/courses', courses.findAll);
app.get('/courses/:id', courses.findById);
app.get('/token', token.auth);
app.get('/auth', auth.auth);
app.get('/refresh', auth.refresh);
app.listen(80);
console.log('Listening on port 80...');
this is my error message :
F:\NODE.JS\poc\node_modules\express\lib\router\index.js:291
throw new Error(msg);
^
Error: .get() requires callback functions but got a [object Undefined]
at F:\NODE.JS\poc\node_modules\express\lib\router\index.js:291:11
at Array.forEach (native)
at Router.route (F:\NODE.JS\poc\node_modules\express\lib\router\index.js:287:13)
at Router.(anonymous function) [as get] (F:\NODE.JS\poc\node_modules\express\lib\router\index.js:318:16)
at Function.app.(anonymous function) [as get] (F:\NODE.JS\poc\node_modules\express\lib\application.js:431:26)
at Object.<anonymous> (F:\NODE.JS\poc\server.js:44:5)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
When i run the node server.js file i got above error. it was working earlier. i couldn't sort out the issue. please anyone help me.
The error says it all, app.get() requires a callback function. So it means that one or more of your routes are missing a callback.
ALL of your routes should have a function(req,res), whether explicitely as in the example or in another function (see comments) :
app.get('/me/whatshappeningfeed', function(req,res){ //request, response
//then here you can define what your server should send as a response when queries for /me/whatshappeningfeed
res.send(feeds.getfeeds()); //this will send back to the browser the result of feeds.getfeeds()
});
Also, not sure if it's due to the copypaste you did, but the first semicolon require('express'); should be a comma.

Categories

Resources