Building a simple API With Node.js & JavaScript Dates

In my effort to start working with Node.js, I recently completed the “learnyounode” tutorial. This is a workshopper module with a command line interface, available through NodeSchool.io and npm. Essentially, it teaches basic Node.js by providing 13 challenges of increasing difficulty, and a way of testing your solutions. After each challenge, it provides hints and links to documentation to help you figure out the information needed to solve the challenge. Unlike many other tutorial systems I’ve used, it doesn’t hold your hand through every detail. You have to do some research and thinking on your own, which I find much more effective for internalizing the information. The tutorial’s final challenge is creating an HTTP server and JSON API that manipulates an ISO date. In this article, I’m going to walk through understanding the requirements of the challenge and composing my solution. I’ll assume general familiarity with JavaScript, JSON, and HTTP.

Challenge #13 from “learnyounode”

Write an HTTP server that serves JSON data when it receives a GET request 
 to the path ‘/api/parsetime’. Expect the request to contain a query string 
 with a key ‘iso’ and an ISO-format time as the value. 
 
 For example: 
 
 /api/parsetime?iso=2013–08–10T12:10:15.474Z 
 
 The JSON response should contain only ‘hour’, ‘minute’ and ‘second’ 
 properties. For example: 
 
 { 
 “hour”: 14, 
 “minute”: 23, 
 “second”: 15 
 } 
 
 Add second endpoint for the path ‘/api/unixtime’ which accepts the same 
 query string but returns UNIX epoch time in milliseconds (the number of 
 milliseconds since 1 Jan 1970 00:00:00 UTC) under the property ‘unixtime’. 
 For example: 
 
 { “unixtime”: 1376136615474 } 
 
 Your server should listen on the port provided by the first argument to 
 your program.

Breaking down the challenge’s requirements

Before I start researching or typing code, I need to understand exactly what’s being asked of me. I need to take stock of which requirements I already know how to solve from prior challenges, and which requirements I need to research. Here’s how I broke down the challenge:

  1. We need to create an HTTP server that receives a GET request, a specific path, and an ISO-format time in the query string. The server needs to respond to these requests with a JSON string in a specific format.
  2. The HTTP request paths we are concerned with are: ‘/api/parsetime’ and ‘/api/unixtime’.
  3. The ISO-formatted date will be inside the query string, with the field name ‘iso’, such as: /api/parsetime?iso=2013–08–10T12:10:15.474Z
  4. If we receive the parsetime path, our JSON response will need to include the hour, minute, and second digits from the requested ISO date.
  5. If we receive the unixtime path, our JSON response will need to include the UNIX epoch time format of the requested ISO date.
  6. Our HTTP server must listen on the port number provided as the first command line argument to our program.

Building my solution

To address requirement #1, we need to create an HTTP server that responds to GET requests with a JSON string version of our output. To do this, we can use the Node http core module, the http.createServer function, and JSON.stringify(), which turns a JavaScript object into a JSON string.

var http = require(‘http’)
var server = http.createServer( function(request, response) {
if (response.method === ‘GET’) {
// server logic to build output
// then send our output in the http response
response.writeHead(200, {‘content-type’: ‘application/json’})
response.end(JSON.stringify(output));
}
}

To address requirements #2–3, we need to extract the path and the time from the requested URL. For this, we can use the Node url core module and the url.parse function, which parses the URL into a JavaScript object. Passing the second argument of true causes url.parse() to additionally parse the URL’s query string into object format, which will allow us to access the ISO time using parsedURL.query.iso. Lastly, we’ll create a new JavaScript Date object from the ISO-format string, so that we can work with the date and change it into other formats for our responses.

var url = require(‘url’)

and inside our createServer callback function:

var parsedURL = url.parse(request.url, true);
var path = parsedURL.pathname;
var date = new Date(parsedURL.query.iso);

To solve requirements #4–5, we’ll build our outputs as JavaScript objects in the required formats. To access the pieces and formats of the time that we need, we’ll use JavaScript’s built-in Date methods on our date object.

if (path === ‘/api/parsetime’) {
var output = { hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds()
};
} else if (path === ‘/api/unixtime’) {
var output = {unixtime: date.getTime()};
}

Lastly, for requirement #6, we need to tell the server to listen on the provided port number, which we can access from the process.argv array. Positions 0 and 1 are used by the system, so the first command line argument is in position 2.

server.listen(process.argv[2]);

Full Solution

var http = require(‘http’);
var url = require(‘url’);
var server = http.createServer(function(request, response) {
if (request.method === ‘GET’) {
var parsedURL = url.parse(request.url, true);
var path = parsedURL.pathname;
var date = new Date(parsedURL.query.iso);
if (path === ‘/api/parsetime’) {
var output = { hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds()
};
} else if (path === ‘/api/unixtime’) {
var output = {unixtime: date.getTime()};
}
if (output) {
response.writeHead(200, {‘content-type’: ‘application/json’});
response.end(JSON.stringify(output));
}
}
});
server.listen(process.argv[2]);

I found this tutorial very helpful for learning the basics of Node, and getting familiar with the most important structures and methods. For me, it was just the right balance of guidance and forcing me to learn on my own from Node.js and JavaScript documentation. Next, I’ll be moving on to the workshopper tutorials for learning Express.js, npm, and MongoDB!