Express redirect based off URL - node.js

I'm using Express & Node.js.
router.get('/:year?/:month?/:day?', function(req, res) {
var date = moment();
if (req.params.year && req.params.month && req.params.day) {
var dateString = req.params.year + " " + req.params.month + " " + req.params.day;
var tempDate = moment(dateString, "DD MM YYYY");
if (tempDate.isValid()) {
date = tempDate;
}
}
.catch(function (err) {
console.error(err);
res.send("Error");
});
});
The above isn't my full code for my route. But I need some pointers. I'm using Moment.js(http://momentjs.com/) to grab the current date, format it and pass it through the url in the route.get request.
However, I don't want the user to be able to go to a past date. So if the date has already been and the user tries to navigate too it I want to redirect them back to the current date.
.then (function(){
var pastDate = function(req, res) {
if (req.query.[pastDate]) {
res.redirect('/');
} else {}
}
})
I don't think the the syntax is correct. But not sure if i'm looking on the right lines in how I'd do this.
Thanks for help.

I looked through your code and it looks really inconsisten and I don't fully understand what you're trying to do, but you can probably narrow it down to something like this:
router.get('/:year?/:month?/:day?', function (req, res) {
var year = req.params.year;
var month = req.params.month;
var day = req.params.day;
if (year && month && day) {
var requestDate = moment(day + ' ' + month + ' ' + year);
var today = moment();
if (requestDate.isValid() && !requestDate.isBefore(today)) {
// All set and valid, do stuff with the request
} else {
// Invalid date or the requested date is before today
// Redirecting to /year/month/day of this day, e.g /2015/04/31
return res.redirect('/' + today.year() + '/' + today.month() + '/' + today.date());
}
}
});
Moment has an isBefore method that is really handy for these kind of tasks.
You should use a bit more variables in your code so it's easier to work with! :)

You should be able to just do a less than comparison.
var goodDate = function() {
var now = moment();
if (this < now) {
return false
}
return true
}

Related

How to get data for the current day?

How to get the total number of records for the current day? I get 0 as a result, although I have a couple of entries.
module.exports.getOnline = async function (req, res) {
try {
var current_date = new Date().toISOString()
const online = await Online.find({ Date: current_date })
res.status(200).json(online.length)
} catch (e) {
errorHandler(res, e)
}
}
I think that currently you are searching for records with a specific date and time. Try to look for a range of dates, with today at 00:00 and today at 23:59.
This one might help:
https://stackoverflow.com/a/2943685/12647796
edit - I tried to match it to your problem
var min_date = new Date();
var max_date = new Date();
min_date.setHours(0,0,0,0);
max_date.setHours(23,59,59,999);
const online = await Online.find({
Date: {
$gte: min_date,
$lt: max_date
}
})
res.status(200).json(online.length)
var current_date = new Date().toISOString()
The toISOString() method converts a Date object into a string, using the ISO standard.
The standard is called ISO-8601 and the format is: YYYY-MM-DDTHH:mm:ss.sssZ
so when you get the current date and using this method it will not match with the existing records in database.that's why query return 0.
if you want to get the current day records you need to use following code for getting current date,month and year than use it for query.
module.exports.getOnline = async function (req, res) {
try {
var d = new Date();
var date = d.getDate();
var month = d.getMonth() + 1; // Since getMonth() returns month from 0-11 not 1-12
var year = d.getFullYear();
var dateStr = date + "/" + month + "/" + year;
const online = await Online.find({ Date: dateStr })
res.status(200).json(online.length)
} catch (e) {
errorHandler(res, e)
}
}
I think this will help you.

Mongoose middleware function not returning expected result

I have created a pre-init middleware function that is meant to format a Date field in my schema.
StadiumSchema.pre('init', function(next, stadium) {
let date = new Date(stadium.built);
let built = date.getDate() + '/' + date.getMonth() + '/' + date.getFullYear();
stadium.built = built;
console.log(stadium);
console.log(built);
next();
});
Within the function, it does show that stadium.built has been changed. But outside of the function that value stadium.built has not changed.
The order of arguments in the callback function is different as far as i remember, like:
StadiumSchema.pre('init', function(stadium, next) {
let date = new Date(stadium.built);
let built = date.getDate() + '/' + date.getMonth() + '/' + date.getFullYear();
stadium.built = built;
console.log(stadium);
console.log(built);
next();
});
btw, if you're not doing anything async job here, so you can also make it sync, like:
StadiumSchema.pre('init', function(stadium) {
let date = new Date(stadium.built);
let built = date.getDate() + '/' + date.getMonth() + '/' + date.getFullYear();
stadium.built = built;
//console.log(stadium);
//console.log(built);
});
However, please refer the docs for more information.

NodeJS Script Runs on Local Machine but Not in Firebase Cloud Functions?

My script written in NodeJS connects to Firebase, checks my Firebase Database and even successfully sends notifications when results from my database return true... However, it only works when I run it from my local machine. I deploy it to Firebase and it will not work. Could someone please advise? Thank you.
I hate asking on here because I'm a newbie but I have spent hours tonight trying to find an answer...
INDEX.JS
// Firebase Functions
const functions = require('firebase-functions');
var admin = require("firebase-admin");
// Default admin firebase configuration
admin.initializeApp(functions.config().firebase);
// var serviceAccount = require("xxxxxx-80xxxxd-firebase-adminsdk- xxxxxxx.json");
var moment = require('moment');
var FCM = require('fcm-push');
var dateTime = require('node-datetime');
var serverKey = 'xxxxxxxxxxxxxpSELZBjQYwpZgmxxxxxxxxxxx';
var fcm = new FCM(serverKey);
//Initial function call:
exports.CheckDates = functions.https.onRequest((req, response) => {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("records");
var userToken = '';
var itemExpires = '';
var itemName = '';
var reminded = '';
var itemCount = 0;
var counter = 1;
var itemFoundCount = 0;
var dt = dateTime.create();
var formatted = dt.format('m-d-Y');
ref.once("value", function (recordsSnapshot) {
recordsSnapshot.forEach(function (recordsSnapshot) {
var mainKey = recordsSnapshot.key;
recordsSnapshot.forEach(function (child) {
var key = child.key;
var value = child.val();
if (key == 'Account') {
userToken = value.userToken;
}
if (key == 'Items') {
recordsSnapshot.child("Items").forEach(function (itemsSnapshot) {
counter++;
if (itemFoundCount === 0) {
itemFoundCount = itemsSnapshot.numChildren();
}
var itemsChildkey = itemsSnapshot.key;
var itemsChildvalue = itemsSnapshot.val();
itemExpires = itemsChildvalue.itemExpires;
itemName = itemsChildvalue.itemName;
reminded = itemsChildvalue.reminded;
moment().format('YYYY-MM-DD');
var currentDate = moment();
var otherTime = moment(reminded);
if (typeof reminded !== 'undefined') {
if (currentDate.diff(otherTime, 'days') >= 30) {
if (currentDate.diff(itemExpires, 'days') <= 90) {
itemCount++;
console.log("Expire date is less than " +
currentDate + " by 90 days = " + (currentDate.diff(otherTime, 'days') <=
90));
db.ref("records/" + mainKey + "/Items/" +
itemsChildkey + '/reminded').set(formatted);
}
}
} else {
itemCount++;
db.ref("records/" + mainKey + "/Items/" + itemsChildkey +
`enter code here`'/reminded').set(formatted);
}
if (counter == itemFoundCount && itemCount > 0) {
console.log(itemFoundCount);
var message = {
to: userToken, // required fill with device token or
topics
notification: {
title: 'Item Expire Notification',
body: itemCount + ' is about to expire.'
}
};
//callback style
fcm.send(message, function (err, response) {
if (err) {
console.log("Something has gone wrong!");
} else {
console.log("Successfully sent with response: ",
response);
}
});
itemCount = 0;
itemFoundCount = 0;
counter = 1;
}
});
}
});
});
});
response.send(200, "ok");
}) // END exports.CheckDates
Obviously, I remove the Exports.CheckDates lines when I run it locally but it wasn't showing up at all without the exports on Firebase's console. It returns warnings locally and on Firebase console but it works on one and not the other.
Please disregard this question. The script adds the date that the last time a notification was sent to the item's "Reminded" key in the database... this prevents notifications from going out every day for the same thing..
It ran on my local machine, and did it's job but I couldn't figure out why it wouldn't run again... well, ha! At least we know that part works.

Express redirect firebase can't set headers after they are sent

I am using nodejs express and firebase for my database. So what I am trying to do is upon user's post request, update firebase data and redirect user to another page. But I keep getting Error: Can't set headers after they are sent.
Here is my code in controller.js file:
app.post('/carpark', urlencodedParser, function(req,res){
req.session.carpark = req.body.carpark;
lotsRef.orderByChild('CarparkName').equalTo(req.session.carpark).on('value', function(snapshot){
for (var key in snapshot.val()) {
if (snapshot.val()[key]['Availability'] == true) {
firebase.database().ref('Lots/'+ key).update({'Availability': false });
res.redirect('checkin');
break;
}
}
});
EDITED:
app.post('/carpark', urlencodedParser, function(req,res){
req.session.carpark = req.body.carpark;
lotsRef.orderByChild('CarparkName').equalTo(req.session.carpark).on('value', function(snapshot){
for (var key in snapshot.val()) {
var allocatedtime = new Date().getHours() + ':' + (new Date().getMinutes() <10 ? '0' : '') + new Date().getMinutes() + ':' + (new Date().getSeconds() <10 ?'0' : '') + new Date().getSeconds();
req.session.key = key;
req.session.LotID = snapshot.val()[key]['LotID'];
req.session.AllocatedTime = allocatedtime;
req.session.SerialNum = snapshot.val()[key]['SerialNumber'];
var date = new Date().getFullYear() + "-" + (new Date().getMonth()+1) + "-" + new Date().getDate();
req.session.DateAllocated = date;
console.log(req.session);
firebase.database().ref('Lots/'+ req.session.key).update({'Availability': false });
break;
}
}
res.redirect('checkin');
});
The redirect should be moved outside For loop:
app.post('/carpark', urlencodedParser, function(req,res){
req.session.carpark = req.body.carpark;
lotsRef.orderByChild('CarparkName').equalTo(req.session.carpark).on('value', function(snapshot){
for (var key in snapshot.val()) {
if (snapshot.val()[key]['Availability'] == true) {
firebase.database().ref('Lots/'+ key).update({'Availability': false });
break;
}
}
res.redirect('checkin');
});
But this will redirect to 'checkin' irrespective of your if clause, so that depends on your scenario whether you want to redirect to some other page when the if clause is not true even once.

node.js writeFileSync

I'm trying to populate a database with pictures paths & names using Node.js.
What I am trying to do is the following :
- A function send a list of pictures as Base64 string.
- Another function receive this list, loop through it, convert it into picture and get the path back.
I'm pretty new to node.js so I might be doing something really stupid.
Here is the reception code :
app.post('/chatBot/moreinfo/create', function (req, res) {
returnList = '';
res.set('Content-Type', 'application/json');
//IF LIST IS NOT EMPTY
if (req.body.imgList.length !== 0) {
const imagePath = '/var/lib/SMImageBank/';
const regex = /^data:image\/(.*);.*$/i;
const listePicture = req.body.imgList;
// LOOPING INTO THE LIST
req.body.imgList.map ( function (element) {
const file = element;
const filetype = file.match(regex)[1];
var picLink2 = '';
const base64data = file.replace(/^data:image\/.*;base64,/, "");
const latin1data = new Buffer(base64data, 'base64').toString('latin1');
const filename = new Date().getTime() + '' + new Date().getMilliseconds() + "." + filetype;
fs.mkdir(imagePath, () => {
fs.writeFile(imagePath + filename, latin1data, "latin1", function (err, content) {
if (err) {
routerLog(req, {'type': 'error', 'content': err} );
res.sendStatus(500);
}
else {
if (process.env.NODE_ENV === "production")
picLink2 = 'http://****.fr/image/' + filename;
else if(process.env.NODE_ENV === "test")
picLink2 = 'http://dev.****.fr:8010/image/' + filename;
else if(process.env.NODE_ENV === "master")
picLink2 = 'http://dev.****.fr:8008/image/' + filename;
else{
picLink2 = 'http://*****.com:8008/image/' + filename;
}
}
});
})
console.log(picLink2);
returnList = returnList + ";" + picLink2;
});
}
MoreInfo.create(req.body, function (ret) {
res.send(ret);
routerLog(req);
})
});
What I want to do is to be able to access the variable "picLink2" from outside the writeFile & mkdir function so I can populate my returnList at each iteration. Obviously as node.js is asynchronous I can't access to picLink2 content from outside fs.writeFile() function. I know there has been a ton of question about this and lot of the answers are to put the code inside the writeFile()/readFile() function but I don't see how I can do it here since the writeFile() function is inside a map that is iterating into a list.
I'm new to the asynchronous world and I don't see how I can solve this problem.
Use writeFileSync for a synchronous operation if that doesn't hurt performance.

Resources