Last active
February 25, 2016 13:32
-
-
Save weswigham/c142911ba4293d8f47b6 to your computer and use it in GitHub Desktop.
resteasy.js - Makes consuming rest interfaces as data promises super simple
This file contains hidden or 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
(function(window) { | |
//Step 1: Promised wrapper for XMLHTTPRequest | |
function Request(url, options) { | |
return new Promise(function(resolve, reject) { | |
if (!options) { | |
if (typeof(url) == "string") { | |
options = { url: url }; | |
} else { | |
options = url; | |
} | |
} else { | |
options.url = url; | |
} | |
var req = new XMLHttpRequest(); | |
req.timeout = options.timeout || 0; | |
req.ontimeout = function() { | |
reject(new Error('Request timed out!')); | |
}; | |
req.withCredentials = options.withCredentials; | |
req.open(options.method || 'GET', options.url, true, options.user, options.password); | |
Object.keys(options.headers || {}).forEach(function(key){ | |
req.setRequestHeader(key, options.headers[key]); | |
}); | |
req.onreadystatechange = function(e) { | |
var obj; | |
if(req.readyState !== 4) { | |
return; | |
} | |
if([200,304].indexOf(req.status) === -1) { | |
return reject(new Error('Server responded with a status of ' + req.status)); | |
} else { | |
var expect = options.expect || 'anything'; | |
switch(expect.toLowerCase()) { | |
case 'json': | |
try { | |
obj = JSON.parse(e.target.responseText); | |
} catch (_) { | |
return reject(new Error('JSON parsing error.')); | |
} | |
return resolve(obj); | |
case 'xml': | |
return resolve(e.target.responseXML); | |
default: | |
return resolve(e.target.response); | |
} | |
} | |
}; | |
if (options.mimetype) { | |
req.overrideMimeType(options.mimetype); | |
} | |
req.send(options.data || ''); | |
}); | |
} | |
//Step 2: location-protcol-aware wrapper for http(s) requests | |
function LocationRequest(hostpath, options) { | |
options = options || {}; | |
var protocol = window.location.protocol; | |
if (options.forceSSL) { | |
protocol = 'https:'; | |
} | |
var url = protocol + '//' + hostpath; | |
return Request(url, options); | |
} | |
//Step 3: RESTy defaults wrapper | |
function RESTRequest(hostpath, options) { | |
options = options || {}; | |
options.method = options.method || 'GET'; | |
options.expect = options.expect || 'json'; | |
if (options.forceSSL === undefined) { | |
options.forceSSL = true; | |
} | |
return LocationRequest(hostpath, options); | |
} | |
//Step 3.5: Proxy shim | |
if (!window.Proxy) { | |
console.warn('No Proxy object found, RESTEasy cannot be used.'); | |
return; //All is for naught, no proxy present | |
} | |
var LocalProxy = Proxy; | |
if (typeof(Proxy) !== 'function') { | |
LocalProxy = function(target, handlers) { | |
if (target instanceof Function) { | |
return Proxy.createFunction(handlers, target); | |
} else { | |
return Proxy.create(handlers, target); | |
} | |
}; | |
} | |
function isObject(obj) { //From underscore.js | |
var type = typeof obj; | |
return type === 'function' || type === 'object' && !!obj; | |
} | |
function extend(obj) { //From underscore.js | |
if (!isObject(obj)) return obj; | |
var source, prop; | |
for (var i = 1, length = arguments.length; i < length; i++) { | |
source = arguments[i]; | |
for (prop in source) { | |
if (hasOwnProperty.call(source, prop)) { | |
obj[prop] = source[prop]; | |
} | |
} | |
} | |
return obj; | |
} | |
//Step 4: Proxy | |
function RESTEasy(host, path, upperoptions) { | |
if (isObject(path)) { | |
upperoptions = path; | |
path = undefined; | |
} | |
var handlers = { | |
get: function(target, key) { | |
return new RESTEasy(host, (path || '')+'/'+key, upperoptions); | |
} | |
}; | |
return new LocalProxy(function(queryhash, options) { | |
var query = ''; | |
if (queryhash) { | |
var queryitems = []; | |
for (var key in queryhash) { | |
queryitems.push(encodeURIComponent(key) + '=' + encodeURIComponent(queryhash[key])); | |
} | |
query = '?' + queryitems.join('&'); | |
} | |
if (path) { | |
return RESTRequest(host+path+query, extend({}, upperoptions, options)); | |
} | |
return RESTRequest(host+query, extend({}, upperoptions, options)); | |
}, handlers); | |
} | |
//Step 5: Export | |
var noConflict = window.RESTEasy; | |
RESTEasy.noConflict = function() { | |
window.RESTEasy = noConflict; | |
return RESTEasy; | |
}; | |
window.RESTEasy = RESTEasy; | |
//Step 6: ??? | |
//Step 7: Profit! | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment