I am building a node.js app that will upload files to my S3 bucket using knox. I am able to interact with S3 as expected, but I would like to make my controller to receive configuration so I can dynamically construct my client with configuration values.
My questions is how do I get configuration paramters down the call stack to my controller without being careless?
Disclaimer: I am rather new to Node.js so it could be simply my lack of knowledge in the difference between exports. and module.exports.*
Here is an example of how the interaction works with my code:
app.js
...
config = require('./config/config')['env'];
require('./config/router')(app, config);
...
router.js
module.exports = function(app, config) {
...
var controller = require('../app/controllers/home'); //Is there a way for me to pass config here?
app.post('/upload', controller.upload); //Or here?
...
}
home.js
var knox = require('knox');
var client = knox.createClient({ ... }); //I want to use config.key, config.secret, etc instead of hard-coded values
...
exports.upload = function(req, res) {
//Use client
}
...
Try doing something like this...
var config = require('./config/config')['env'];
// The use function will be called before your
// action, because it is registered first.
app.use(function (req, res, next) {
// Assign the config to the req object
req.config = config;
// Call the next function in the pipeline (your controller actions).
return next();
});
// After app.use you register your controller action
app.post('/upload', controller.upload);
And then in your controller action...
exports.upload = function(req, res) {
//Your config should be here...
console.log(req.config);
}
Ps. I can not try it right now, but I solved a similar issue like this.
You can pass the configuration in as a parameter to you controller
Controller
// controller.js file
module.exports = function(req, res, config) {
console.log('config parameter passed to controller', config);
res.end('config passed')
}
App
// index.js file with the express app
var controller = require('./controller');
var config = {
key1: 'foo'
};
var express = require('express');
var app = express();
var port = 3000;
app.get('/', function(req, res){
controller(req, res, config);
});
app.listen(port);
console.log('app listening on port', 3000);
Demo
You can check out the github repo for a complete example
Alternative approach if you want to call multiple functions from one single route, this will do it.
Route
var users = require('../controllers/users');
app.route('/login').post(function(req, res){
if(users.authenticate()){
console.log('valid user');
if(users.createUser())
{
console.log('user created');
}
}
});
Controller
exports.authenticate = function(req, res, next) {
return true;
};
exports.createUser = function(req, res, next) {
return true;
};
Related
I am sending json by POST to nodejs, I declared router.post in index.js, (/routes)
How I can save it so I can actually use that later on? Keep in mind that every 60sec I am getting new data that should replace the old one.
I am listening on port 3000
var express = require('express');
var router = express.Router();
var saveme
/* GET home page. */
router.get('/index', function(req, res, next) {
res.render('index', { title: 'RLH' });
});
router.post('/index', function(req, res, next) {
data = req.body;
console.log('OK')
});
module.exports = router;
I don't know how can I save what I get trough POST, so later on I can use it on my website.
There are multiple ways to use Global variable:
Method1
Using app.locals :
declare app.locals.data = {}; in main file (ex:server.js)
var app = express();
app.locals.data = {};
app.locals available to req object as req.app.locals. When you have new data you can update it as :
req.app.locals.data = req.body;
Method2
Using global object
Assign new data as global.data = req.body
You can always access data as global.data in same or different module
Method3(Recommended)
Create file globaldata.js with below code
module.exports = {};
Import globaldata.js where you need to access or update global data as
var globaldata = require('./globaldata.js');
globaldata = req.body;
What is recommended? global method for small apps, module.exports for big apps.
You can read below ref. for more details:
https://www.hacksparrow.com/nodejs/global-variables-in-node-js.html
http://expressjs.com/en/api.html#app.locals
If by saving the data you mean storing it in a variable you can do:
var express = require('express');
var router = express.Router();
var saveme;
/* GET home page. */
router.get('/index', function(req, res, next) {
if (saveme) {
// you can use `saveme`
res.render('index' + saveme.toString(), { title: 'RLH' });
}
else {
res.render('index', { title: 'RLH' });
}
});
router.post('/index', function(req, res, next) {
data = req.body;
// set `saveme`
saveme = data;
});
module.exports = router;
I want to apply a particular middleware function to the two post requests but not the get request. How could I do this?
var router = express.Router();
var app = express();
router.post('/jobs',(req,resp)=>{
var messageString = JSON.stringify(req.body);
Job.accept(messageString,(statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
router.get('/jobs',(req,resp)=>{
Job.status((statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
router.post('/try',(req,resp)=>{
var messageString = JSON.stringify(req.body);
Job.ok(messageString,(statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
I was reading about app.use, but couldn't really understand its usage.
Add the middleware you want to the function. Here is an example where I log the users IP
const myLogger = (req, res, next) => {
console.log('got a request from', req.connection.remoteAddress);
next();
}
app.post('/jobs', myLogger, (req, res) => {
//your code here...
}
Along with the answer mentioned above, write app.use(myLogger)
I am building an API backend with Express (v4) and facing an issue that my middleware function is not called
on sub-paths of my route. E.g. it is called for /movie but not for /movie/search.
I have split my routes into separate files. Below is the code, shortened to the relevant parts.
Any help is appreciated!
app.js
var express = require('express');
var app = express();
var router = require('routes')(app);
/routes/index.js
module.exports = function(app) {
app.use('/movie', check_authentication, require('movie'));
};
/routes/movie.js
var Movie = require(../models/movie');
// Middleware is working for this route (/movie?movie_id=123)
router.get('/', function(req, res) {
Movie.findById(req.query.movie_id)
.then(function(movie) {
res.status(200).json(movie);
}, function(err) {
res.status(400).send(err);
});
});
// Middleware is NOT working for this route (/movie/search?keyword=matrix)
router.get('/search', function(req, res) {
Movie.findById(req.query.keyword)
.then(function(movie) {
res.status(200).json(movie);
}, function(err) {
res.status(400).send(err);
});
});
/routes/check_authentication.js
var express = require('express');
var router = express.Router();
var firebaseAdmin = require('firebase-admin');
var path = require('path');
var config = require(path.resolve(__dirname, '../config/config.json'));
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(path.resolve(__dirname, '../config/' + config.firebase.serviceAccount)),
databaseURL: config.firebase.databaseURL
});
// AUTHENTICATION MIDDLEWARE
// needs to be included in any request which requires authorization
// =============================================================================
router.all('/', function(req, res, next) {
// check if authorization header is present
var token = req.headers['authorization'];
if (typeof token === 'undefined') {
res.status(403).json({ Error: 'Unauthenticated' });
}
else {
firebaseAdmin.auth().verifyIdToken(token).then(function(decodedToken) {
req.email = decodedToken.email;
next(); // all good. go ahead with the request
}).catch(function(error) {
res.status(403).json({ Error: 'Unauthenticated' });
});
}
});
module.exports = router;
It seems I found the problem.
Changing the middleware to trigger on * fixes it.
router.all('*', function(req, res, next)
Maybe someone can confirm that this is the way to go.
The check_authentication module should export the middleware function, not a router.
module.exports = function(req, res, next) {
// check if authorization header is present
// ...
});
Would like to know a "good" way of sharing a variable for the following scenario.
My server.js file includes an authenticator.js file like so:
var authenticator = require('./server/services/authenticator')(app);
app.use(authenticator);
Within the authenticator.js file there is a variable called privateKey:
module.exports = function (app) {
var authenticator = function (req, res, next) {
//do some stuff here
var privateKey = 'value from Basic Auth header'
};
return authenticator;
};
My api.js file now needs this privateKey variable.
I include the api.js file from my server.js in the same way:
var api = require('./server/api')(app);
app.use('/v1', api);
and I would like to pass the privateKey too using something like:
var api = require('./server/api')(app, privateKey);
QUESTION: How can I make privateKey available in my server.js file so that I can pass it to the api.js file?
You could attach it to the req variable
module.exports = function(app) {
var authenticator = function(req, res, next) {
//do some stuff here
req.privateKey = 'value from Basic Auth header'; //This can be shared accross middlewares.
next(); //don't forget to call this.
};
return authenticator;
};
server.js
var api = require('./server/api')(app);
app.use('/v1', api);
api.js
module.exports = function(api) {
var api = function(req, res, next) {
var privateKey = req.privateKey; //this is how we can use it
//do something with it
next();
};
return api;
};
}
I am getting my hands on node.js and I am trying to understand the whole require/exports thing. I have the following main app.js file:
/app.js
var express = require('express'),
http = require('http'),
redis = require('redis'),
routes = require('./routes'),
var app = express(),
client = redis.createClient();
// some more stuff here...
// and my routes
app.get('/', routes.index);
then, I have the routes file:
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
I can of course use the client object on my app.js file, but how can I use the same object in my routes?
Since req and res are already being passed around by Express, you can attach client to one or both in a custom middleware:
app.use(function (req, res, next) {
req.client = res.client = client;
next();
});
Note that order does matter with middleware, so this will need to be before app.use(app.router);.
But, then you can access the client within any route handlers:
exports.index = function(req, res){
req.client.get(..., function (err, ...) {
res.render('index', { title: 'Express' });
});
};
The easiest way is to export a function from your routes file that takes a client, and returns an object with your routes:
exports = module.exports = function (client) {
return {
index: function (req, res) {
// use client here, as needed
res.render('index', { title: 'Express' });
}
};
};
Then from app.js:
var client = redis.createClient(),
routes = require('./routes')(client);