RESTController.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  2. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  3. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  4. var _ParseError = _interopRequireDefault(require("./ParseError"));
  5. var _promiseUtils = require("./promiseUtils");
  6. var _require = require('uuid'),
  7. uuidv4 = _require.v4;
  8. var XHR = null;
  9. if (typeof XMLHttpRequest !== 'undefined') {
  10. XHR = XMLHttpRequest;
  11. }
  12. var useXDomainRequest = false;
  13. if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) {
  14. useXDomainRequest = true;
  15. }
  16. function ajaxIE9(method, url, data, headers, options) {
  17. return new Promise(function (resolve, reject) {
  18. var xdr = new XDomainRequest();
  19. xdr.onload = function () {
  20. var response;
  21. try {
  22. response = JSON.parse(xdr.responseText);
  23. } catch (e) {
  24. reject(e);
  25. }
  26. if (response) {
  27. resolve({
  28. response: response
  29. });
  30. }
  31. };
  32. xdr.onerror = xdr.ontimeout = function () {
  33. var fakeResponse = {
  34. responseText: JSON.stringify({
  35. code: _ParseError.default.X_DOMAIN_REQUEST,
  36. error: "IE's XDomainRequest does not supply error info."
  37. })
  38. };
  39. reject(fakeResponse);
  40. };
  41. xdr.onprogress = function () {
  42. if (options && typeof options.progress === 'function') {
  43. options.progress(xdr.responseText);
  44. }
  45. };
  46. xdr.open(method, url);
  47. xdr.send(data);
  48. if (options && typeof options.requestTask === 'function') {
  49. options.requestTask(xdr);
  50. }
  51. });
  52. }
  53. var RESTController = {
  54. ajax: function (method, url, data, headers, options) {
  55. if (useXDomainRequest) {
  56. return ajaxIE9(method, url, data, headers, options);
  57. }
  58. var promise = (0, _promiseUtils.resolvingPromise)();
  59. var isIdempotent = _CoreManager.default.get('IDEMPOTENCY') && ['POST', 'PUT'].includes(method);
  60. var requestId = isIdempotent ? uuidv4() : '';
  61. var attempts = 0;
  62. var dispatch = function dispatch() {
  63. if (XHR == null) {
  64. throw new Error('Cannot make a request: No definition of XMLHttpRequest was found.');
  65. }
  66. var handled = false;
  67. var xhr = new XHR();
  68. xhr.onreadystatechange = function () {
  69. if (xhr.readyState !== 4 || handled || xhr._aborted) {
  70. return;
  71. }
  72. handled = true;
  73. if (xhr.status >= 200 && xhr.status < 300) {
  74. var response;
  75. try {
  76. response = JSON.parse(xhr.responseText);
  77. if (typeof xhr.getResponseHeader === 'function') {
  78. if ((xhr.getAllResponseHeaders() || '').includes('x-parse-job-status-id: ')) {
  79. response = xhr.getResponseHeader('x-parse-job-status-id');
  80. }
  81. }
  82. } catch (e) {
  83. promise.reject(e.toString());
  84. }
  85. if (response) {
  86. promise.resolve({
  87. response: response,
  88. status: xhr.status,
  89. xhr: xhr
  90. });
  91. }
  92. } else if (xhr.status >= 500 || xhr.status === 0) {
  93. if (++attempts < _CoreManager.default.get('REQUEST_ATTEMPT_LIMIT')) {
  94. var delay = Math.round(Math.random() * 125 * Math.pow(2, attempts));
  95. setTimeout(dispatch, delay);
  96. } else if (xhr.status === 0) {
  97. promise.reject('Unable to connect to the Parse API');
  98. } else {
  99. promise.reject(xhr);
  100. }
  101. } else {
  102. promise.reject(xhr);
  103. }
  104. };
  105. headers = headers || {};
  106. if (typeof headers['Content-Type'] !== 'string') {
  107. headers['Content-Type'] = 'text/plain';
  108. }
  109. if (_CoreManager.default.get('IS_NODE')) {
  110. headers['User-Agent'] = "Parse/" + _CoreManager.default.get('VERSION') + " (NodeJS " + process.versions.node + ")";
  111. }
  112. if (isIdempotent) {
  113. headers['X-Parse-Request-Id'] = requestId;
  114. }
  115. if (_CoreManager.default.get('SERVER_AUTH_TYPE') && _CoreManager.default.get('SERVER_AUTH_TOKEN')) {
  116. headers.Authorization = _CoreManager.default.get('SERVER_AUTH_TYPE') + " " + _CoreManager.default.get('SERVER_AUTH_TOKEN');
  117. }
  118. var customHeaders = _CoreManager.default.get('REQUEST_HEADERS');
  119. for (var key in customHeaders) {
  120. headers[key] = customHeaders[key];
  121. }
  122. function handleProgress(type, event) {
  123. if (options && typeof options.progress === 'function') {
  124. if (event.lengthComputable) {
  125. options.progress(event.loaded / event.total, event.loaded, event.total, {
  126. type: type
  127. });
  128. } else {
  129. options.progress(null, null, null, {
  130. type: type
  131. });
  132. }
  133. }
  134. }
  135. xhr.onprogress = function (event) {
  136. handleProgress('download', event);
  137. };
  138. if (xhr.upload) {
  139. xhr.upload.onprogress = function (event) {
  140. handleProgress('upload', event);
  141. };
  142. }
  143. xhr.open(method, url, true);
  144. for (var h in headers) {
  145. xhr.setRequestHeader(h, headers[h]);
  146. }
  147. xhr.onabort = function () {
  148. promise.resolve({
  149. response: {
  150. results: []
  151. },
  152. status: 0,
  153. xhr: xhr
  154. });
  155. };
  156. xhr.send(data);
  157. if (options && typeof options.requestTask === 'function') {
  158. options.requestTask(xhr);
  159. }
  160. };
  161. dispatch();
  162. return promise;
  163. },
  164. request: function (method, path, data, options) {
  165. options = options || {};
  166. var url = _CoreManager.default.get('SERVER_URL');
  167. if (url[url.length - 1] !== '/') {
  168. url += '/';
  169. }
  170. url += path;
  171. var payload = {};
  172. if (data && typeof data === 'object') {
  173. for (var k in data) {
  174. payload[k] = data[k];
  175. }
  176. }
  177. var _options = options,
  178. context = _options.context;
  179. if (context !== undefined) {
  180. payload._context = context;
  181. }
  182. if (method !== 'POST') {
  183. payload._method = method;
  184. method = 'POST';
  185. }
  186. payload._ApplicationId = _CoreManager.default.get('APPLICATION_ID');
  187. var jsKey = _CoreManager.default.get('JAVASCRIPT_KEY');
  188. if (jsKey) {
  189. payload._JavaScriptKey = jsKey;
  190. }
  191. payload._ClientVersion = _CoreManager.default.get('VERSION');
  192. var _options2 = options,
  193. useMasterKey = _options2.useMasterKey;
  194. if (typeof useMasterKey === 'undefined') {
  195. useMasterKey = _CoreManager.default.get('USE_MASTER_KEY');
  196. }
  197. if (useMasterKey) {
  198. if (_CoreManager.default.get('MASTER_KEY')) {
  199. delete payload._JavaScriptKey;
  200. payload._MasterKey = _CoreManager.default.get('MASTER_KEY');
  201. }
  202. }
  203. if (_CoreManager.default.get('FORCE_REVOCABLE_SESSION')) {
  204. payload._RevocableSession = '1';
  205. }
  206. var _options3 = options,
  207. installationId = _options3.installationId;
  208. var installationIdPromise;
  209. if (installationId && typeof installationId === 'string') {
  210. installationIdPromise = Promise.resolve(installationId);
  211. } else {
  212. var installationController = _CoreManager.default.getInstallationController();
  213. installationIdPromise = installationController.currentInstallationId();
  214. }
  215. return installationIdPromise.then(function (iid) {
  216. payload._InstallationId = iid;
  217. var userController = _CoreManager.default.getUserController();
  218. if (options && typeof options.sessionToken === 'string') {
  219. return Promise.resolve(options.sessionToken);
  220. }
  221. if (userController) {
  222. return userController.currentUserAsync().then(function (user) {
  223. if (user) {
  224. return Promise.resolve(user.getSessionToken());
  225. }
  226. return Promise.resolve(null);
  227. });
  228. }
  229. return Promise.resolve(null);
  230. }).then(function (token) {
  231. if (token) {
  232. payload._SessionToken = token;
  233. }
  234. var payloadString = JSON.stringify(payload);
  235. return RESTController.ajax(method, url, payloadString, {}, options).then(function (_ref) {
  236. var response = _ref.response,
  237. status = _ref.status;
  238. if (options.returnStatus) {
  239. return (0, _extends2.default)({}, response, {
  240. _status: status
  241. });
  242. }
  243. return response;
  244. });
  245. }).catch(RESTController.handleError);
  246. },
  247. handleError: function (response) {
  248. var error;
  249. if (response && response.responseText) {
  250. try {
  251. var errorJSON = JSON.parse(response.responseText);
  252. error = new _ParseError.default(errorJSON.code, errorJSON.error);
  253. } catch (e) {
  254. error = new _ParseError.default(_ParseError.default.INVALID_JSON, "Received an error with invalid JSON from Parse: " + response.responseText);
  255. }
  256. } else {
  257. var message = response.message ? response.message : response;
  258. error = new _ParseError.default(_ParseError.default.CONNECTION_FAILED, "XMLHttpRequest failed: " + JSON.stringify(message));
  259. }
  260. return Promise.reject(error);
  261. },
  262. _setXHR: function (xhr) {
  263. XHR = xhr;
  264. },
  265. _getXHR: function () {
  266. return XHR;
  267. }
  268. };
  269. module.exports = RESTController;