Dynamic configuration file in Nodejs and Express - javascript

I am working with NodeJs with expressjs and I would like to use a middleware that will read a variable from dynamic configuration file before each request (some js file that holds an object that I can change manually while the server is running).
I would like to store a flag that will close down all requests (i.e send response without proceeding to next routes) until I change the variable value to true and then the middleware will call next() so all routes will work.
I prefer to avoid shutting down the server for that, and I also don't want to store this variable in a database...
Is there something similar to what I need?
Thanks

You will read config.json file each time, if you just put it inside function. If you will use require('config.json), then you will read this file only once on start.
var fs = require("fs");
function (req,res,next) {
var config = fs.readFileSync('./config.json');
config = JSON.parse(config.toString());
if (config.registrationStatus === "open") {
next();
} else {
res.send("registration closed");
}
}

Check supervisor: https://github.com/petruisfan/node-supervisor
It will watch for file changes and crashes and will restart your application each time.
You will get much better performance.

Related

Express with JSON Data Control

I use lowDB dependency to control the JSON Data with Express and actually it works. But there is a bug and I cannot find how to solve it.
I create /create page to add information in JSON file and it contains 4 form and submit button.
And In express I code like this. each forms data will save it in variable and push with lowdb module.
router.post('/post', function (req, res) {
let pjName = req.body.projectName;
let pjURL = req.body.projectURL;
let pjtExplanation = req.body.projectExplanation;
let pjImgURL = req.body.projectImgURL;
console.log(pjName);
db.get('project').push({
name: pjName,
url: pjURL,
explanation: pjtExplanation,
imgurl: pjImgURL
}).write();
console.log(db.get('project'));
console.log(db.get('project').value());
res.redirect('/');
})
And it works well. But when I modify the JSON file myself (ex. reset the JSON file) and execute again. It shows the data that I reset before. I think in this app somewhere saves the all data and show save it in array again.
And When I shutdown the app in CMD and execute again, the Array is initialized.
As you may already know the lowdb persist the data into your secondary memory (hdd), and may return a promise depending on your environment when you call write method.As mentioned in the doc
Persists database using adapter.write (depending on the adapter, may return a promise).
So the data may be still getting write when you read them, so the old data is queried. Try this,
db.get('project').push({
name: pjName,
url: pjURL,
explanation: pjtExplanation,
imgurl: pjImgURL
}).write().then(() => {
console.log(db.get('project'));
console.log(db.get('project').value());
});

Socket.io: io is not defined

So, I am trying to get data on my node.js file instead of directly getting it on my JS file.
I a using Socket.io 2 here, Below is a snapshot of my code and this is also the first time I am using Websocket with Node.
I am doing something like
var socket = require('socket.io')
//Home Page
app.get("/", function(req, res) {
var cryto = io.connect("https://xyfz.com/);
cryto.on('trades', function (tradeMsg) {
console.log(tradeMsg);
});
res.render("index");
});
I also tried something like
var io = socket("https://abc.io/");
and
var socket = require('socket.io')
var io = socket();
which was throwing errors like server.listeners is not a function and io.connect is not a function.
I am certain that I messing up stuff here so can someone guide me about the correct way of doing it?
Two things which are wrong .
First Consider using Socket.io-client instead of Socket.io.
Second and very much important.
Never ever make API calls inside your routes. This will trigger a API call everytime user opens your website or webpage
You can also expect an error "Unexpected headers" or something like that.
Always, Try do declare it outside any routes in your NodeAPP.
Same goes for socket.io as well

nedb post data appears only after restart

So basically I wrote a simple API where you can perform http POST and http GET on a nedb.
My problem however is, that after posting an entry (customer), the entry appears in the nedb file but when I use the GET method it isn't returned.
However after restarting the API it works as expected and the expected data is returned. But why does it have to restart in order to "refresh" the data?
Get-Function:
const db = new Datastore({filename: __dirname + '/db.dat', autoload:true});
export function getAll(req: Request, res:Response, next: Next):void{
db.find({}, (err, customers) => {
res.send(customers);
});
next();
}
In situations where you get weird errors or something strange is not working with nedb and you cannot figure out what's wrong, try to delete the .dat file and try again.
Often you accidentally modify the nedb file (e.g. with autosave of your editor) and you corrupt it.

NodeJS Modulization

So, I was told that passing around the request and or response variable in nodeJS is "bad practice". But this means that most of your code has to be in the server.js file, making it cluttered and kind of ugly.
How can you modularize your nodejs server, passing around req/res appropriately and be able to organize your code into separate files?
For example, I would like to split my socket routing, .get and .post into different files, but still be able to use the callback parameters like so:
app.io.route("disconnect", function(req,res) { <--- these params
db.query("UPDATE player_data SET online=0 WHERE id="+mysql.escape(req.session.user));
req.io.broadcast("event", {msg:req.session.username+" has logged out!"});
app.io.broadcast("reloadXY");
});
As of right now they're all in one file and I don't like that.
I think what the person meant by 'passing around' was something like this (in plain express):
app.get('/kittens', function(req, res) {
db.doAthing(req);
updateSomethingElse(res);
upvoteThisAnswer(res);
});
That is, passing around the two variables beyond the first function. This is bad because it becomes increasingly difficult to figure out where the call actually ends. One little res.end(500) in updateSomethingElse can cause the whole house of cards to come tumbling down.
It's perfectly ok (in fact, standard to the point of being the default in express) to declare that callback elsewhere (usually the /routes directory of your project.)
// app.js
var user = require('./routes/user')
, kittens = require('./routes/kittens');
// express stuff...
app.get('/settings', user.getSettings);
app.get('/fur', kittens.shed);
Then, in routes/user.js:
exports.getSettings = function(req, res) {
// Note how we're passing around properties of req/res, not the objects themselves.
db.getUserSettings(req.user.id).then(function(settings) {
res.render('settings', settings);
});
};
This video from TJ Holowaychuk (the guy who wrote Express and a ton of other Node infrastructure that we all use) helped me take Express modularization to the next level. Basically you can make individual apps in their own folders and consume them as middleware very easily. I have managed to extend this technique to socket.io with some tricks.
http://vimeo.com/56166857
You should not pass req and res to another modules but pass callbacks from another modules to route.
It should look like.
var someModule = require("./someModule")
app.get("/someAction", someModule.handleSomeAction) ;
If You want to have post and get in another modules You should pass reference to app (from express()) once to that module and operate on that.
For example :
var express = require("express") ;
var app = express();
var get_handler = require("./get_handler ")
var post_handler = require("./post_handler ")
get_handler.init(app);
post_handler.init(app);
and in post/get_handler :
var app;
exports.init = function( eApp){
app = eApp;
// operate on app
}

Node.js Express.js | Automatically render handelbar templates from views/static folder

I have got the following code to automatically load my handelbar templates from the views/static folder without having to manually setup a route for each page.
app.get("/:template", function(req,res){
var template = req.params.template; // Is this safe?
res.render("static/" + template, function(err, html) {
if (err) {
res.send(404, 'Sorry cant find that!');
} else {
res.send(html);
}
});
});
It works fine, however I am worried that this potentially exposes my app to security problems. Any suggestions how I could do this better. I am using Express. Thanks so much for your help.
I think it's pretty safe.
Usually, you have to worry about paths being passed that contain stuff like ../ (to go back a directory level), but those won't match your route. Also, the route you declare will stop matching at a /, so requests like /foo/../bar won't match either.
An issue that may occur is when the static directory contains files that you don't want to expose: a request for /secret.js will at least try to render a file called static/secret.js.

Categories