Callum Kerr

“There is no place I know,
like the world of pure imagination.”



Email me  About me  


< All Posts

Building a Node Server (Session 3)

Loading Events from the Google Calendar API

Following from the last session, we set to work to pull our information about upcoming events from the Google Calendar API. We need to make a call to the Events: List endpoint.

When trying something new, it's often a good idea to start with the simplest thing that could possibly work. So in this case, we started with a blocking (synchronous) call, using the http-sync library (not the httpsync library, which apparently doesn't support https://).

# in the terminal:
    npm install http-sync
    
// in serve.js
    var httpsync = require("http-sync"),
        moment = require("moment");
    
    function getCalendarEvents() {
        var gCalID = "0u9nj9urhs8887sla430apcqfc@group.calendar.google.com",
        options = {
            protocol: 'https',
            host: 'www.googleapis.com',
            path: '/calendar/v3/calendars/'+gCalID+'/events'
        },
            request = httpsync.request( options ),
            response = request.end()
    
        return formatEvents(response.body.toJSON())
    }
    
    // Extract just the data that we need from google's response
    function formatEvents(json) {
        var results = []
        // loop over the items array
        json.items.forEach(function(item) {
            // and collect the data that we need
            results.push(
                {
                  time: moment(item.start.dateTime).format('MMMM Do YYYY, h:mm a'),
                  description: item.description
                }
            )
        });
        return results;
    }
    

We're using the moment.js library to format the time stamp.

After a little trial-and-error and some fumbling, we made contact to the google server, which gave us an 'error' response, we'd exceeded our daily request limit. Odd... "The Google Calendar API has a courtesy limit of 1,000,000 queries per day." I can only assume that with the application running on localhost, it will identify as such when making the request, and get lumped in with all the other localhost servers making google API requests in the world.

So in practice, you'll probably need to follow the directions to get an API key (or run the server on a public IP address). Then you will add the key to the path above like so:

{
        //...
        path: '/calendar/v3/calendars/0u9nj9urhs8887sla430apcqfc@group.calendar.google.com/events?key=YOUR_API_KEY'
        //...
    }
    

With the API key, the request worked, and returned our event data. Hooray!

Now to refactor.

Making a synchronous request like this will mean that any clients (users) connecting to our site will have to wait for that http request to succeed before they recieve any data from the server. Factor in a network downtime and our users will be left wondering. So let's convert to an asynchronous request, cache the events data in a variable, and query the google API periodically, serving only slightly stale data.

// in serve.js
    
    var https = require("https");
    
    function getCalendarEvents() {
        var result = "",
        options = {
            host: 'www.googleapis.com',
            path: '/calendar/v3/calendars/0u9nj9urhs8887sla430apcqfc@group.calendar.google.com/events'
        },
        callback = function(response) {
            //response is a stream
            response.on("data", function(data) {
                //collect data as it comes in
                result += data
            }).on("end", function() {
                global.events = formatEvents(JSON.parse(result))
            })
        }
        request = https.request( options , callback ),
        response = request.end()
    }
    

As you check out the full updated source code, you can see that we're calling getCalendarEvents before the server first starts, then periodically (every 15 minutes) through a call to setInterval. It also gets called when any request comes in. Because it's asynchronous, it won't serve that updated response to the user in that request, but will ensure that it's up-to-date for the next request that comes in.

Obviously, this is still a naïve implementation of caching, but it's a start ;)

Next session, let's look at WebSockets, through SockJS or Socket.io, to provide always-up-to-date event information.

Thanks for attending, and/or reading this :) Comments below!

< Part 2