Skip to content

Instantly share code, notes, and snippets.

@sajal
Created January 18, 2012 11:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sajal/1632470 to your computer and use it in GitHub Desktop.
Save sajal/1632470 to your computer and use it in GitHub Desktop.
Cloudfront API Access from JS (needs cross-domain XHR)
/*
Check : https://github.com/sajal/Cloudfront-Purge-Tool/blob/master/cloudfrontapi.js for maintained version.
Author: Sajal Kayan
URL: http://www.cdnplanet.com/
License: Undecided probably BSD style
Description: Access to CloudFront API from browser. Requires crossdomain XHR!!!.
Wont work from webpages, but i'm making this for chrome extention.
Sample Usage :
var c = new cloudfrontapi("XXXXXXXXXX", "XXXXXXXXX");
c.usesystemtime = false; // set this if users system clock is innacurate by more than 15 mins
var print = function(obj){
console.log(obj);
}
c.getAllDistributions(print);
c.getAllInvalidations("DISTIDXXX", print);
c.getPendingInvalidations("DISTIDXXX", print);
Dependencies: http://davidwalsh.name/convert-xml-json , http://www.java2s.com/Open-Source/Javascript/Benchmark/sunspider-mod/tests/sunspider-0.9.1/crypto-sha1.js.htm
*/
var cloudfrontapi = function(aws_access, aws_secret){
this.aws_access = aws_access;
this.aws_secret = aws_secret;
this.usesystemtime = true;
this.endpoint = "cloudfront.amazonaws.com";
// this.tmpdatestr = ""
this.getAWStime = function(){
var req = new XMLHttpRequest();
req.open(
"GET",
"https://cloudfront.amazonaws.com/date",
false
);
req.send(null);
return req.getResponseHeader("Date");
}
this.getDate = function(){
if (this.usesystemtime){
return (new Date()).toGMTString();
} else {
//fetch the date from AWS, since we dont trust system time
return this.getAWStime()
}
}
this.getAuth = function(){
var datestr = this.getDate();
var signature = sha1.hmac.toB64(this.aws_secret, datestr);
var authorization = "AWS " + this.aws_access + ":" + signature + "="; // no idea why i gotta manually add = but this shit works
return {datestr: datestr, authorization:authorization}
};
this.makeRequest = function(path, callback, data){
var req = new XMLHttpRequest();
var auth = this.getAuth();
var method = "POST";
if (data == undefined){
method = "GET";
data == null;
}
req.open(
method,
"https://" + this.endpoint + path,
true
);
req.setRequestHeader("Authorization", auth.authorization);
req.setRequestHeader("x-amz-date", auth.datestr);
if (method == "POST"){
req.setRequestHeader("Content-Type", "text/xml");
}
req.onload = function(){
callback(req);
};
req.send(data);
}
this.getfield = function(node, tagname){
console.log(tagname);
console.log(node);
return node.getElementsByTagName(tagname)[0].textContent
}
this.getAllDistributions = function(callback){
/*
Returns Array : List of CloudFront distributions.
*/
var getfield = this.getfield;
var localcb = function(res){
var distributions = xmlToJson(res.responseXML).DistributionList.DistributionSummary;
if (distributions.length == undefined){
distributions = [distributions];
}
callback(distributions);
};
this.makeRequest("/2010-11-01/distribution", function(res){ localcb(res) })
};
this.getAllInvalidations = function(distid, callback){
/*
Returns Array : List of last 20 invalidation requests.
*/
var getfield = this.getfield;
var localcb = function(res){
var invalidations = xmlToJson(res.responseXML).InvalidationList.InvalidationSummary;
if (invalidations == undefined){
callback([]);
} else {
if (invalidations.length == undefined){
invalidations = [invalidations];
}
callback(invalidations);
}
}
this.makeRequest("/2010-11-01/distribution/" + distid + "/invalidation?MaxItems=20", localcb);
};
this.getPendingInvalidations = function(distid, callback){
/*
Returns Array : List of last 20 invalidation requests (only filtering non completed ones).
*/
var localcb = function(allinvalidations){
pending = [];
for(i=0;i<allinvalidations.length;i++){
if(allinvalidations[i].Status["#text"] != 'Completed'){
pending.push(allinvalidations[i]);
}
}
callback(pending);
}
this.getAllInvalidations(distid, localcb);
};
this.AddNewPurgeRequest = function(distid, pathcsv, callback){
/*
Places a purge request for comma seperated list of paths.
*/
var localcb = function(res){
callback(res);
}
var files = pathcsv.split(',');
var invallist = "";
for(i=0;i<files.length;i++){
invallist += '<Path>' + files[i].trim() + '</Path>'
}
var callerref = "batch" + (new Date()).getTime();
var teststr = "<InvalidationBatch>" + invallist + "<CallerReference>" + callerref + "</CallerReference></InvalidationBatch>";
console.log(teststr);
var path = "/2010-11-01/distribution/" + distid + "/invalidation";
this.makeRequest(path, localcb, teststr);
};
this.getInvalidationDetails = function(distid, invalid, callback){
//todo
var localcb = function(res){
callback(xmlToJson(res.responseXML));
}
var path = "/2010-11-01/distribution/" + distid + "/invalidation/" + invalid;
console.log(path)
this.makeRequest(path, localcb);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment