summaryrefslogtreecommitdiffstats
path: root/remoting/webapp/xhr.js
blob: b0c205643a2a17fb35bcede480a1914c0ac7dc92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// 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;
};