Last active
May 4, 2018 12:18
-
-
Save petersirka/0270f0da944d878b440325b0ef6ebb2a to your computer and use it in GitHub Desktop.
A simple REST implementation of Azure DocumentDB with help of Total.js framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Crypto = require('crypto'); | |
require('total.js'); | |
function DocumentDB(hostname, key) { | |
this.hostname = hostname; | |
this.key = key; | |
this.attempts = 0; | |
this.expiration = '10 minutes'; | |
} | |
global.DocumentDB = DocumentDB; | |
DocumentDB.DOCUMENTDB = {}; | |
DocumentDB.prototype.createToken = function(method, type, id, recreate) { | |
var keycache = ((this.hostname || '') + (method || '') + (type || '') + (id || '')).hash().toString(); | |
var meta = DocumentDB.DOCUMENTDB[keycache]; | |
var date = new Date(); | |
if (meta && !recreate) { | |
if (meta.expire > new Date().add('-' + this.expiration).getTime()) | |
return meta; | |
} | |
var key = new Buffer(this.key, 'base64'); | |
var builder = []; | |
builder.push((method || '').toLowerCase()); | |
builder.push((type || '').toLowerCase()); | |
builder.push(id || ''); | |
builder.push(date.toUTCString().toLowerCase()); | |
builder.push(''); | |
var body = new Buffer(builder.join('\n') + '\n', 'utf8'); | |
return DocumentDB.DOCUMENTDB[keycache] = { token: 'type=master&ver=1.0&sig=' + Crypto.createHmac('sha256', key).update(body).digest('base64'), utc: date.toUTCString(), expire: date.getTime() }; | |
}; | |
DocumentDB.prototype.createBuilder = function(method, type, id, recreate) { | |
var builder = new RESTBuilder(); | |
var meta = this.createToken(method, type, id, recreate); | |
builder.header('x-ms-date', meta.utc); | |
builder.header('x-ms-version', '2015-08-06'); | |
builder.header('authorization', meta.token); | |
builder.header('cache-control', 'no-cache'); | |
builder.noDnsCache(); | |
builder.timeout(0); | |
builder.method(method); | |
return builder; | |
}; | |
DocumentDB.prototype.callback = function(err, response, callback) { | |
if (response.code === 'Unauthorized') { | |
if (this.attempts++ > 30) { | |
callback && callback(err, response); | |
return true; | |
} | |
return false; | |
} | |
this.attempts = 0; | |
callback && callback(err, response); | |
return true; | |
}; | |
DocumentDB.prototype.insert = function(database, collection, doc, callback, recreate) { | |
var self = this; | |
var builder = this.createBuilder('POST', 'docs', 'dbs/{0}/colls/{1}'.format(database, collection), recreate); | |
builder.header('x-ms-documentdb-isquery', true); | |
builder.url(this.hostname + '/dbs/{0}/colls/{1}/docs'.format(database, collection)); | |
builder.json(doc); | |
builder.exec((err, response) => !self.callback(err, response, callback) && self.insert(database, collection, doc, callback, true)); | |
}; | |
DocumentDB.prototype.query = function(database, collection, query, callback, recreate) { | |
var self = this; | |
var builder = self.createBuilder('POST', 'docs', 'dbs/{0}/colls/{1}'.format(database, collection), recreate); | |
builder.header('x-ms-documentdb-isquery', true); | |
builder.header('content-type', 'application/query+json'); | |
builder.url(self.hostname + '/dbs/{0}/colls/{1}/docs'.format(database, collection)); | |
builder.json({ query: query }); | |
builder.exec((err, response) => !self.callback(err, response, callback) && self.query(database, collection, query, callback, true)); | |
}; | |
DocumentDB.prototype.databases = function(callback, recreate) { | |
var self = this; | |
var builder = this.createBuilder('GET', 'dbs', '', recreate); | |
builder.url(this.hostname + '/dbs'); | |
builder.exec((err, response) => !self.callback(err, response, callback) && self.databases(callback, true)); | |
}; | |
// USAGE: | |
// "DocumentDB" is a global variable | |
var db = new DocumentDB('https://yourDB.documents.azure.com', 'YOUR_MASTER_KEY'); | |
// db.query(database, collection, query, callback); | |
// db.insert(database, collection, doc, callback); | |
// db.databases(callback); | |
db.query('sensors', 'items', 'SELECT TOP 10 * FROM root', (err, json) => console.log(json)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment