In addition to MaxCDN's powerful Oauth API, they offer a number of simple modules for various languages. Here I'll be covering they're Node.js module.
In this post, I'll go over some basic examples of how to display reports and purge caches using the MaxCDN Node module, which like all of MaxCDN's modules, is open sourced at github.com/MaxCDN/node-maxcdn.
If you're like me and prefer to read up on the technologies you'll be using in this post before diving in, here's what we'll be using:
- Node.js, "a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications"
- npm, "Node Packaged Modules"
- Express, "a web application framework for node"
- Jade, a templating engine for Node
- Bootstrap, "The most popular front-end framework for developing responsive, mobile first projects on the web."
- jQuery, "a fast, small, and feature-rich [client-side] JavaScript library"
Before getting started, we'll need to make we've installed Node and the modules we'll need.
Check that Node is installed and you're running a more recent version. The example's contained with in this post have been tested using 0.10.26
(the latest at the time of writing this), but any 0.10.x
(and probably 0.8.x
) version should do.
$ node --version
v0.10.26
Here are some links to help you on your way, if you haven't installed Node yet.
I like to create an empty package.json
file, allowing npm's --save
flag to store our installed packages for later use. You can also use npm init
, if you're planning on building a package for later installation via npm. Optionally, you can skip this all together and omit the --save
option in the npm command below.
$ echo '{}' > package.json
Next, we'll install the modules we'll be using for the examples in this post. By default, npm installs modules locally to the directory you're in when installing (in ./node_modules
), so ensure that you're an acceptable working directory before running the next command. If you need to change directories, you should move your package.json
as well.
$ npm install --save maxcdn express jade
# npm output omitted ...
If you saved the install, package.json
will look something like this:
{
"dependencies": {
"maxcdn": "^0.1.3",
"express": "^3.4.8",
"jade": "^1.1.5"
}
}
If you haven't used Express, that's okay. What I've included here is a good basic example of of how to setup simple application without prior knowledge of the framework. That said, I recommend that you read more deeply into best practices, as the way I'm implementing this application is suitable for smaller applications, but isn't as maintainable on a larger scale.
We'll start by creating a the file app.js
and initializing MaxCDN Node module and creating a variable containing the id of the zone we'll be working with. Notice I'm pulling the required data from my environment (set via export ALIAS=MY_ALIAS
, etc.). However, feel free to hardcode them, or better yet, abstract them to a configuration file.
// file: app.js
'use strict';
var MaxCDN = require('maxcdn');
// Initialize maxcdn from environment.
var maxcdn = new MaxCDN(process.env.ALIAS,
process.env.KEY,
process.env.SECRET);
// For this example, I'll restrict to a single zone,
// however, it wouldn't be hard to adapt this for
// multiple zones.
var zoneid = 12345;
Now that we have a maxcdn
instance to work with in our application, let's get Express setup with basic logging and a few simple routes to hit.
var express = require('express');
var app = express();
// A little logging gose a long way.
app.use(express.logger('dev'));
// main route
app.get('/?', function (req, res) {
res.send('Hello!');
});
// purge zone cache route
app.get('/purge/?', function (req, res) {
res.send('Purge!');
});
// clear file cache route
app.get('/purge/*', function (req, res) {
res.send('Purge '+req.params+'!');
});
app.listen(3333, function (err) {
if (err) {
console.trace(err);
} else {
console.log('Started on port 3333!');
}
});
Start the app by running node app.js
and using a browser, hit the following end points:
The results should be something like the following.
We have a basic Express application in place and know that routes properly. Let's get our main page displaying a report of our popular files from MaxCDN's API, and do so with style. Bootstrap provides a simple scaffolding for building applications. With the added support of BootstrapCDN and the Bootswatch templates it hosts, it makes styling up a simple application like this stupid simple. As I mentioned before, for templating we'll be using the Jade templating engine to generate markup. Jade is a simple tab based templating engine (much like Haml), which relies on indentation to build structured, well-indented and clear markup.
To support Jade, we'll need to make a few tweaks to our Express setup.
In app.js
, after your app
definition, add the following:
// Tell Jade where our templates are.
app.set('views', __dirname + '/views');
// Tell Express to use Jade as it's templating engine.
app.set('view engine', 'jade');
// Here, we're not using any external assets, but if we were, we'd tell
// Express where to find them with the following...
app.use(express.static(__dirname + '/public')); // Support
Using MaxCDN's API, we'll have our main route do a simple fetch on the reports/popularfiles.json endpoint and pass it to our template for rendering.
app.get('/?', function(req, res) {
// Fetch popularfiles from MaxCDN
maxcdn.get('reports/popularfiles.json', function(err, data) {
// Handle errors, should they arise.
if (err) {
console.trace(err);
res.send(500, err);
return;
}
// Render 'index.jade' with popularfiles object.
res.render('index', { popularfiles: data.data.popularfiles });
});
});
With our popular files from MaxCDN available, let's build a basic template to display the information, leveraging Bootstrap for a simple and clean look. Create ./views/index.jade
and add the following to it.
doctype html5
html
head
title MaxCDN Popularfiles
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
//- Include Bootstrap from BootstrapCDN
link(href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/united/bootstrap.min.css", rel="stylesheet")
body
//- Header / Title Bar
.navbar.navbar-default.navbar-static-top
.navbar-header
a.navbar-brand(href="/") MaxCDN Popularfiles
//- Main Body
.container
.table-responsive
table.table.table-striped
thead
tr
th File
th Hits
tbody
- for entry in popularfiles
tr
td= entry.uri
td= entry.hit
//- Footer Information
footer
center
p Powered by
a(href="http://maxcdn.com") MaxCDN
After saving our files and restarting our app (node app.js
), we should see something like this:
Note: If you're getting errors from MaxCDN, ensure that all your credentials are correct and that the host you're working on is whitelisted in your MaxCDN Account. For questions see MaxCDN's Authentication Documentation.
What we have built above is good enough for most public use cases. In fact, it's a simplified version of what's used on BoostrapCDN for displaying usage information. That said, one of the more common usages of CDN APIs in general is automating the purging cached files. So to take this example a step further, let's add some buttons to our page to purge indivial files, or the entire zone in one shot.
To do so, we'll need update to our Express app, modifing the /purge
routes that we setup early to run a maxcdn.delete
on the zones cache endpoint, both with and without specifying a file. When no file is specified, the entire cache is purged.
In app.js
replace the two purge end points we created earlier with the follow code sample.
app.get('/purge/?', function(req, res) {
// Purge entire zone.
maxcdn.delete('zones/pull.json/'+zoneid+'/cache', function(err, data) {
if (err) {
console.trace(err);
res.send(500, err);
return;
}
// Return status.
res.send(data.code);
});
});
// purge file cache route
app.get('/purge/*', function(req, res) {
var files = { files: [ '/'+req.params ] };
// Purge requested file.
maxcdn.delete('zones/pull.json/'+zoneid+'/cache', files, function(err, data) {
if (err) {
console.trace(err);
res.send(500, err);
return;
}
// Return status.
res.send(data.code);
});
});
// ...
With that, our application ow supports purging zones and it's files, we'll need to add some buttons to our page to initiate the purge. In views/index.jade
, replace the previous table
tag with the following.
table.table.table-striped
thead
tr
th File
th Hits
th(width=100)
button.btn.btn-primary(value='') Purge All
tbody
- for entry in popularfiles
tr
td= entry.uri
td= entry.hit
td
button.btn.btn-primary(value=entry.uri) Purge
Button's are pretty, but they don't actually do anything anything on their own. Using jQuery, let's add some magic to submit an aJax request back to our app, requesting a cache purge and waiting for a response. In addition, we'll include a few bells and whistles, like modifing the style on our buttons to show the status of our purge, and a simple text based spinner to show that the purge is in action (purges take anywhere from 10-30 seconds).
If you're not that familar with jQuery, simply copy and paste this inside the head
tag (ensuring proper indenting, as always with Jade).
//- Include jQuery
script(src='http://code.jquery.com/jquery-2.1.0.min.js')
script.
$(window).load(function() {
$('button').each(function() {
//- Add click event to all buttons.
$(this).click(function() {
//- Build purge url string from button value.
var url = '/purge'+$(this).attr('value');
var that = $(this);
//- Add a simple text spinner while pruging.
var spinner = [ '|', '/', '---', '\\' ];
var spinIdx = 0;
function ticker() {
if (spinIdx == spinner.length) {
spinIdx = 0;
}
that.html(spinner[spinIdx++]);
}
ticker();
var interval = setInterval(function() {
ticker();
}, 1000);
// Update button style.
that.removeClass('btn-primary');
that.addClass('btn-warning');
that.addClass('disabled');
// Sumbit Ajax purge request.
$.ajax(url)
.always(function() {
// On pass or fail, cleanup.
clearInterval(interval);
that.removeClass('disabled');
that.removeClass('btn-warning');
})
.done(function() {
// On success, notify.
that.html('Complete');
that.addClass('btn-success');
})
.fail(function() {
// On error, notify.
that.html('ERROR!');
that.addClass('btn-danger');
});
});
});
});
That's it! We now have a simple, easy on the eyes application that allows us to see the most popular file's being loaded via our MaxCDN account. As an added bonus we're able to purge our cache or a single file from the cache, at the click of a button.
Consider this the TL;DR. You can grab the completed code samples used in this post here.
MaxCDN's APIs offer a ton of functionality to interact with your account and report on it's usage. For more examples using the MaxCDN Node Module, visit github.com/MaxCDN/node-maxcdn and checkout the README and examples included there. For more information on MaxCDN's Oauth API, visit docs.maxcdn.com.