How do I call {express,connect}.bodyParser() from within middleware? - express

I have some custom middleware. In some of my handlers, I want to use req.body, but that only works if the user did
app.use(express.bodyParser());
I could always tell the user, "you must use express.bodyParser() first," but I prefer to be safe and instantiate it if it has not been loaded yet.
Is there any way to invoke express.bodyParser() or connect.bodyParser() inside middleware?

I'm not sure if this is will work and if it'll always work, but I believe it'll be the "closer" way of doing what you want, without depending on connect/express (thing that you haven't specified in your question).
// Beware that the main module of the node process _must_
// be able to resolve express with this! This will allow to not depend on express.
var express = require.main.require( "express" );
// If you can depend on express, use this instead!
//var express = require( "express" );
function yourMiddleware( req, res, next ) {
var me = function( req, res ) {
// do your things
next();
};
if ( req.body === undefined ) {
express.bodyParser()( req, res, me );
} else {
me( req, res );
}
}

Related

express-validator on PUT methods

I'm creating an API and decided to use express-validator for validation (duh), I've never used this before so I'm unsure on some aspects of it so my validations might not be the best but I'm getting by.
I have built two validation middle ware using this and export them from the same folder like this:
module.exports = {
create: require('./create'),
update: require('./update')
}
So I can then do this in my router:
const validation = require('../validations/plotValidation')
// ...
router.get('/', controller.all)
router.post('/create', validation.create(), controller.create)
router.get('/:plotId', controller.read)
router.put('/:plotId/update', validation.update(), controller.update)
router.delete('/:plotId/delete', controller.delete)
// ...
I'm not good enough with express-validator to do both validate both routes with the same file, maybe I'll try it at some point, anyway.
The .post method works fine and validates everything I want it to however the .put method just seems to be ignoring every check here are is file in case you want to see the checks:
const { body, check, param } = require('express-validator');
module.exports = () => {
return [
param('plotId')
.exists().withMessage('URI requires plot id'),
body('price')
.optional()
.isObject()
]
}
As you can probably tell I only just stated it, but even with only these two tiny checks it just doesn't seem to run.
Does express-validator not work on PUT methods?
For anyone else who has this issue I solved this by using .run on my checks, you can read more about this here essentially this is the code that saved me:
// parallel processing
const validate = validations => {
return async (req, res, next) => {
await Promise.all(validations.map(validation => validation.run(req)));
const errors = validationResult(req);
if (errors.isEmpty()) {
return next();
}
res.status(400).json({ errors: errors.array() });
};
};

Error: Route.get() requires a callback function but got a [object Object] [duplicate]

