esri-leaflet
Version:
Leaflet plugins for consuming ArcGIS Online and ArcGIS Server services.
249 lines (201 loc) • 7.33 kB
JavaScript
import { Util, DomUtil } from 'leaflet';
import { Support } from './Support';
var callbacks = 0;
function serialize (params) {
var data = '';
params.f = params.f || 'json';
for (var key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) {
var param = params[key];
var type = Object.prototype.toString.call(param);
var value;
if (data.length) {
data += '&';
}
if (type === '[object Array]') {
value = (Object.prototype.toString.call(param[0]) === '[object Object]') ? JSON.stringify(param) : param.join(',');
} else if (type === '[object Object]') {
value = JSON.stringify(param);
} else if (type === '[object Date]') {
value = param.valueOf();
} else {
value = param;
}
data += encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
}
return data;
}
function createRequest (callback, context) {
var httpRequest = new window.XMLHttpRequest();
httpRequest.onerror = function (e) {
httpRequest.onreadystatechange = Util.falseFn;
callback.call(context, {
error: {
code: 500,
message: 'XMLHttpRequest error'
}
}, null);
};
httpRequest.onreadystatechange = function () {
var response;
var error;
if (httpRequest.readyState === 4) {
try {
response = JSON.parse(httpRequest.responseText);
} catch (e) {
response = null;
error = {
code: 500,
message: 'Could not parse response as JSON. This could also be caused by a CORS or XMLHttpRequest error.'
};
}
if (!error && response.error) {
error = response.error;
response = null;
}
httpRequest.onerror = Util.falseFn;
callback.call(context, error, response);
}
};
httpRequest.ontimeout = function () {
this.onerror();
};
return httpRequest;
}
function xmlHttpPost (url, params, callback, context) {
var httpRequest = createRequest(callback, context);
httpRequest.open('POST', url);
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
}
}
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
httpRequest.send(serialize(params));
return httpRequest;
}
function xmlHttpGet (url, params, callback, context) {
var httpRequest = createRequest(callback, context);
httpRequest.open('GET', url + '?' + serialize(params), true);
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
if (context.options.withCredentials) {
httpRequest.withCredentials = true;
}
}
}
httpRequest.send(null);
return httpRequest;
}
// AJAX handlers for CORS (modern browsers) or JSONP (older browsers)
export function request (url, params, callback, context) {
var paramString = serialize(params);
var httpRequest = createRequest(callback, context);
var requestLength = (url + '?' + paramString).length;
// ie10/11 require the request be opened before a timeout is applied
if (requestLength <= 2000 && Support.cors) {
httpRequest.open('GET', url + '?' + paramString);
} else if (requestLength > 2000 && Support.cors) {
httpRequest.open('POST', url);
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
}
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
if (context.options.withCredentials) {
httpRequest.withCredentials = true;
}
}
}
// request is less than 2000 characters and the browser supports CORS, make GET request with XMLHttpRequest
if (requestLength <= 2000 && Support.cors) {
httpRequest.send(null);
// request is more than 2000 characters and the browser supports CORS, make POST request with XMLHttpRequest
} else if (requestLength > 2000 && Support.cors) {
httpRequest.send(paramString);
// request is less than 2000 characters and the browser does not support CORS, make a JSONP request
} else if (requestLength <= 2000 && !Support.cors) {
return jsonp(url, params, callback, context);
// request is longer then 2000 characters and the browser does not support CORS, log a warning
} else {
warn('a request to ' + url + ' was longer then 2000 characters and this browser cannot make a cross-domain post request. Please use a proxy https://developers.arcgis.com/esri-leaflet/api-reference/request/');
return;
}
return httpRequest;
}
export function jsonp (url, params, callback, context) {
window._EsriLeafletCallbacks = window._EsriLeafletCallbacks || {};
var callbackId = 'c' + callbacks;
params.callback = 'window._EsriLeafletCallbacks.' + callbackId;
window._EsriLeafletCallbacks[callbackId] = function (response) {
if (window._EsriLeafletCallbacks[callbackId] !== true) {
var error;
var responseType = Object.prototype.toString.call(response);
if (!(responseType === '[object Object]' || responseType === '[object Array]')) {
error = {
error: {
code: 500,
message: 'Expected array or object as JSONP response'
}
};
response = null;
}
if (!error && response.error) {
error = response;
response = null;
}
callback.call(context, error, response);
window._EsriLeafletCallbacks[callbackId] = true;
}
};
var script = DomUtil.create('script', null, document.body);
script.type = 'text/javascript';
script.src = url + '?' + serialize(params);
script.id = callbackId;
script.onerror = function (error) {
if (error && window._EsriLeafletCallbacks[callbackId] !== true) {
// Can't get true error code: it can be 404, or 401, or 500
var err = {
error: {
code: 500,
message: 'An unknown error occurred'
}
};
callback.call(context, err);
window._EsriLeafletCallbacks[callbackId] = true;
}
};
DomUtil.addClass(script, 'esri-leaflet-jsonp');
callbacks++;
return {
id: callbackId,
url: script.src,
abort: function () {
window._EsriLeafletCallbacks._callback[callbackId]({
code: 0,
message: 'Request aborted.'
});
}
};
}
var get = ((Support.cors) ? xmlHttpGet : jsonp);
get.CORS = xmlHttpGet;
get.JSONP = jsonp;
export function warn () {
if (console && console.warn) {
console.warn.apply(console, arguments);
}
}
// choose the correct AJAX handler depending on CORS support
export { get };
// always use XMLHttpRequest for posts
export { xmlHttpPost as post };
// export the Request object to call the different handlers for debugging
export var Request = {
request: request,
get: get,
post: xmlHttpPost
};
export default Request;