// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* Simple utilities for making XHRs more pleasant.
*/
'use strict';
/** @suppress {duplicate} */
var remoting = remoting || {};
/** Namespace for XHR functions */
/** @type {Object} */
remoting.xhr = remoting.xhr || {};
/**
* Takes an associative array of parameters and urlencodes it.
*
* @param {Object.<string>} paramHash The parameter key/value pairs.
* @return {string} URLEncoded version of paramHash.
*/
remoting.xhr.urlencodeParamHash = function(paramHash) {
var paramArray = [];
for (var key in paramHash) {
paramArray.push(encodeURIComponent(key) +
'=' + encodeURIComponent(paramHash[key]));
}
if (paramArray.length > 0) {
return paramArray.join('&');
}
return '';
};
/**
* Execute an XHR GET asynchronously.
*
* @param {string} url The base URL to GET, excluding parameters.
* @param {function(XMLHttpRequest):void} onDone The function to call on
* completion.
* @param {(string|Object.<string>)=} opt_parameters The request parameters,
* either as an associative array, or a string. If it is a string, do
* not include the ? and be sure it is correctly URLEncoded.
* @param {Object.<string>=} opt_headers Additional headers to include on the
* request.
* @param {boolean=} opt_withCredentials Set the withCredentials flags in the
* XHR.
* @return {XMLHttpRequest} The request object.
*/
remoting.xhr.get = function(url, onDone, opt_parameters, opt_headers,
opt_withCredentials) {
return remoting.xhr.doMethod('GET', url, onDone, opt_parameters,
opt_headers, opt_withCredentials);
};
/**
* Execute an XHR POST asynchronously.
*
* @param {string} url The base URL to POST, excluding parameters.
* @param {function(XMLHttpRequest):void} onDone The function to call on
* completion.
* @param {(string|Object.<string>)=} opt_parameters The request parameters,
* either as an associative array, or a string. If it is a string, be
* sure it is correctly URLEncoded.
* @param {Object.<string>=} opt_headers Additional headers to include on the
* request.
* @param {boolean=} opt_withCredentials Set the withCredentials flags in the
* XHR.
* @return {XMLHttpRequest} The request object.
*/
remoting.xhr.post = function(url, onDone, opt_parameters, opt_headers,
opt_withCredentials) {
return remoting.xhr.doMethod('POST', url, onDone, opt_parameters,
opt_headers, opt_withCredentials);
};
/**
* Execute an XHR DELETE asynchronously.
*
* @param {string} url The base URL to DELETE, excluding parameters.
* @param {function(XMLHttpRequest):void} onDone The function to call on
* completion.
* @param {(string|Object.<string>)=} opt_parameters The request parameters,
* either as an associative array, or a string. If it is a string, be
* sure it is correctly URLEncoded.
* @param {Object.<string>=} opt_headers Additional headers to include on the
* request.
* @param {boolean=} opt_withCredentials Set the withCredentials flags in the
* XHR.
* @return {XMLHttpRequest} The request object.
*/
remoting.xhr.remove = function(url, onDone, opt_parameters, opt_headers,
opt_withCredentials) {
return remoting.xhr.doMethod('DELETE', url, onDone, opt_parameters,
opt_headers, opt_withCredentials);
};
/**
* Execute an XHR PUT asynchronously.
*
* @param {string} url The base URL to PUT, excluding parameters.
* @param {function(XMLHttpRequest):void} onDone The function to call on
* completion.
* @param {(string|Object.<string>)=} opt_parameters The request parameters,
* either as an associative array, or a string. If it is a string, be
* sure it is correctly URLEncoded.
* @param {Object.<string>=} opt_headers Additional headers to include on the
* request.
* @param {boolean=} opt_withCredentials Set the withCredentials flags in the
* XHR.
* @return {XMLHttpRequest} The request object.
*/
remoting.xhr.put = function(url, onDone, opt_parameters, opt_headers,
opt_withCredentials) {
return remoting.xhr.doMethod('PUT', url, onDone, opt_parameters,
opt_headers, opt_withCredentials);
};
/**
* Execute an arbitrary HTTP method asynchronously.
*
* @param {string} methodName The HTTP method name, e.g. "GET", "POST" etc.
* @param {string} url The base URL, excluding parameters.
* @param {function(XMLHttpRequest):void} onDone The function to call on
* completion.
* @param {(string|Object.<string>)=} opt_parameters The request parameters,
* either as an associative array, or a string. If it is a string, be
* sure it is correctly URLEncoded.
* @param {Object.<string>=} opt_headers Additional headers to include on the
* request.
* @param {boolean=} opt_withCredentials Set the withCredentials flags in the
* XHR.
* @return {XMLHttpRequest} The XMLHttpRequest object.
*/
remoting.xhr.doMethod = function(methodName, url, onDone,
opt_parameters, opt_headers,
opt_withCredentials) {
/** @type {XMLHttpRequest} */
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) {
return;
}
onDone(xhr);
};
var parameterString = '';
if (typeof(opt_parameters) === 'string') {
parameterString = opt_parameters;
} else if (typeof(opt_parameters) === 'object') {
parameterString = remoting.xhr.urlencodeParamHash(opt_parameters);
} else if (opt_parameters === undefined) {
// No problem here. Do nothing.
} else {
throw 'opt_parameters must be string or associated array.';
}
var useBody = (methodName == 'POST') || (methodName == 'PUT');
if (!useBody && parameterString != '') {
url = url + '?' + parameterString;
}
xhr.open(methodName, url, true);
if (methodName == 'POST' &&
(typeof opt_headers !== 'object' ||
typeof opt_headers['Content-type'] !== 'string')) {
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
// Add in request headers.
if (typeof(opt_headers) === 'object') {
for (var key in opt_headers) {
xhr.setRequestHeader(key, opt_headers[key]);
}
} else if (opt_headers === undefined) {
// No problem here. Do nothing.
} else {
throw 'opt_headers must be associative array.';
}
if (opt_withCredentials) {
xhr.withCredentials = true;
}
xhr.send(useBody ? parameterString : null);
return xhr;
};