FCC Speedrun — Timestamp Microservice
Today I jumped from the FCC Frontend to the FCC Backend in my quest to finish the Chingu FCC Speedrun Challenge speed run. Why? Frontend was getting tedious and I felt like mixing it up a bit to keep my progress rolling.
The project I tacked this time out is the Timestamp Microservice. Basically, it’s just a small api which will respond with a json object containing both a unix timestamp plus a normal English date if you pass it either — you send it one, it calculates the other and returns both back to you.
For me, this was a really simple application to throw together but I realize that there are others out there who are just getting their feet wet with Node.js so I’m going to put together a primer of sorts to help out anyone feeling a bit intimidated by this project.
First, some terminology I’ll be using throughout:
- Node.js — serverside JavaScript
- Express.js — nifty JavaScript for creating a web server in Node.js
- Moment.js — awesome library for manipulating dates
- Pug.js — templating engine (so our HTML can contain variables passed from our Express.js application)
Dissecting our problem:
To implement this app, we only need a tiny bit of code. We need code to:
- Spin up a Node/Express server to handle HTTP requests
- Create a module that accepts an api request consisting of a date in one of the two formats we expect, and returns an appropriate JSON object containing that date in both formats
- Route requests to that module
- Display an index page describing the app and how to use it
First, creating the server app:
This is pretty straightforward and quite similar to what you’ll find in any basic tutorial on Express. Leave me a note in the comments below if any of the following snippet doesn’t make sense. Basically, you just require express (because you’re making an express app) and http (because you want to spin up an http server to handle requests to your web page (so people can browse to it and use it). Then, you require a “routes” file (we’ll be creating this in a bit), setup “express.static” (which is really important otherwise your frontend code won’t be able to find your frontend css and JavaScript — which is a huge pain to debug — yes I know from experience).
Then, you “use” the routes from the routse file you requred (so your app will know where to send various requests “/” goes to the home page, “/api” will get routed to your serverside routes so the api request gets appropriately processed.
And, finally, you spin up the server :D
// Get dependencies
const express = require('express');
const http = require('http');
const app = express();// Get our API routes
const api = require('./routes/api');// Make sure our app can find our css and javascript frontend files
// which are located in the public folder
app.use(express.static('public'));// Route to the routes :D
app.use('/api/v1', api);
app.use('/api/', api);
app.use('/', api);// Enable pug (jade) for view rendering
app.set('view engine', 'pug');// Create the server and fire it up
const server = http.createServer(app);
const port = process.env.PORT || '3000';
app.set('port', port);
server.listen(port, () => console.log(`API running on localhost:${port}`));
Second, creating a module to process the timestamps:
You’re probably going to be pretty surprised at how easy moment.js makes this part. Seriously, take a look at the code below. Moment just takes the date and, bam, converts it.
If you’re wondering what the module.exports business is — You should really give You Don’t Know JS: ES6 & Beyond a read, Kyle does a great job explaining everything — much better than I have time or space to here.
const moment = require('moment');module.exports = {
parse: function (req, res) {
const date = req.params.query;
let processedDate = {
"unix": null,
"natural": null
}
if (+date >= 0) {
processedDate.unix = +date;
processedDate.natural = moment.unix(+date).format("MMMM D, YYYY")
}
if (isNaN(+date) && moment(date, "MMMM D, YYYY").isValid()) {
processedDate.unix = moment(date, "MMMM D, YYYY").format("X");
processedDate.natural = date;
}
res.send(processedDate);
}
}
Third, route the requests:
Here, we start off by requiring express, express’ router and the timestamp module we create above. Then it’s a simple matter of routing the api requests to our timestamp module and everything else to our frontend.
const express = require('express');
const router = express.Router();// modules this api provides routing for
const timestamp = require('../timestamp/timestamp');// TimeStamp Microservice Routes
// (note, catching a variety of urls and routing them to the same place)
router.route('/timestamp/api/v1/:query').get(timestamp.parse);
router.route('/timestamp/api/:query').get(timestamp.parse);
router.route('/timestamp/:query').get(timestamp.parse);// If it's not an api request, display the index page (found in frontend)
router.get('*', (req, res) => {
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
res.render('index.pug', {
fullUrl: fullUrl,
title: 'Timestamp Microservice'
});
});module.exports = router;
The final piece — an index page on the frontend:
Note: I used pug for this. You’re totally fine using any templating engine you want, or just plain HTML for that matter. I went with pug because “I like it”, I think it makes the HTML look a bit tidier, plus it lets me send data from the backend and just drop the variables into my HTML on the frontend — and it’s pretty simple to use.
doctype html
html
head
meta(charset='utf-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
title #{title} - FCC Speedrun
link(id='favicon', rel='icon', type='image/x-icon', href='https://cdn.gomix.com/6b38c407-645c-4cad-beea-3f7aaf616b9c%2Ffavicon.ico')
link(href='https://fonts.googleapis.com/css?family=Roboto', rel='stylesheet')
link(href='/main.css', rel='stylesheet')body
h1 Timestamp Microservice
h2 Example Usagep #{fullUrl}api/v1/timestamp/December%2015,%202015<br>
p #{fullUrl}api/v1/timestamp/1450137600h2 Example Output
p { "unix": 1450137600, "natural": "December 15, 2015" }
Note the use of #{fullUrl} and #{title} — those are the variables I passed to my index route in the serverside routing section above.
Notes:
- You can view the source code here
- You can see both the code and a live demo on GoMix.
- You can find Francesco Agnoletto (Kornil’s) amazing repository of favicons here.
- Another freeCodeCamper Jay Schwane wrote an amazing tutorial on Writing Modular JavaScript recently — it’s definitely worth a read and will make your ventures into the backend projects in FCC a lot smoother.
My progress in the Speedrun thusfar:
- Tribute Page
- Random Quote Machine
- Timestamp Microservice — this post