Building a Timestamp Microservice

Photo by Lum3n.com from Pexels

Around two months ago I was determined to learn backend development, and so I deep my toe in it with some help of Programming for the Web with JavaScript course. It’s a very good course, though at that time I quickly began to get uninterested in videos and quizzes. Now, my college is beginning to ask for real programming projects involving backend and database solutions, and I felt that leaving that course was not the best idea. Anyway, I thought this fCC project may be a good first hands-on experience with backend development. And it was.

It basically consist of an api which will request a date under the form of unix timestamp or a normal English date; you send it one and returns a calculated form of the other back to you. As you’ll need to set up a server, create a module that accepts an api request (as /api/timestamp/) and returns an appropriate JSON object including the date in both formats: This project is one of the best to learn how a web server AND an API works “under the hood”.

First thing’s first — App architecture

I tried to follow some nice tutorials I found of this topic (all of them are in the notes section) and as I wanted to keep the structure a bit “professional” I create the following:

.
├── routes
│ └── routes.js
├── services
│ └── timestamp.js
├── public
│ ├── favicon
│ ├── styles
│ └── main.css
├── views
│ └── index.html
├──
package.json
├── README.md
└── app.js

The views — or the front page

No templates, jsx, libraries, etc. Just a simple ol’ html file.

<!DOCTYPE html>
<html>
<head>
<title>Timestamp microservice</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width;initial-scale=1.0">
<link rel="icon" type="image/png" size="32x32" href="favicon/favicon-32x32.png">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="stylesheet" href="styles/main.css">
</head>
<body>
<section class="container">
<h1>Timestamp microservice</h1>
<h2>Example usage</h2>
<ul>
<li>
<a href="/api/timestamp/2018-08-02">jesuodz-timestamp.glitch.me/api/timestamp/2018-08-02</a>
</li>
<li>
<a href="/api/timestamp/1533227498">jesuodz-timestamp.glitch.me/api/timestamp/1533227498</a>
</li>
<li>
<a href="/api/timestamp/">jesuodz-timestamp.glitch.me/api/timestamp/</a>
</li>
</ul>
<h2>Output</h2>
<div class="output-example">
<code>
{"unix":1533168000,"utc":"Thu, 02 Aug 2018 00:00:00 GMT"}
<br>
{"unix":1533227498,"utc":"Thu, 02 Aug 2018 16:31:38 GMT"}
<br>
{"unix":1533240424,"utc":"Thu, 02 Aug 2018 20:07:04 GMT"}
</code>
</div>
</section>
</body>
</html>

The service

This is the section of our app that will do our calculations. I’m using moment.js and the module pattern to build a neat module.

const moment = require('moment');
const timestamp = { parser : null };
let processed = {
"unix": "error",
"utc": "Invalid value"
};
const formatUTC = function(momentObj) {
return momentObj.format('ddd, DD MMM YYYY HH:mm:ss') + ' GMT';
}
timestamp.parser = (request, response) => {
const value = request.params.query;
// Handle an empty date string
if (Object.keys(request.params).length == 0) {
let now = moment().utc();
processed.unix = now.unix();
processed.utc = formatUTC(now);
response.send(processed);
return;
}
if (isNaN(+value) && moment(value, 'YYYY-MM-DD', true).isValid()) {
processed.unix = moment.utc(value).unix();
processed.utc = formatUTC(moment(value));
} else if (!isNaN(+value)) {
processed.unix = +value;
processed.utc = formatUTC(moment.utc(moment.unix(+value)));
} else {
response.json({"error" : "Invalid value"});
return;
}
response.send(processed);
}
module.exports = timestamp;

Remember that conversions from and to unix timestamp are always made in local timezone but fCC user stories said that them should be made in UTC timezone. Moment makes that easier to deal with.

The routes

const router = require('express').Router();
const timestamp = require('../service/timestamp.js');
// Handle routes
router.route('/api/timestamp/').get(timestamp.parser);
router.route('/api/timestamp/:query').get(timestamp.parser);
// Main page
router.get('/', (request, response) => {
response.sendFile('index.html', { root: './views/' });
});
module.exports = router;

At this moment, routing is the most difficult concept to understand for me. It looks counterproductive to me I can’t redirect all-non api requests to the front page, and the only fix I found was to add another handler for those request in the server file.

The server

Okay, every express tutorial must explain what app.listen(); do but, you know this is not a tutorial and there are plenty of them out there, so I’m keeping things simple and I’ll what are the peeks of this block of code: first I’m importing the routes (all the routing stuff deserve their own file), then I use express.static('public') to serve all static content like css and favicons.

After that, we handle all routes with app.use so our server knows where to send “/api” request and “/” goes to the home page. Also I said before all requests are processed here as 404 errors, here is defined as app.use('*', function); .

const express = require('express');
const app = express();
const routes = require('./routes/index.js');
// Serve public files
app.use(express.static('public'));
// Handle routes
app.use('/api/', routes);
app.use('/', routes);
app.use('*', (request, response) => {
response.send("404 — File not found");
});
// Create and start the server
const port = process.env.PORT || '3000';
app.listen(port, () => {
console.log(`Listening on localhost:${port}`);
});

Lastly, we fired up the server setting it with any or the default port (process.env.PORT || '3000'); ).

Some notes aside

This project was a very good introduction to building a node/express app. Although I still don’t know clearly how routing works, I think it’s still a success (maybe?).

See you the next time!