So I'm starting to use Node.js. I saw the video with Ryan Dahl on Nodejs.org and heard he recommended Express-js for websites.
I downloaded the latest version of Express, and began to code. I have a fully fledged static view up on /, but as soon as I try sending parameters, I get errors like this:
Cannot GET /wiki
I tried following the guide on expressjs.com but the way one uses routes has changed in the latest version, which makes the guide unusable.
Guide:
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if (id) {
// do something
} else {
next();
}
});
Generated by Express:
app.get('/', routes.index);
My problem arises when I try and add another route.
app.get('/wiki', routes.wiki_show);
I've tried a bunch of approaches, but I keep getting the Cannot GET /wiki (404) error.
routes/index.js looks like this:
exports.index = function(req, res) {
res.render('index', { title: 'Test', articles: articles, current_article: current_article, sections: sections })
};
The only thing I did there was add some parameters (arrays in the same file) and this i working. But when I copy the contents and change exports.index to exports.wiki or exports.wiki_show I still get the Cannot GET /wiki error.
Can anyone explain to me what I'm missing here? - Thanks.
So, after I created my question, I got this related list on the right with a similar issue: Organize routes in Node.js.
The answer in that post linked to the Express repo on GitHub and suggests to look at the 'route-separation' example.
This helped me change my code, and I now have it working. - Thanks for your comments.
My implementation ended up looking like this;
I require my routes in the app.js:
var express = require('express')
, site = require('./site')
, wiki = require('./wiki');
And I add my routes like this:
app.get('/', site.index);
app.get('/wiki/:id', wiki.show);
app.get('/wiki/:id/edit', wiki.edit);
I have two files called wiki.js and site.js in the root of my app, containing this:
exports.edit = function(req, res) {
var wiki_entry = req.params.id;
res.render('wiki/edit', {
title: 'Editing Wiki',
wiki: wiki_entry
})
}
The route-map express example matches url paths with objects which in turn matches http verbs with functions. This lays the routing out in a tree, which is concise and easy to read. The apps's entities are also written as objects with the functions as enclosed methods.
var express = require('../../lib/express')
, verbose = process.env.NODE_ENV != 'test'
, app = module.exports = express();
app.map = function(a, route){
route = route || '';
for (var key in a) {
switch (typeof a[key]) {
// { '/path': { ... }}
case 'object':
app.map(a[key], route + key);
break;
// get: function(){ ... }
case 'function':
if (verbose) console.log('%s %s', key, route);
app[key](route, a[key]);
break;
}
}
};
var users = {
list: function(req, res){
res.send('user list');
},
get: function(req, res){
res.send('user ' + req.params.uid);
},
del: function(req, res){
res.send('delete users');
}
};
var pets = {
list: function(req, res){
res.send('user ' + req.params.uid + '\'s pets');
},
del: function(req, res){
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
}
};
app.map({
'/users': {
get: users.list,
del: users.del,
'/:uid': {
get: users.get,
'/pets': {
get: pets.list,
'/:pid': {
del: pets.del
}
}
}
}
});
app.listen(3000);
Seems that only index.js get loaded when you require("./routes") .
I used the following code in index.js to load the rest of the routes:
var fs = require('fs')
, path = require('path');
fs.readdirSync(__dirname).forEach(function(file){
var route_fname = __dirname + '/' + file;
var route_name = path.basename(route_fname, '.js');
if(route_name !== 'index' && route_name[0] !== "."){
exports[route_name] = require(route_fname)[route_name];
}
});
You could also organise them into modules. So it would be something like.
./
controllers
index.js
indexController.js
app.js
and then in the indexController.js of the controllers export your controllers.
//indexController.js
module.exports = function(){
//do some set up
var self = {
indexAction : function (req,res){
//do your thing
}
return self;
};
then in index.js of controllers dir
exports.indexController = require("./indexController");
and finally in app.js
var controllers = require("./controllers");
app.get("/",controllers.indexController().indexAction);
I think this approach allows for clearer seperation and also you can configure your controllers by passing perhaps a db connection in.
No one should ever have to keep writing app.use('/someRoute', require('someFile')) until it forms a heap of code.
It just doesn't make sense at all to be spending time invoking/defining routings. Even if you do need custom control, it's probably only for some of the time, and for the most bit you want to be able to just create a standard file structure of routings and have a module do it automatically.
Try Route Magic
As you scale your app, the routing invocations will start to form a giant heap of code that serves no purpose. You want to do just 2 lines of code to handle all the app.use routing invocations with Route Magic like this:
const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')
For those you want to handle manually, just don't use pass the directory to Magic.

Change Express static path dynamically

In Express you setup a static folder to serve your files through a middleware. From what I have understood this is then set throughout the applications lifecycle.
Is this possible to set somewhere in server.js for each request instead? For instance some requests uses "clientNew" folder while other requests uses "client". I want to be able to see the difference through a session-id, not through the URL.
So while this is not a recommended approach for a an "open" application with lots of users due to optimization with caching and response time I solved it by doing a pointer to the static handler.
exports.createDynamicPath = function(app, path) {
var static = app.loopback.static(path, { etag: false});
var dynamicPath = function (req, res, next) {
return static(req, res, next);
}
dynamicPath.setPath = function (newPath) {
static = app.loopback.static(newPath, { etag: false})
}
return dynamicPath;
}
exports.determineClient = function(app, dynamicPath){
return function(req, res, next) {
if(req.cookies && req.cookies.version != "client2"){
dynamicPath.setPath("client");
}else{
dynamicPath.setPath("client2");
}
next();
}
}
Based upon the variable in cookies it then switches path. Something worth noting is the disabling of etag, this is critical due to browsers storing previous client and determining if their file is still viable to keep.
This code is used early by the app, in this case Loopback (which by core uses Express).

Use external function in express.js middleware

How can I access some function from the outside world in the middleware? For example, if I need to check some part of request and set locals.
app.use(function (req, res, next) {
if (myfunc(req)) { // <-- how should I load this function to be accessible here?
res.locals.myvar = true;
}
next();
});
At the head of that file you'd want to import a custom module:
var myfunc = require('./path/to/myfunc/module')
That file would look like:
var myfunc = function(req) {
// Do something.
}
module.exports = myfunc;
Then, you should just be able to call: myfunc(req);
Further information on Custom NodeJS Modules.

Sails.js Policies, is there an OR operator to allow an action if one of a group of policies succeeds?

When configuring policies in sails in config/policies.js such as:
ActivityController: {
create: ['authenticated'],
update: ['authenticated', 'isActivityOwner'],
destroy: ['authenticated' ,'isActivityOwner']
}
Is there any functionality that would allow me to grant access to the action provided one or more of a group of policies succeeds maybe something like:
ActivityController: {
create: ['authenticated'],
update: ['authenticated', {or:['isActivityOwner', 'isAdmin']}],
destroy: ['authenticated' ,'isActivityOwner']
}
Alternatively is it possible to create composite policies so that in one policy I may check one or more other policies?
If both of these options seem like poor solutions, can you suggest an approach that would would be considered better practice?
Forgive me if this is a bit obvious but I'm fairly new to sails and node in general, and thanks in advance for any help!
I haven't found any official support for operators in sails policies but here is what I am doing.
ActivityController: {
update: ['authenticated', 'orActivityOwner', 'orAdmin', orPolicy],
}
Both orActivityOwner and orAdmin return next() as if they are valid. But they also set a boolean value to a session variable. Remember, policies are executed from left to right. I added an orPolicy to the end which will then evaluate the state of our session variable.
check out sails-must:
ActivityController: {
create: 'authenticated',
update: ['authenticated', must().be.the.owner.or.be.a.member.of('admins')],
destroy: ['authenticated', must().be.the.owner]
}
I've created a sails hook to be able to add parameters to policies:
https://github.com/mastilver/sails-hook-parametized-policies
I've setup an example where I defined an or policy:
module.exports = function(firstPolicy, secondPolicy){
return function(req, res, next){
var fakeRes = {};
for(var i in res){
if(i === 'forbidden'){
// override the functions you want the `or` factory to handle
fakeRes[i] = function(){
secondPolicy(req, res, next);
};
}
else{
fakeRes[i] = res[i];
}
}
firstPolicy(req, fakeRes, next);
}
}
Which you can use that way:
ActivityController: {
create: ['authenticated'],
update: ['authenticated', 'or(isActivityOwner, isAdmin)'],
destroy: ['authenticated' ,'isActivityOwner']
}
Just to complete the previous answer, that works like a charm :
Piece of information
But they also set a boolean value to a session variable
I myself prefer setting this boolean to the req object, that :
Is more semantic (access granted or not to ressource for the request, not for entire session)
Does not requires me to manually reset this variable
(I should add that, if you DO want to use session like in #Travis solution , the last orPolicy policy must reset (even unset) the variable in order to protect the next request)
My implementation
config/policies.js :
MyController: {
find: ['orIsTest1', 'orIsTest2', 'protectedResourceGranted']
}
api/policies/orIsTest1.js :
module.exports = function(req, res, next) {
req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERFIRSTTEST;
return next();
};
api/policies/orIsTest2.js
module.exports = function(req, res, next) {
req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERSECONDTEST;
return next();
};
api/policies/protectedResourceGranted.js
module.exports = function(req, res, next) {
if(req.protectedResourceGranted) {
return next();
}
return res.forbidden();
};
NB: Just answering 'cause I haven't got enough reputation to comment.
The other answers here work great, but here is an implementation that I find slightly cleaner.
Instead of creating policies designed for an OR situation that call next() even though they should fail, you can modify your existing policies to use in an AND/OR context, while hardly changing their behavior. Then create a composite policy (like the OP suggested) that checks the modified existing policies.
config/policies.js with example controllers and policies:
AdminController: {
adminDashboard: 'isAuthenticated',
},
ItemController: {
findOne: 'isPublishedOrIsAuthenticated'
}
api/policies/isAuthenticated.js and api/policies/isPublished.js and any other policy you want to use as a part of an AND/OR check:
If next was set to the true boolean (as opposed to a callback), just return true or false before the policy would normally return next(), res.notFound(), etc.
module.exports = function(req, res, next) {
// do some checking
if(next === true) return true; // or return false
return next();
};
Note that we need to use the triple-equals sign here.
api/policies/isPublishedOrIsAuthenticated.js
module.exports = function(req, res, next) {
var isPublished = require('./isPublished.js');
var isAuthenticated = require('./isAuthenticated.js');
// This reads like what we are trying to achieve!
// The third argument in each call tells the function to return a boolean
if(isPublished(req, res, true) || isAuthenticated(req, res, true))
return next();
return res.notFound();
};