RESTController.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. "use strict";
  2. var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys");
  3. var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols");
  4. var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter");
  5. var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor");
  6. var _forEachInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/for-each");
  7. var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors");
  8. var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties");
  9. var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
  10. var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
  11. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
  12. var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof"));
  13. var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
  14. var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
  15. var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
  16. var _setTimeout2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set-timeout"));
  17. var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
  18. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  19. var _ParseError = _interopRequireDefault(require("./ParseError"));
  20. var _promiseUtils = require("./promiseUtils");
  21. function ownKeys(object, enumerableOnly) {
  22. var keys = _Object$keys(object);
  23. if (_Object$getOwnPropertySymbols) {
  24. var symbols = _Object$getOwnPropertySymbols(object);
  25. enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) {
  26. return _Object$getOwnPropertyDescriptor(object, sym).enumerable;
  27. })), keys.push.apply(keys, symbols);
  28. }
  29. return keys;
  30. }
  31. function _objectSpread(target) {
  32. for (var i = 1; i < arguments.length; i++) {
  33. var _context5, _context6;
  34. var source = null != arguments[i] ? arguments[i] : {};
  35. i % 2 ? _forEachInstanceProperty(_context5 = ownKeys(Object(source), !0)).call(_context5, function (key) {
  36. (0, _defineProperty2.default)(target, key, source[key]);
  37. }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context6 = ownKeys(Object(source))).call(_context6, function (key) {
  38. _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key));
  39. });
  40. }
  41. return target;
  42. }
  43. /**
  44. * Copyright (c) 2015-present, Parse, LLC.
  45. * All rights reserved.
  46. *
  47. * This source code is licensed under the BSD-style license found in the
  48. * LICENSE file in the root directory of this source tree. An additional grant
  49. * of patent rights can be found in the PATENTS file in the same directory.
  50. *
  51. * @flow
  52. */
  53. /* global XMLHttpRequest, XDomainRequest */
  54. var _require = require('uuid'),
  55. uuidv4 = _require.v4;
  56. var XHR = null;
  57. if (typeof XMLHttpRequest !== 'undefined') {
  58. XHR = XMLHttpRequest;
  59. }
  60. var useXDomainRequest = false;
  61. if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) {
  62. useXDomainRequest = true;
  63. }
  64. function ajaxIE9(method
  65. /*: string*/
  66. , url
  67. /*: string*/
  68. , data
  69. /*: any*/
  70. , headers
  71. /*:: ?: any*/
  72. , options
  73. /*:: ?: FullOptions*/
  74. ) {
  75. return new _promise.default(function (resolve, reject) {
  76. var xdr = new XDomainRequest();
  77. xdr.onload = function () {
  78. var response;
  79. try {
  80. response = JSON.parse(xdr.responseText);
  81. } catch (e) {
  82. reject(e);
  83. }
  84. if (response) {
  85. resolve({
  86. response: response
  87. });
  88. }
  89. };
  90. xdr.onerror = xdr.ontimeout = function () {
  91. // Let's fake a real error message.
  92. var fakeResponse = {
  93. responseText: (0, _stringify.default)({
  94. code: _ParseError.default.X_DOMAIN_REQUEST,
  95. error: "IE's XDomainRequest does not supply error info."
  96. })
  97. };
  98. reject(fakeResponse);
  99. };
  100. xdr.onprogress = function () {
  101. if (options && typeof options.progress === 'function') {
  102. options.progress(xdr.responseText);
  103. }
  104. };
  105. xdr.open(method, url);
  106. xdr.send(data);
  107. if (options && typeof options.requestTask === 'function') {
  108. options.requestTask(xdr);
  109. }
  110. });
  111. }
  112. var RESTController = {
  113. ajax: function (method
  114. /*: string*/
  115. , url
  116. /*: string*/
  117. , data
  118. /*: any*/
  119. , headers
  120. /*:: ?: any*/
  121. , options
  122. /*:: ?: FullOptions*/
  123. ) {
  124. var _context;
  125. if (useXDomainRequest) {
  126. return ajaxIE9(method, url, data, headers, options);
  127. }
  128. var promise = (0, _promiseUtils.resolvingPromise)();
  129. var isIdempotent = _CoreManager.default.get('IDEMPOTENCY') && (0, _includes.default)(_context = ['POST', 'PUT']).call(_context, method);
  130. var requestId = isIdempotent ? uuidv4() : '';
  131. var attempts = 0;
  132. var dispatch = function dispatch() {
  133. if (XHR == null) {
  134. throw new Error('Cannot make a request: No definition of XMLHttpRequest was found.');
  135. }
  136. var handled = false;
  137. var xhr = new XHR();
  138. xhr.onreadystatechange = function () {
  139. if (xhr.readyState !== 4 || handled || xhr._aborted) {
  140. return;
  141. }
  142. handled = true;
  143. if (xhr.status >= 200 && xhr.status < 300) {
  144. var response;
  145. try {
  146. response = JSON.parse(xhr.responseText);
  147. if (typeof xhr.getResponseHeader === 'function') {
  148. var _context2;
  149. if ((0, _includes.default)(_context2 = xhr.getAllResponseHeaders() || '').call(_context2, 'x-parse-job-status-id: ')) {
  150. response = xhr.getResponseHeader('x-parse-job-status-id');
  151. }
  152. }
  153. } catch (e) {
  154. promise.reject(e.toString());
  155. }
  156. if (response) {
  157. promise.resolve({
  158. response: response,
  159. status: xhr.status,
  160. xhr: xhr
  161. });
  162. }
  163. } else if (xhr.status >= 500 || xhr.status === 0) {
  164. // retry on 5XX or node-xmlhttprequest error
  165. if (++attempts < _CoreManager.default.get('REQUEST_ATTEMPT_LIMIT')) {
  166. // Exponentially-growing random delay
  167. var delay = Math.round(Math.random() * 125 * Math.pow(2, attempts));
  168. (0, _setTimeout2.default)(dispatch, delay);
  169. } else if (xhr.status === 0) {
  170. promise.reject('Unable to connect to the Parse API');
  171. } else {
  172. // After the retry limit is reached, fail
  173. promise.reject(xhr);
  174. }
  175. } else {
  176. promise.reject(xhr);
  177. }
  178. };
  179. headers = headers || {};
  180. if (typeof headers['Content-Type'] !== 'string') {
  181. // Avoid pre-flight
  182. headers['Content-Type'] = 'text/plain';
  183. }
  184. if (_CoreManager.default.get('IS_NODE')) {
  185. var _context3;
  186. headers['User-Agent'] = (0, _concat.default)(_context3 = "Parse/".concat(_CoreManager.default.get('VERSION'), " (NodeJS ")).call(_context3, process.versions.node, ")");
  187. }
  188. if (isIdempotent) {
  189. headers['X-Parse-Request-Id'] = requestId;
  190. }
  191. if (_CoreManager.default.get('SERVER_AUTH_TYPE') && _CoreManager.default.get('SERVER_AUTH_TOKEN')) {
  192. var _context4;
  193. headers.Authorization = (0, _concat.default)(_context4 = "".concat(_CoreManager.default.get('SERVER_AUTH_TYPE'), " ")).call(_context4, _CoreManager.default.get('SERVER_AUTH_TOKEN'));
  194. }
  195. var customHeaders = _CoreManager.default.get('REQUEST_HEADERS');
  196. for (var key in customHeaders) {
  197. headers[key] = customHeaders[key];
  198. }
  199. function handleProgress(type, event) {
  200. if (options && typeof options.progress === 'function') {
  201. if (event.lengthComputable) {
  202. options.progress(event.loaded / event.total, event.loaded, event.total, {
  203. type: type
  204. });
  205. } else {
  206. options.progress(null, null, null, {
  207. type: type
  208. });
  209. }
  210. }
  211. }
  212. xhr.onprogress = function (event) {
  213. handleProgress('download', event);
  214. };
  215. if (xhr.upload) {
  216. xhr.upload.onprogress = function (event) {
  217. handleProgress('upload', event);
  218. };
  219. }
  220. xhr.open(method, url, true);
  221. for (var h in headers) {
  222. xhr.setRequestHeader(h, headers[h]);
  223. }
  224. xhr.onabort = function () {
  225. promise.resolve({
  226. response: {
  227. results: []
  228. },
  229. status: 0,
  230. xhr: xhr
  231. });
  232. };
  233. xhr.send(data);
  234. if (options && typeof options.requestTask === 'function') {
  235. options.requestTask(xhr);
  236. }
  237. };
  238. dispatch();
  239. return promise;
  240. },
  241. request: function (method
  242. /*: string*/
  243. , path
  244. /*: string*/
  245. , data
  246. /*: mixed*/
  247. , options
  248. /*:: ?: RequestOptions*/
  249. ) {
  250. options = options || {};
  251. var url = _CoreManager.default.get('SERVER_URL');
  252. if (url[url.length - 1] !== '/') {
  253. url += '/';
  254. }
  255. url += path;
  256. var payload = {};
  257. if (data && (0, _typeof2.default)(data) === 'object') {
  258. for (var k in data) {
  259. payload[k] = data[k];
  260. }
  261. } // Add context
  262. var _options = options,
  263. context = _options.context;
  264. if (context !== undefined) {
  265. payload._context = context;
  266. }
  267. if (method !== 'POST') {
  268. payload._method = method;
  269. method = 'POST';
  270. }
  271. payload._ApplicationId = _CoreManager.default.get('APPLICATION_ID');
  272. var jsKey = _CoreManager.default.get('JAVASCRIPT_KEY');
  273. if (jsKey) {
  274. payload._JavaScriptKey = jsKey;
  275. }
  276. payload._ClientVersion = _CoreManager.default.get('VERSION');
  277. var _options2 = options,
  278. useMasterKey = _options2.useMasterKey;
  279. if (typeof useMasterKey === 'undefined') {
  280. useMasterKey = _CoreManager.default.get('USE_MASTER_KEY');
  281. }
  282. if (useMasterKey) {
  283. if (_CoreManager.default.get('MASTER_KEY')) {
  284. delete payload._JavaScriptKey;
  285. payload._MasterKey = _CoreManager.default.get('MASTER_KEY');
  286. }
  287. }
  288. if (_CoreManager.default.get('FORCE_REVOCABLE_SESSION')) {
  289. payload._RevocableSession = '1';
  290. }
  291. var _options3 = options,
  292. installationId = _options3.installationId;
  293. var installationIdPromise;
  294. if (installationId && typeof installationId === 'string') {
  295. installationIdPromise = _promise.default.resolve(installationId);
  296. } else {
  297. var installationController = _CoreManager.default.getInstallationController();
  298. installationIdPromise = installationController.currentInstallationId();
  299. }
  300. return installationIdPromise.then(function (iid) {
  301. payload._InstallationId = iid;
  302. var userController = _CoreManager.default.getUserController();
  303. if (options && typeof options.sessionToken === 'string') {
  304. return _promise.default.resolve(options.sessionToken);
  305. }
  306. if (userController) {
  307. return userController.currentUserAsync().then(function (user) {
  308. if (user) {
  309. return _promise.default.resolve(user.getSessionToken());
  310. }
  311. return _promise.default.resolve(null);
  312. });
  313. }
  314. return _promise.default.resolve(null);
  315. }).then(function (token) {
  316. if (token) {
  317. payload._SessionToken = token;
  318. }
  319. var payloadString = (0, _stringify.default)(payload);
  320. return RESTController.ajax(method, url, payloadString, {}, options).then(function (_ref) {
  321. var response = _ref.response,
  322. status = _ref.status;
  323. if (options.returnStatus) {
  324. return _objectSpread(_objectSpread({}, response), {}, {
  325. _status: status
  326. });
  327. }
  328. return response;
  329. });
  330. }).catch(RESTController.handleError);
  331. },
  332. handleError: function (response) {
  333. // Transform the error into an instance of ParseError by trying to parse
  334. // the error string as JSON
  335. var error;
  336. if (response && response.responseText) {
  337. try {
  338. var errorJSON = JSON.parse(response.responseText);
  339. error = new _ParseError.default(errorJSON.code, errorJSON.error);
  340. } catch (e) {
  341. // If we fail to parse the error text, that's okay.
  342. error = new _ParseError.default(_ParseError.default.INVALID_JSON, "Received an error with invalid JSON from Parse: ".concat(response.responseText));
  343. }
  344. } else {
  345. var message = response.message ? response.message : response;
  346. error = new _ParseError.default(_ParseError.default.CONNECTION_FAILED, "XMLHttpRequest failed: ".concat((0, _stringify.default)(message)));
  347. }
  348. return _promise.default.reject(error);
  349. },
  350. _setXHR: function (xhr
  351. /*: any*/
  352. ) {
  353. XHR = xhr;
  354. },
  355. _getXHR: function () {
  356. return XHR;
  357. }
  358. };
  359. module.exports = RESTController;