Node Express Middleware - javascript

I am currently writing an express app and want to use some custom middleware that I have written however express keeps throwing an issue.
I have an es6 class that has a method that accepts the correct parameters like below:
foo(req, res, next){
console.log('here');
}
then in my app I am telling express to use it like so:
const module = require('moduleName');
...
app.use(module.foo);
but express keeps throwing this error:
app.use() requires middleware functions
any help would be greatly appreciated.

This error always occurs TypeError: app.use() requires middleware functions
Since you are not exporting that function that's why it's unreachable
try to export it like this from file
exports.foo=function(req, res, next){
console.log('here');
next();
}
You can also use module.exports
module.exports={
foo:function(req,res,next){
next();
}
}

The solution has two parts. First make the middleware function a static method of that class that you export from your module. This function needs to take an instance of your class and will invoke whatever methods you need to.
"use strict";
class Middle {
constructor(message) {
this._message = message;
}
static middleware(middle) {
return function middleHandler(req, res, next) {
// this code is invoked on every request to the app
// start request processing and perhaps stop now.
middle.onStart(req, res);
// let the next middleware process the request
next();
};
}
// instance methods
onStart(req, res) {
console.log("Middleware was given this data on construction ", this._message);
}
}
module.exports = Middle;
Then in your node JS / express app server, after requiring the module, create an instance of your class. Then pass this instance into the middleware function.
var Middle = require('./middle');
var middle = new Middle("Sample data for middle to use");
app.use(Middle.middleware(middle));
Now on every request your middle ware runs with access to the class data.

Related

Expressjs middleware keeps variable changed

I am trying to do a simple thing which is obvious I believe in the code below:
module.exports = function(req, res, next) {
var dop = require('../../config/config').DefaultOptions;
console.log(require('../../config/config').DefaultOptions);
console.log(dop);
dop.firstPage = 'test.sjs';
next();
};
This is an Expressjs middle ware which is very simple but the interesting point is that next time I load a page both of the console.log results has been changed to 'firstPage: test.sjs'. It shouldn't act like this and it should only change the dop variable.
Anyone with the knowledge why this creepy thing is happening?
Thank you
The main issue is require() is cached, so require('../../config/config') returns reference to the same instance, and as a result changing in one place causes all other references and subsequent requires to get that modified instance.
The simplest solution would be have a function in config to return a config object, that way every time invoking the get config function you will get a new instance with essentially the same content. I.e.:
config.js:
module.exports = {
getDefaultOptions: function(){
return {foo: 'bar', ip: '1.1.1.1'}
}
};

How to access global scope variables in callback functions? [JS]

For my user registration I have
const express = require ('express');
const userRouter = express.Router ();
userRouter.get ('/', function getUserList (req, res) {
let User = require ('../models').User;
User.find ({}, function (err, list) {
res.json (list);
});
});
userRouter.post ('/', function createUser (req, res) {
let User = require ('../models').User;
if (req.body.username && req.body.password)
User.create (req.body, function (err, user) {
res.json (user);
});
});
... 3 more functions with the same `let User` ...
module.exports = userRouter;
Here, I have to require the module models twice. I tried setting the User variable as a global variable up at the top of the program, like
const express = ..., userRouter = ...
var User = ...
However this User variable is still not accessible inside my callback functions.
Is requiring the User module multiple times the correct way to do this or am I missing something?
edit: Inside the callback functions, the User variable is undefined.
As #Doug mentioned, you should pass global to the user variable like this:
global.user = ...
This process essentially turns user into a globally accessible variable. You can read more about Node's global here to understand what it does as well as understand what it's implications are too: http://stackabuse.com/using-global-variables-in-node-js/
To #charloetfl ‘s point if it is just within the file, declaring it outside the callback or on top of the file should do. If we are talking about access across all modules and files within the project then adding it to the global object is the way to go about it in node as #doug and #andrewl mentioned.

Why is this Express middleware not being called with arguments?

I am working on a middleware that needs bodyParser to run, but I don't want to make the app bring that in as a dependency. Instead, I want to make a package that requires that and exports a middleware like this:
//routes.js
app.use('/', middlewareWrapper(thing));
//middlware.js
export function middlewareWrapper(thing) {
return function addBody(req, res, next) {
function othermiddleware(_req, _res) {
// do something with thing and _req
return next();
}
return bodyParser.json()(req, res, othermiddleware);
};
}
This looks like it would work, and the othermiddleware is called, but with no arguments.
I found another answer that addresses this in basically the same way (it's old, but JS still works the same way): https://stackoverflow.com/a/17997640/444871
Why is the othermiddleware being called with no args?
The problem is that the middleware returned by bodyParser.json() simply call next() like this (i.e. with no argument). Here you are passing othermiddleware as next to the middleware returned by bodyParser.json(). Therefore it does not contain any argument.
Also the bodyParser does not change the original reference of req/res object. So the main req/res object still refer to the same object. So you dont need arguments to be passed. You can simply use the same req/res object in your othermiddleware function too.
return function addBody(req, res, next) {
function othermiddleware() {
// You should be able to use req and res modified by bodyParser.
// You dont need arguments to be passed.
return next();
}
return bodyParser.json()(req, res, othermiddleware);
};
Cause you do
next();
without passing parameters. Usually express does sth like that:
bodyParser.json()(
req,
res,
() => {
othermiddleware(req,res,next);
}
);
Or you use some bind magic:
bodyParser.json()(req, res, othermiddleware.bind(this,req,res,next));

ExpressJS - Optional part of the URL which is not a param?

I have a route like this: /products/123/versions/456.
I want the sub resource to be optional, so I want one route path to handle both /products/123 and /products/123/versions/456.
This doesn't work: /products/:pid/versions?/:vid?.
How do I make the /versions/ part optional without making it a param with :..?
You can make a named handler and use it for two routes:
function yourhandler(req, res) {
// ...
}
app.get('/products/:pid', yourHandler);
app.get('/products/:pid/versions/:vid', yourHandler);
Or you can fight with regular expressions and optional parts. But those are really two different routes, not one, and it just happens that you want to use the same handler for both of them so using two app.get() (or whatever HTTP method it is) route definitions is the clearest way to solve it.
You can also add this if you need it as well:
app.get('/products/:pid/versions', yourHandler);
app.get('/products/*', (req, res, next){
const path = req.path;
//now use any logic on path as string
if(path.includes('versions')){
console.log('run version handler');
}else{
console.log('run else handler')}
}
//or const [product, version] = /\/products\/(.*)\/versions\/(.*)/.exec(path)
}

nodejs connect middleware function override

does the connect middleware prevent a middleware component from accidentally override a function that was a method of res? OR you just have to make sure you name it differently?
So in this example you basically just messed up the body data, whats the best way to prevent this?
.use(connect.bodyParser())
.use(function(req,res,next){
req.body=null;
})
.use(function(req,res){
res.end(req.body);
});
You can put everything in your own namespace if you're very worried about it:
app.use(function (req, res, next) {
req.myappname.foo = null
req.myappname.bar = null
});
Or just make absolutely sure it doesn't exist before you overwrite it. You can always do a manual check in a test script.

Categories

Resources