TimeStamp Service: Exploring the wonderful World of Node.js
As part of the back end certification from Freecodecamp, I am making a timestamp service. Since, Freecodecamp is “under construction” I had to learn a lot of things myself.
I am using Webstorm on my mac Sirera with Node 6.9.1.
I have done the modules on Freecodecamp using learnyounode to learn the basics of node. One of the lessons on learnyounode was taking a time input and parsing it out into two json objects with natural and unix time objects respectively.
My first move was to create an http server using node.
var http = require('http');
var url = require('url');
var port = process.env.PORT || 3000;
var express = require('express');
var app = express();
var server = http.createServer(function (req,res) {
});
server.listen(Number(port));
Then, I tried to find out how to get the the argument from the url:
The time I am meant to parse will be given in in url in this form:
https://timestamp-ms.herokuapp.com/December%2015,%202015
So I ask Mr.Google and I stumbled upon this useful chart on how the requests are parsed when you use ulr.parse from node:
Realizing that I need the pathname of the request, I checked it just to make sure.
var http = require('http');
var url = require('url');
var port = process.env.PORT || 3000;
var express = require('express');
var app = express();
var server = http.createServer(function (req,res) {
var data = url.parse(req.url,true);
var userinput = data['pathname'];
res.end(userinput['pathname'])
});
server.listen(Number(port));
It worked! Woooooooooooooot!
But my output was ugly.
/December%2015,%202015
I needed to clean it up. I split the string into an array, shift()-ed the ‘/’ off, and replaced “%20” with spaces.
This is the result:
December 15, 2015
This, I can put into my Date.parse() function and return a unix timestamp
var http = require('http');
var url = require('url');
var port = process.env.PORT || 3000;
var express = require('express');
var app = express();
var server = http.createServer(function (req,res) {
var data = url.parse(req.url,true);
re = /%20/g;
var userinput = data['pathname'];
userinput = userinput.replace(re," ");
userinput = userinput.toString();
userinput =userinput.split("");
userinput.shift();
userinput = userinput.join("");
var date = new Date(userinput);
var timestamp = Date.parse(userinput);
var unixjs = {
"unixtime": Math.floor(date.getTime())
};
res.end(timestamp.toString())
});
server.listen(Number(port), function () {
console.log("app is listening on" +port)
});
n.b.: The timestamp variable will be a buffer so you must turn it into a string with the toString() function.
At this point, some of you might be thinking, “why doesn’t she just use express?”. Well…
I quickly turned the http.create server into an express server by installing express, requiring it, and creating an instance of it called app.
With the app instance, I exchanged the var server = http.createServer
line with app.use
and then replaced the server listener at the bottom with app.listen.
After this, I looked up a way to figure out if the input was a date. I used moments for this because it has a verify function that returns a boolean. This is great for if statements because I have to treat the input differently depending on the format.
var http = require('http');
var url = require('url');
var port = process.env.PORT || 3000;
var express = require('express');
var moment = require('moment');
var m = moment();
var app = express();
var path = '/Users/DragonQueen/WebstormProjects/timestampservice/';app.use(function (req,res) {
var data = url.parse(req.url,true);
re = /%20/g;
var userinput = data['pathname'];
userinput = userinput.replace(re," ");
userinput = userinput.toString();
userinput =userinput.split("");
userinput.shift();
userinput = userinput.join("");
if (userinput !== ""){
var date = new Date(userinput);
var output = {};
if (moment.unix(userinput).isValid() == true){
var unx = moment.unix(userinput);
output['unix'] = parseInt(userinput);
output['natural'] = unx.format('MMMM Do YYYY');
}
else if (moment(userinput).isValid() == true){
var unx = moment(date);
output['unix'] = parseInt(date.getTime()/1000);
output['natural'] = unx.format('MMMM Do YYYY');
}
else{
output['unix'] = null;
output['natural'] = null;
}
res.end(JSON.stringify(output))}
});
This worked wonderfully but I wanted a “home” screen so I created a pug (I have never used it and I wanted to experiment). For this, I had to create another app instance but this time it was an app.get. In that, I set the path for my pug template and just put in some simple text and the current date.
Then I had a second though about the pug. It worked but I felt a bit cocky. I made a simple HTML file that had the information about my app in markdown notation and used the Marked package to transform it. I also changed the font for it to look nicer but since the app is not very elaborate, I just went with simple text explanation (static file).
Now, I want to go ahead and deploy on Heroku.
All this time, I used Webstorm. Webstorm is great but using the built in terminal is annoying so I did all the terminal work in the terminal native to my mac.
I know NOTHING about Heroku so I went here. They have a tutorial for how to get started. I went through the tutorial and I still couldn’t quite get a clear picture in my head of what was happening so I went here. This is a node specific walk through. I went through all the steps on the page and fixed any problems as they arrive. I read the errors very carefully.
One thing to note with node is that you cannot use control z
to kill the process. This will only suspend the process and that port will continue to be used by the program. You must use control c
this will kill the program. If you are like me, and used to using z to terminate processes, you can go into your terminal and type in:
ps aux | grep node
and you will get a list that looks like this:
the first numbered column is called the process id number or the PID.
you can use the kill -9
tag followed by the PID to kill the process that is running on that port.
To kill my node index.js process, I needed to use:
kill -9 18515
That’s all! But it is a pain to do all the time.
While I was trying to actually deploy the app, I can into a problem. The
git push heroku master
command was trying to push to a repo for a project I had deleted so I needed to remove that repo and put the new one as the master. I did that with the commands I found here. It is the answer by Gonzalo S.
I don’t know about the setup that others have, but even though I have root access on my mac, I have to use sudo every time the command has Heroku in it. I don’t know why.
This is what the home screen of my app looks like
What I learned:
- use control c
- the terminal is your friend
- play with different packages butt…
- try not to mess with the package.json directly
Then I just finished the step-by-step guide and put my app on Heroku. The finished app can be found here:
and the github repo can be found here:
I will be putting this on the portfolio on my website soon.
P.S:
While attempting to put another app on Heroku, I ran into a strange problem. It kept saying the repo I wanted either didn’t exist or that I did not have permission. So I did more research and found another Stackoverflow post that solved this problem. It is the answer by Joost Schuur. I took a screen shot:
hopefully, this can help someone down the line.