Skip to content

Instantly share code, notes, and snippets.

@timraymond
Created May 18, 2015 16:12
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 timraymond/042cbed0ef0a9fe3ef30 to your computer and use it in GitHub Desktop.
Save timraymond/042cbed0ef0a9fe3ef30 to your computer and use it in GitHub Desktop.
IE9 Compatible XHR Adapter
/**
* Connection class to use with the elasticsearch.js client for limited compatibility with
* IE 9 (also IE 8 is you include an es5 shim like https://github.com/es-shims/es5-shim).
*
* All connections from the browser, directly to elasticsearch, are assumed to be cross-domain
* and therefore suffer from a lack of support in legacy browsers. To prevent the client from
* behaving differently based on the browser version, the following limitations have been imposed
* on all requests:
*
* - only GET and POST are supported
* - Authentication can't be used
* - Custom headers can't be set
* - Requests can't be made to localhost unless the page is running on localhost
* - Protocols of the parent window and the request must match.
*
* Also because of restrictions put in place by IE8/9, responses will be different
* in the following ways:
* - Status codes are not available for the responses
* - Any non-20x status code is considered a generic error. No response body will be available
*
* @class Ie9CompatibleXhrConnector
*/
window.Ie9CompatibleXhrConnector = (function () {
var EsXhrConnection = elasticsearch.ConnectionPool.connectionClasses.xhr;
var ConnectionFault = elasticsearch.errors.ConnectionFault;
// perminent references
var ModernXhr = window.XMLHttpRequest;
var LegacyXhr = window.XDomainRequest;
var setImmediate = window.setImmediate || function (cb) { setTimeout(cb, 1); };
var currentProtocol = window.location.protocol.substr(0, window.location.protocol.length - 1);
var localhostRE = /:\/\/(localhost|127\.0\.0\.1)[:\/]/;
function Ie9CompatibleXhrConnector(host, config) {
EsXhrConnection.call(this, host, config);
this._XhrConstructor = (function () {
if (typeof ModernXhr !== 'undefined') {
var req = new ModernXhr();
if ('withCredentials' in req) {
return ModernXhr;
}
}
if (typeof LegacyXhr !== 'undefined') {
return LegacyXhr;
}
throw new Error('Unable to find a suitable Cross-Domain AJAX handler.');
}());
}
// inherit EsXhrConnection's prototype
Ie9CompatibleXhrConnector.prototype = Object.create(EsXhrConnection.prototype, { 'constructor': Ie9CompatibleXhrConnector });
Ie9CompatibleXhrConnector.prototype.request = function (params, cb) {
var xhr = new this._XhrConstructor();
// This is a patch to this.host by Tim Raymond to get results working
// on search. It isn't really necessary for that page.
this.host.getHeaders = function() { return false };
var hasHeaders = !!this.host.getHeaders(params.headers);
var url = this.host.makeUrl(params);
var log = this.log;
var hasAuth = this.host.auth;
var method = (params.method || 'GET').toUpperCase();
var err = function (msg) {
// always callback async
setImmediate(function () {
cb(new TypeError('Cross-domain AJAX requests ' + msg + ' are not supported'));
});
};
/**
* To prevent some browsers from behaving differently from others, implement some checks here
*/
if (method !== 'GET' && method !== 'POST') {
return err('using HTTP method ' + method);
}
if (localhostRE.test(url) && !localhostRE.test(window.location.href)) {
return err('to localhost from other domains');
}
if (hasAuth) {
return err('with authentication');
}
if (hasHeaders) {
return err('with custom headers');
}
if (this.host.protocol !== currentProtocol) {
return err('across protocols');
}
/**
* Setup listeners for the response
*/
if (this._XhrConstructor === LegacyXhr) {
// XDomainRequest does not support onreadystatechange
xhr.onload = function () {
log.trace(params.method, url, params.body, xhr.responseText, xhr.status);
cb(void 0, xhr.responseText, 200);
};
// XDomainRequest also sends errors elsewhere
xhr.onerror = function (err) {
log.trace(params.method, url, params.body, xhr.responseText, xhr.status);
cb(new ConnectionFault(err.message), xhr.responseText, void 0);
};
}
if (this._XhrConstructor === ModernXhr) {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
log.trace(params.method, url, params.body, xhr.responseText, xhr.status);
var err = xhr.status ? void 0 : new ConnectionFault(xhr.statusText || 'Request failed to complete.');
cb(err, xhr.responseText, xhr.status);
}
};
}
/**
* Send the request
*/
xhr.open(method, url);
xhr.send(params.body || void 0);
return function () {
xhr.abort();
};
};
return Ie9CompatibleXhrConnector;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment