Chromium Code Reviews| Index: remoting/webapp/crd/js/xhr.js |
| diff --git a/remoting/webapp/crd/js/xhr.js b/remoting/webapp/crd/js/xhr.js |
| index 4a3d5740e9eba76850a3c5b2496bffaec7f37aea..444a7387f20fe165678e2c32bab3c76a9f8fe15f 100644 |
| --- a/remoting/webapp/crd/js/xhr.js |
| +++ b/remoting/webapp/crd/js/xhr.js |
| @@ -19,7 +19,7 @@ remoting.xhr = remoting.xhr || {}; |
| /** |
| * Takes an associative array of parameters and urlencodes it. |
| * |
| - * @param {Object.<string>} paramHash The parameter key/value pairs. |
| + * @param {Object.<string,string>} paramHash The parameter key/value pairs. |
| * @return {string} URLEncoded version of paramHash. |
| */ |
| remoting.xhr.urlencodeParamHash = function(paramHash) { |
| @@ -36,108 +36,149 @@ remoting.xhr.urlencodeParamHash = function(paramHash) { |
| }; |
| /** |
| - * Execute an XHR GET asynchronously. |
| + * Parameters for the 'start' function. |
|
Jamie
2015/02/21 01:35:48
I'm not a big fan of mixing optional and mandatory
John Williams
2015/02/23 23:00:55
I prefer to keep it the way it is, because when th
|
| * |
| - * @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); |
| -}; |
| + * method: The HTTP method to use. |
| + * |
| + * url: The URL to request. |
| + * |
| + * onDone: Function to call when the XHR finishes. |
| -/** |
| - * Execute an XHR POST asynchronously. |
| + * urlParams: (optional) Parameters to be appended to the URL. |
| + * Null-valued parameters are omitted. |
| + * |
| + * textContent: (optional) Text to be sent as the request body. |
| + * |
| + * fromContent: (optional) Data to be URL-encoded and sent as the |
|
Jamie
2015/02/21 01:35:48
s/from/form/
John Williams
2015/02/23 23:00:55
Done.
|
| + * request body. Causes Content-type header to be set |
| + * appropriately. |
| + * |
| + * jsonContent: (optional) Data to be JSON-encoded and sent as the |
| + * request body. Causes Content-type header to be set |
| + * appropriately. |
| + * |
| + * headers: (optional) Additional request headers to be sent. |
| + * Null-valued headers are omitted. |
| + * |
| + * withCredentials: (optional) Value of the XHR's withCredentials field. |
| * |
| - * @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. |
| + * oauthToken: (optional) An OAuth2 token used to construct an |
| + * Authentication header. |
| + * |
| + * @typedef {{ |
| + * method: string, |
| + * url:string, |
| + * onDone:(function(XMLHttpRequest):void), |
| + * urlParams:(string|Object<string,?string>|undefined), |
| + * textContent:(string|undefined), |
| + * formContent:(Object|undefined), |
| + * jsonContent:(*|undefined), |
| + * headers:(Object<string,?string>|undefined), |
| + * withCredentials:(boolean|undefined), |
| + * oauthToken:(string|undefined) |
| + * }} |
| */ |
| -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); |
| -}; |
| +remoting.XhrParams; |
| /** |
| - * Execute an XHR DELETE asynchronously. |
| + * Returns a copy of the input object with all null or undefined |
| + * fields removed. |
| * |
| - * @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. |
| + * @param {Object<string,?string>|undefined} input |
| + * @return {!Object<string,string>} |
| + * @private |
| */ |
| -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); |
| +remoting.xhr.removeNullFields_ = function(input) { |
| + /** @type {!Object<string,string>} */ |
| + var result = {}; |
| + if (input) { |
| + for (var field in input) { |
| + var value = input[field]; |
| + if (value != null) { |
| + result[field] = value; |
| + } |
| + } |
| + } |
| + return result; |
| }; |
| /** |
| - * Execute an XHR PUT asynchronously. |
| + * Executes an arbitrary HTTP method 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. |
| + * @param {remoting.XhrParams} params |
| + * @return {XMLHttpRequest} The XMLHttpRequest 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); |
| +remoting.xhr.start = function(params) { |
| + // Extract fields that can be used more or less as-is. |
| + var method = params.method; |
| + var url = params.url; |
| + var onDone = params.onDone; |
| + var headers = remoting.xhr.removeNullFields_(params.headers); |
| + var withCredentials = params.withCredentials || false; |
| + |
| + // Apply URL parameters. |
| + var parameterString = ''; |
| + if (typeof(params.urlParams) === 'string') { |
| + parameterString = params.urlParams; |
| + } else if (typeof(params.urlParams) === 'object') { |
| + parameterString = remoting.xhr.urlencodeParamHash( |
| + remoting.xhr.removeNullFields_(params.urlParams)); |
| + } |
| + if (parameterString) { |
| + base.debug.assert(url.indexOf('?') == -1); |
| + url += '?' + parameterString; |
| + } |
| + |
| + // Check that the content spec is consistent. |
| + if ((0 + |
|
Jamie
2015/02/21 01:35:48
An explicit cast using Number would be more readab
John Williams
2015/02/23 23:00:55
Changed to an explicit cast. I don't want to use s
|
| + (params.textContent !== undefined) + |
| + (params.formContent !== undefined) + |
| + (params.jsonContent !== undefined)) > 1) { |
| + throw Error( |
|
Jamie
2015/02/21 01:35:48
s/Error/new Error/ for consistency with (most of)
John Williams
2015/02/23 23:00:55
Done.
|
| + 'may only specify one of textContent, formContent, and jsonContent'); |
| + } |
| + |
| + // Convert the content fields to a single text content variable. |
| + /** @type {?string} */ |
| + var content = null; |
| + if (params.textContent !== undefined) { |
| + content = params.textContent; |
| + } else if (params.formContent !== undefined) { |
| + if (!('Content-type' in headers)) { |
| + headers['Content-type'] = 'application/x-www-form-urlencoded'; |
| + } |
| + content = remoting.xhr.urlencodeParamHash(params.formContent); |
| + } else if (params.jsonContent !== undefined) { |
| + if (!('Content-type' in headers)) { |
| + headers['Content-type'] = 'application/json; charset=UTF-8'; |
| + } |
| + content = JSON.stringify(params.jsonContent); |
| + } |
| + |
| + // Apply the oauthToken field. |
| + if (params.oauthToken !== undefined) { |
| + base.debug.assert(!('Authorization' in headers)); |
| + headers['Authorization'] = 'Bearer ' + params.oauthToken; |
| + } |
| + |
| + return remoting.xhr.startInternal_( |
| + method, url, onDone, content, headers, withCredentials); |
| }; |
| /** |
| - * Execute an arbitrary HTTP method asynchronously. |
| + * Executes 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. |
| + * @param {string} method |
| + * @param {string} url |
| + * @param {function(XMLHttpRequest):void} onDone |
| + * @param {?string} content |
| + * @param {!Object<string,string>} headers |
| + * @param {boolean} withCredentials |
| * @return {XMLHttpRequest} The XMLHttpRequest object. |
| + * @private |
| */ |
| -remoting.xhr.doMethod = function(methodName, url, onDone, |
| - opt_parameters, opt_headers, |
| - opt_withCredentials) { |
| +remoting.xhr.startInternal_ = function( |
| + method, url, onDone, content, headers, withCredentials) { |
| /** @type {XMLHttpRequest} */ |
| var xhr = new XMLHttpRequest(); |
| xhr.onreadystatechange = function() { |
| @@ -147,45 +188,12 @@ remoting.xhr.doMethod = function(methodName, url, onDone, |
| 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.'; |
| + xhr.open(method, url, true); |
| + for (var key in headers) { |
| + xhr.setRequestHeader(key, headers[key]); |
| } |
| - |
| - 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); |
| + xhr.withCredentials = withCredentials; |
| + xhr.send(content); |
| return xhr; |
| }; |