falcor-http-datasource
Version:
This package contains falcor components for use in browsers.
372 lines (323 loc) • 10.7 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
;
var request = require('./request');
var buildQueryObject = require('./buildQueryObject');
var isArray = Array.isArray;
function simpleExtend(obj, obj2) {
var prop;
for (prop in obj2) {
obj[prop] = obj2[prop];
}
return obj;
}
function XMLHttpSource(jsongUrl, config) {
this._jsongUrl = jsongUrl;
if (typeof config === 'number') {
var newConfig = {
timeout: config
};
config = newConfig;
}
this._config = simpleExtend({
timeout: 15000,
headers: {}
}, config || {});
}
XMLHttpSource.prototype = {
// because javascript
constructor: XMLHttpSource,
/**
* buildQueryObject helper
*/
buildQueryObject: buildQueryObject,
/**
* @inheritDoc DataSource#get
*/
get: function httpSourceGet(pathSet) {
var method = 'GET';
var queryObject = this.buildQueryObject(this._jsongUrl, method, {
paths: pathSet,
method: 'get'
});
var config = simpleExtend(queryObject, this._config);
// pass context for onBeforeRequest callback
var context = this;
return request(method, config, context);
},
/**
* @inheritDoc DataSource#set
*/
set: function httpSourceSet(jsongEnv) {
var method = 'POST';
var queryObject = this.buildQueryObject(this._jsongUrl, method, {
jsong: jsongEnv,
method: 'set'
});
var config = simpleExtend(queryObject, this._config);
// pass context for onBeforeRequest callback
var context = this;
return request(method, config, context);
},
/**
* @inheritDoc DataSource#call
*/
call: function httpSourceCall(callPath, args, pathSuffix, paths) {
// arguments defaults
args = args || [];
pathSuffix = pathSuffix || [];
paths = paths || [];
var method = 'POST';
var queryData = [];
queryData.push('method=call');
queryData.push('callPath=' + encodeURIComponent(JSON.stringify(callPath)));
queryData.push('arguments=' + encodeURIComponent(JSON.stringify(args)));
queryData.push('pathSuffixes=' + encodeURIComponent(JSON.stringify(pathSuffix)));
queryData.push('paths=' + encodeURIComponent(JSON.stringify(paths)));
var queryObject = this.buildQueryObject(this._jsongUrl, method, queryData.join('&'));
var config = simpleExtend(queryObject, this._config);
// pass context for onBeforeRequest callback
var context = this;
return request(method, config, context);
}
};
// ES6 modules
XMLHttpSource.XMLHttpSource = XMLHttpSource;
XMLHttpSource['default'] = XMLHttpSource;
// commonjs
module.exports = XMLHttpSource;
},{"./buildQueryObject":2,"./request":5}],2:[function(require,module,exports){
;
module.exports = function buildQueryObject(url, method, queryData) {
var qData = [];
var keys;
var data = {url: url};
var isQueryParamUrl = url.indexOf('?') !== -1;
var startUrl = (isQueryParamUrl) ? '&' : '?';
if (typeof queryData === 'string') {
qData.push(queryData);
} else {
keys = Object.keys(queryData);
keys.forEach(function (k) {
var value = (typeof queryData[k] === 'object') ? JSON.stringify(queryData[k]) : queryData[k];
qData.push(k + '=' + value);
});
}
if (method === 'GET') {
data.url += startUrl + qData.join('&');
} else {
data.data = qData.join('&');
}
return data;
};
},{}],3:[function(require,module,exports){
(function (global){
;
// Get CORS support even for older IE
module.exports = function getCORSRequest() {
var xhr = new global.XMLHttpRequest();
if ('withCredentials' in xhr) {
return xhr;
} else if (!!global.XDomainRequest) {
return new XDomainRequest();
} else {
throw new Error('CORS is not supported by your browser');
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],4:[function(require,module,exports){
(function (global){
;
module.exports = function getXMLHttpRequest() {
var progId,
progIds,
i;
if (global.XMLHttpRequest) {
return new global.XMLHttpRequest();
} else {
try {
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
for (i = 0; i < 3; i++) {
try {
progId = progIds[i];
if (new global.ActiveXObject(progId)) {
break;
}
} catch(e) { }
}
return new global.ActiveXObject(progId);
} catch (e) {
throw new Error('XMLHttpRequest is not supported by your browser');
}
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],5:[function(require,module,exports){
;
var getXMLHttpRequest = require('./getXMLHttpRequest');
var getCORSRequest = require('./getCORSRequest');
var hasOwnProp = Object.prototype.hasOwnProperty;
function Observable() {}
Observable.create = function(subscribe) {
var o = new Observable();
o.subscribe = function(observer) {
var s = subscribe(observer);
if (typeof s === 'function') {
return {
dispose: s
};
}
else {
return s;
}
}
return o;
}
function request(method, options, context) {
return Observable.create(function requestObserver(observer) {
var config = {
method: method || 'GET',
crossDomain: false,
async: true,
headers: {},
responseType: 'json'
};
var xhr,
isDone,
headers,
header,
prop;
for (prop in options) {
if (hasOwnProp.call(options, prop)) {
config[prop] = options[prop];
}
}
// Add request with Headers
if (!config.crossDomain && !config.headers['X-Requested-With']) {
config.headers['X-Requested-With'] = 'XMLHttpRequest';
}
// allow the user to mutate the config open
if (context.onBeforeRequest != null) {
context.onBeforeRequest(config);
}
// create xhr
try {
xhr = config.crossDomain ? getCORSRequest() : getXMLHttpRequest();
} catch (err) {
observer.onError(err);
}
try {
// Takes the url and opens the connection
if (config.user) {
xhr.open(config.method, config.url, config.async, config.user, config.password);
} else {
xhr.open(config.method, config.url, config.async);
}
// Sets timeout information
xhr.timeout = config.timeout;
// Anything but explicit false results in true.
xhr.withCredentials = config.withCredentials !== false;
// Fills the request headers
headers = config.headers;
for (header in headers) {
if (hasOwnProp.call(headers, header)) {
xhr.setRequestHeader(header, headers[header]);
}
}
if (config.responseType) {
try {
xhr.responseType = config.responseType;
} catch (e) {
// WebKit added support for the json responseType value on 09/03/2013
// https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
// known to throw when setting the value "json" as the response type. Other older
// browsers implementing the responseType
//
// The json response type can be ignored if not supported, because JSON payloads are
// parsed on the client-side regardless.
if (responseType !== 'json') {
throw e;
}
}
}
xhr.onreadystatechange = function onreadystatechange(e) {
// Complete
if (xhr.readyState === 4) {
if (!isDone) {
isDone = true;
onXhrLoad(observer, xhr, status, e);
}
}
};
// Timeout
xhr.ontimeout = function ontimeout(e) {
if (!isDone) {
isDone = true;
onXhrError(observer, xhr, 'timeout error', e);
}
};
// Send Request
xhr.send(config.data);
} catch (e) {
observer.onError(e);
}
// Dispose
return function dispose() {
// Doesn't work in IE9
if (!isDone && xhr.readyState !== 4) {
isDone = true;
xhr.abort();
}
};//Dispose
});
}
/*
* General handling of ultimate failure (after appropriate retries)
*/
function _handleXhrError(observer, textStatus, errorThrown) {
// IE9: cross-domain request may be considered errors
if (!errorThrown) {
errorThrown = new Error(textStatus);
}
observer.onError(errorThrown);
}
function onXhrLoad(observer, xhr, status, e) {
var responseData,
responseObject,
responseType;
// If there's no observer, the request has been (or is being) cancelled.
if (xhr && observer) {
responseType = xhr.responseType;
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
responseData = ('response' in xhr) ? xhr.response : xhr.responseText;
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
var status = (xhr.status === 1223) ? 204 : xhr.status;
if (status >= 200 && status <= 399) {
try {
if (responseType !== 'json' && typeof responseData === 'string') {
responseData = JSON.parse(responseData || '');
}
} catch (e) {
_handleXhrError(observer, 'invalid json', e);
}
observer.onNext(responseData);
observer.onCompleted();
return;
} else if (status === 401 || status === 403 || status === 407) {
return _handleXhrError(observer, responseData);
} else if (status === 410) {
// TODO: Retry ?
return _handleXhrError(observer, responseData);
} else if (status === 408 || status === 504) {
// TODO: Retry ?
return _handleXhrError(observer, responseData);
} else {
return _handleXhrError(observer, responseData || ('Response code ' + status));
}//if
}//if
}//onXhrLoad
function onXhrError(observer, xhr, status, e) {
_handleXhrError(observer, status || xhr.statusText || 'request error', e);
}
module.exports = request;
},{"./getCORSRequest":3,"./getXMLHttpRequest":4}]},{},[1]);