xhr.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. define([
  2. "./kernel",
  3. "./sniff",
  4. "require",
  5. "../io-query",
  6. /*===== "./declare", =====*/
  7. "../dom",
  8. "../dom-form",
  9. "./Deferred",
  10. "./config",
  11. "./json",
  12. "./lang",
  13. "./array",
  14. "../on",
  15. "../aspect",
  16. "../request/watch",
  17. "../request/xhr",
  18. "../request/util"
  19. ], function(dojo, has, require, ioq, /*===== declare, =====*/ dom, domForm, Deferred, config, json, lang, array, on, aspect, watch, _xhr, util){
  20. // module:
  21. // dojo/_base/xhr
  22. /*=====
  23. dojo._xhrObj = function(){
  24. // summary:
  25. // does the work of portably generating a new XMLHTTPRequest object.
  26. };
  27. =====*/
  28. dojo._xhrObj = _xhr._create;
  29. var cfg = dojo.config;
  30. // mix in io-query and dom-form
  31. dojo.objectToQuery = ioq.objectToQuery;
  32. dojo.queryToObject = ioq.queryToObject;
  33. dojo.fieldToObject = domForm.fieldToObject;
  34. dojo.formToObject = domForm.toObject;
  35. dojo.formToQuery = domForm.toQuery;
  36. dojo.formToJson = domForm.toJson;
  37. // need to block async callbacks from snatching this thread as the result
  38. // of an async callback might call another sync XHR, this hangs khtml forever
  39. // must checked by watchInFlight()
  40. dojo._blockAsync = false;
  41. // MOW: remove dojo._contentHandlers alias in 2.0
  42. var handlers = dojo._contentHandlers = dojo.contentHandlers = {
  43. // summary:
  44. // A map of available XHR transport handle types. Name matches the
  45. // `handleAs` attribute passed to XHR calls.
  46. // description:
  47. // A map of available XHR transport handle types. Name matches the
  48. // `handleAs` attribute passed to XHR calls. Each contentHandler is
  49. // called, passing the xhr object for manipulation. The return value
  50. // from the contentHandler will be passed to the `load` or `handle`
  51. // functions defined in the original xhr call.
  52. // example:
  53. // Creating a custom content-handler:
  54. // | xhr.contentHandlers.makeCaps = function(xhr){
  55. // | return xhr.responseText.toUpperCase();
  56. // | }
  57. // | // and later:
  58. // | dojo.xhrGet({
  59. // | url:"foo.txt",
  60. // | handleAs:"makeCaps",
  61. // | load: function(data){ /* data is a toUpper version of foo.txt */ }
  62. // | });
  63. "text": function(xhr){
  64. // summary:
  65. // A contentHandler which simply returns the plaintext response data
  66. return xhr.responseText;
  67. },
  68. "json": function(xhr){
  69. // summary:
  70. // A contentHandler which returns a JavaScript object created from the response data
  71. return json.fromJson(xhr.responseText || null);
  72. },
  73. "json-comment-filtered": function(xhr){
  74. // summary:
  75. // A contentHandler which expects comment-filtered JSON.
  76. // description:
  77. // A contentHandler which expects comment-filtered JSON.
  78. // the json-comment-filtered option was implemented to prevent
  79. // "JavaScript Hijacking", but it is less secure than standard JSON. Use
  80. // standard JSON instead. JSON prefixing can be used to subvert hijacking.
  81. //
  82. // Will throw a notice suggesting to use application/json mimetype, as
  83. // json-commenting can introduce security issues. To decrease the chances of hijacking,
  84. // use the standard `json` contentHandler, and prefix your "JSON" with: {}&&
  85. //
  86. // use djConfig.useCommentedJson = true to turn off the notice
  87. if(!config.useCommentedJson){
  88. console.warn("Consider using the standard mimetype:application/json."
  89. + " json-commenting can introduce security issues. To"
  90. + " decrease the chances of hijacking, use the standard the 'json' handler and"
  91. + " prefix your json with: {}&&\n"
  92. + "Use djConfig.useCommentedJson=true to turn off this message.");
  93. }
  94. var value = xhr.responseText;
  95. var cStartIdx = value.indexOf("\/*");
  96. var cEndIdx = value.lastIndexOf("*\/");
  97. if(cStartIdx == -1 || cEndIdx == -1){
  98. throw new Error("JSON was not comment filtered");
  99. }
  100. return json.fromJson(value.substring(cStartIdx+2, cEndIdx));
  101. },
  102. "javascript": function(xhr){
  103. // summary:
  104. // A contentHandler which evaluates the response data, expecting it to be valid JavaScript
  105. // FIXME: try Moz and IE specific eval variants?
  106. return dojo.eval(xhr.responseText);
  107. },
  108. "xml": function(xhr){
  109. // summary:
  110. // A contentHandler returning an XML Document parsed from the response data
  111. var result = xhr.responseXML;
  112. if(result && has("dom-qsa2.1") && !result.querySelectorAll && has("dom-parser")){
  113. // http://bugs.dojotoolkit.org/ticket/15631
  114. // IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation
  115. // returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain
  116. // the fuller-featured implementation and avoid bugs caused by the inconsistency
  117. result = new DOMParser().parseFromString(xhr.responseText, "application/xml");
  118. }
  119. if(has("ie")){
  120. if((!result || !result.documentElement)){
  121. //WARNING: this branch used by the xml handling in dojo.io.iframe,
  122. //so be sure to test dojo.io.iframe if making changes below.
  123. var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
  124. var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
  125. array.some(dp, function(p){
  126. try{
  127. var dom = new ActiveXObject(p);
  128. dom.async = false;
  129. dom.loadXML(xhr.responseText);
  130. result = dom;
  131. }catch(e){ return false; }
  132. return true;
  133. });
  134. }
  135. }
  136. return result; // DOMDocument
  137. },
  138. "json-comment-optional": function(xhr){
  139. // summary:
  140. // A contentHandler which checks the presence of comment-filtered JSON and
  141. // alternates between the `json` and `json-comment-filtered` contentHandlers.
  142. if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
  143. return handlers["json-comment-filtered"](xhr);
  144. }else{
  145. return handlers["json"](xhr);
  146. }
  147. }
  148. };
  149. /*=====
  150. // kwargs function parameter definitions. Assigning to dojo namespace rather than making them local variables
  151. // because they are used by dojo/io modules too
  152. dojo.__IoArgs = declare(null, {
  153. // url: String
  154. // URL to server endpoint.
  155. // content: Object?
  156. // Contains properties with string values. These
  157. // properties will be serialized as name1=value2 and
  158. // passed in the request.
  159. // timeout: Integer?
  160. // Milliseconds to wait for the response. If this time
  161. // passes, the then error callbacks are called.
  162. // form: DOMNode?
  163. // DOM node for a form. Used to extract the form values
  164. // and send to the server.
  165. // preventCache: Boolean?
  166. // Default is false. If true, then a
  167. // "dojo.preventCache" parameter is sent in the request
  168. // with a value that changes with each request
  169. // (timestamp). Useful only with GET-type requests.
  170. // handleAs: String?
  171. // Acceptable values depend on the type of IO
  172. // transport (see specific IO calls for more information).
  173. // rawBody: String?
  174. // Sets the raw body for an HTTP request. If this is used, then the content
  175. // property is ignored. This is mostly useful for HTTP methods that have
  176. // a body to their requests, like PUT or POST. This property can be used instead
  177. // of postData and putData for dojo/_base/xhr.rawXhrPost and dojo/_base/xhr.rawXhrPut respectively.
  178. // ioPublish: Boolean?
  179. // Set this explicitly to false to prevent publishing of topics related to
  180. // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
  181. // will be published via dojo/topic.publish() for different phases of an IO operation.
  182. // See dojo/main.__IoPublish for a list of topics that are published.
  183. load: function(response, ioArgs){
  184. // summary:
  185. // This function will be
  186. // called on a successful HTTP response code.
  187. // ioArgs: dojo/main.__IoCallbackArgs
  188. // Provides additional information about the request.
  189. // response: Object
  190. // The response in the format as defined with handleAs.
  191. },
  192. error: function(response, ioArgs){
  193. // summary:
  194. // This function will
  195. // be called when the request fails due to a network or server error, the url
  196. // is invalid, etc. It will also be called if the load or handle callback throws an
  197. // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications
  198. // to continue to run even when a logic error happens in the callback, while making
  199. // it easier to troubleshoot while in debug mode.
  200. // ioArgs: dojo/main.__IoCallbackArgs
  201. // Provides additional information about the request.
  202. // response: Object
  203. // The response in the format as defined with handleAs.
  204. },
  205. handle: function(loadOrError, response, ioArgs){
  206. // summary:
  207. // This function will
  208. // be called at the end of every request, whether or not an error occurs.
  209. // loadOrError: String
  210. // Provides a string that tells you whether this function
  211. // was called because of success (load) or failure (error).
  212. // response: Object
  213. // The response in the format as defined with handleAs.
  214. // ioArgs: dojo/main.__IoCallbackArgs
  215. // Provides additional information about the request.
  216. }
  217. });
  218. dojo.__IoCallbackArgs = declare(null, {
  219. // args: Object
  220. // the original object argument to the IO call.
  221. // xhr: XMLHttpRequest
  222. // For XMLHttpRequest calls only, the
  223. // XMLHttpRequest object that was used for the
  224. // request.
  225. // url: String
  226. // The final URL used for the call. Many times it
  227. // will be different than the original args.url
  228. // value.
  229. // query: String
  230. // For non-GET requests, the
  231. // name1=value1&name2=value2 parameters sent up in
  232. // the request.
  233. // handleAs: String
  234. // The final indicator on how the response will be
  235. // handled.
  236. // id: String
  237. // For dojo/io/script calls only, the internal
  238. // script ID used for the request.
  239. // canDelete: Boolean
  240. // For dojo/io/script calls only, indicates
  241. // whether the script tag that represents the
  242. // request can be deleted after callbacks have
  243. // been called. Used internally to know when
  244. // cleanup can happen on JSONP-type requests.
  245. // json: Object
  246. // For dojo/io/script calls only: holds the JSON
  247. // response for JSONP-type requests. Used
  248. // internally to hold on to the JSON responses.
  249. // You should not need to access it directly --
  250. // the same object should be passed to the success
  251. // callbacks directly.
  252. });
  253. dojo.__IoPublish = declare(null, {
  254. // summary:
  255. // This is a list of IO topics that can be published
  256. // if djConfig.ioPublish is set to true. IO topics can be
  257. // published for any Input/Output, network operation. So,
  258. // dojo.xhr, dojo.io.script and dojo.io.iframe can all
  259. // trigger these topics to be published.
  260. // start: String
  261. // "/dojo/io/start" is sent when there are no outstanding IO
  262. // requests, and a new IO request is started. No arguments
  263. // are passed with this topic.
  264. // send: String
  265. // "/dojo/io/send" is sent whenever a new IO request is started.
  266. // It passes the dojo.Deferred for the request with the topic.
  267. // load: String
  268. // "/dojo/io/load" is sent whenever an IO request has loaded
  269. // successfully. It passes the response and the dojo.Deferred
  270. // for the request with the topic.
  271. // error: String
  272. // "/dojo/io/error" is sent whenever an IO request has errored.
  273. // It passes the error and the dojo.Deferred
  274. // for the request with the topic.
  275. // done: String
  276. // "/dojo/io/done" is sent whenever an IO request has completed,
  277. // either by loading or by erroring. It passes the error and
  278. // the dojo.Deferred for the request with the topic.
  279. // stop: String
  280. // "/dojo/io/stop" is sent when all outstanding IO requests have
  281. // finished. No arguments are passed with this topic.
  282. });
  283. =====*/
  284. dojo._ioSetArgs = function(/*dojo/main.__IoArgs*/args,
  285. /*Function*/canceller,
  286. /*Function*/okHandler,
  287. /*Function*/errHandler){
  288. // summary:
  289. // sets up the Deferred and ioArgs property on the Deferred so it
  290. // can be used in an io call.
  291. // args:
  292. // The args object passed into the public io call. Recognized properties on
  293. // the args object are:
  294. // canceller:
  295. // The canceller function used for the Deferred object. The function
  296. // will receive one argument, the Deferred object that is related to the
  297. // canceller.
  298. // okHandler:
  299. // The first OK callback to be registered with Deferred. It has the opportunity
  300. // to transform the OK response. It will receive one argument -- the Deferred
  301. // object returned from this function.
  302. // errHandler:
  303. // The first error callback to be registered with Deferred. It has the opportunity
  304. // to do cleanup on an error. It will receive two arguments: error (the
  305. // Error object) and dfd, the Deferred object returned from this function.
  306. var ioArgs = {args: args, url: args.url};
  307. //Get values from form if requested.
  308. var formObject = null;
  309. if(args.form){
  310. var form = dom.byId(args.form);
  311. //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
  312. //so use it for all. See #2844
  313. var actnNode = form.getAttributeNode("action");
  314. ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
  315. formObject = domForm.toObject(form);
  316. }
  317. // set up the query params
  318. var miArgs = [{}];
  319. if(formObject){
  320. // potentially over-ride url-provided params w/ form values
  321. miArgs.push(formObject);
  322. }
  323. if(args.content){
  324. // stuff in content over-rides what's set by form
  325. miArgs.push(args.content);
  326. }
  327. if(args.preventCache){
  328. miArgs.push({"dojo.preventCache": new Date().valueOf()});
  329. }
  330. ioArgs.query = ioq.objectToQuery(lang.mixin.apply(null, miArgs));
  331. // .. and the real work of getting the deferred in order, etc.
  332. ioArgs.handleAs = args.handleAs || "text";
  333. var d = new Deferred(function(dfd){
  334. dfd.canceled = true;
  335. canceller && canceller(dfd);
  336. var err = dfd.ioArgs.error;
  337. if(!err){
  338. err = new Error("request cancelled");
  339. err.dojoType="cancel";
  340. dfd.ioArgs.error = err;
  341. }
  342. return err;
  343. });
  344. d.addCallback(okHandler);
  345. //Support specifying load, error and handle callback functions from the args.
  346. //For those callbacks, the "this" object will be the args object.
  347. //The callbacks will get the deferred result value as the
  348. //first argument and the ioArgs object as the second argument.
  349. var ld = args.load;
  350. if(ld && lang.isFunction(ld)){
  351. d.addCallback(function(value){
  352. return ld.call(args, value, ioArgs);
  353. });
  354. }
  355. var err = args.error;
  356. if(err && lang.isFunction(err)){
  357. d.addErrback(function(value){
  358. return err.call(args, value, ioArgs);
  359. });
  360. }
  361. var handle = args.handle;
  362. if(handle && lang.isFunction(handle)){
  363. d.addBoth(function(value){
  364. return handle.call(args, value, ioArgs);
  365. });
  366. }
  367. // Attach error handler last (not including topic publishing)
  368. // to catch any errors that may have been generated from load
  369. // or handle functions.
  370. d.addErrback(function(error){
  371. return errHandler(error, d);
  372. });
  373. //Plug in topic publishing, if dojo.publish is loaded.
  374. if(cfg.ioPublish && dojo.publish && ioArgs.args.ioPublish !== false){
  375. d.addCallbacks(
  376. function(res){
  377. dojo.publish("/dojo/io/load", [d, res]);
  378. return res;
  379. },
  380. function(res){
  381. dojo.publish("/dojo/io/error", [d, res]);
  382. return res;
  383. }
  384. );
  385. d.addBoth(function(res){
  386. dojo.publish("/dojo/io/done", [d, res]);
  387. return res;
  388. });
  389. }
  390. d.ioArgs = ioArgs;
  391. // FIXME: need to wire up the xhr object's abort method to something
  392. // analogous in the Deferred
  393. return d;
  394. };
  395. var _deferredOk = function(/*Deferred*/dfd){
  396. // summary:
  397. // okHandler function for dojo._ioSetArgs call.
  398. var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
  399. return ret === undefined ? null : ret;
  400. };
  401. var _deferError = function(/*Error*/error, /*Deferred*/dfd){
  402. // summary:
  403. // errHandler function for dojo._ioSetArgs call.
  404. if(!dfd.ioArgs.args.failOk){
  405. console.error(error);
  406. }
  407. return error;
  408. };
  409. //Use a separate count for knowing if we are starting/stopping io calls.
  410. var _checkPubCount = function(dfd){
  411. if(_pubCount <= 0){
  412. _pubCount = 0;
  413. if(cfg.ioPublish && dojo.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
  414. dojo.publish("/dojo/io/stop");
  415. }
  416. }
  417. };
  418. var _pubCount = 0;
  419. aspect.after(watch, "_onAction", function(){
  420. _pubCount -= 1;
  421. });
  422. aspect.after(watch, "_onInFlight", _checkPubCount);
  423. dojo._ioCancelAll = watch.cancelAll;
  424. /*=====
  425. dojo._ioCancelAll = function(){
  426. // summary:
  427. // Cancels all pending IO requests, regardless of IO type
  428. // (xhr, script, iframe).
  429. };
  430. =====*/
  431. dojo._ioNotifyStart = function(/*Deferred*/dfd){
  432. // summary:
  433. // If dojo.publish is available, publish topics
  434. // about the start of a request queue and/or the
  435. // the beginning of request.
  436. //
  437. // Used by IO transports. An IO transport should
  438. // call this method before making the network connection.
  439. if(cfg.ioPublish && dojo.publish && dfd.ioArgs.args.ioPublish !== false){
  440. if(!_pubCount){
  441. dojo.publish("/dojo/io/start");
  442. }
  443. _pubCount += 1;
  444. dojo.publish("/dojo/io/send", [dfd]);
  445. }
  446. };
  447. dojo._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
  448. // summary:
  449. // Watches the io request represented by dfd to see if it completes.
  450. // dfd: Deferred
  451. // The Deferred object to watch.
  452. // validCheck: Function
  453. // Function used to check if the IO request is still valid. Gets the dfd
  454. // object as its only argument.
  455. // ioCheck: Function
  456. // Function used to check if basic IO call worked. Gets the dfd
  457. // object as its only argument.
  458. // resHandle: Function
  459. // Function used to process response. Gets the dfd
  460. // object as its only argument.
  461. var args = dfd.ioArgs.options = dfd.ioArgs.args;
  462. lang.mixin(dfd, {
  463. response: dfd.ioArgs,
  464. isValid: function(response){
  465. return validCheck(dfd);
  466. },
  467. isReady: function(response){
  468. return ioCheck(dfd);
  469. },
  470. handleResponse: function(response){
  471. return resHandle(dfd);
  472. }
  473. });
  474. watch(dfd);
  475. _checkPubCount(dfd);
  476. };
  477. var _defaultContentType = "application/x-www-form-urlencoded";
  478. dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
  479. // summary:
  480. // Adds query params discovered by the io deferred construction to the URL.
  481. // Only use this for operations which are fundamentally GET-type operations.
  482. if(ioArgs.query.length){
  483. ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
  484. ioArgs.query = null;
  485. }
  486. };
  487. /*=====
  488. dojo.__XhrArgs = declare(dojo.__IoArgs, {
  489. // summary:
  490. // In addition to the properties listed for the dojo._IoArgs type,
  491. // the following properties are allowed for dojo.xhr* methods.
  492. // handleAs: String?
  493. // Acceptable values are: text (default), json, json-comment-optional,
  494. // json-comment-filtered, javascript, xml. See `dojo/_base/xhr.contentHandlers`
  495. // sync: Boolean?
  496. // false is default. Indicates whether the request should
  497. // be a synchronous (blocking) request.
  498. // headers: Object?
  499. // Additional HTTP headers to send in the request.
  500. // failOk: Boolean?
  501. // false is default. Indicates whether a request should be
  502. // allowed to fail (and therefore no console error message in
  503. // the event of a failure)
  504. // contentType: String|Boolean
  505. // "application/x-www-form-urlencoded" is default. Set to false to
  506. // prevent a Content-Type header from being sent, or to a string
  507. // to send a different Content-Type.
  508. });
  509. =====*/
  510. dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
  511. // summary:
  512. // Deprecated. Use dojo/request instead.
  513. // description:
  514. // Sends an HTTP request with the given method.
  515. // See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
  516. // for those HTTP methods. There are also methods for "raw" PUT and POST methods
  517. // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
  518. // method:
  519. // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase.
  520. // hasBody:
  521. // If the request has an HTTP body, then pass true for hasBody.
  522. var rDfd;
  523. //Make the Deferred object for this xhr request.
  524. var dfd = dojo._ioSetArgs(args, function(dfd){
  525. rDfd && rDfd.cancel();
  526. }, _deferredOk, _deferError);
  527. var ioArgs = dfd.ioArgs;
  528. //Allow for specifying the HTTP body completely.
  529. if("postData" in args){
  530. ioArgs.query = args.postData;
  531. }else if("putData" in args){
  532. ioArgs.query = args.putData;
  533. }else if("rawBody" in args){
  534. ioArgs.query = args.rawBody;
  535. }else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) === -1){
  536. //Check for hasBody being passed. If no hasBody,
  537. //then only append query string if not a POST or PUT request.
  538. dojo._ioAddQueryToUrl(ioArgs);
  539. }
  540. var options = {
  541. method: method,
  542. handleAs: "text",
  543. timeout: args.timeout,
  544. withCredentials: args.withCredentials,
  545. ioArgs: ioArgs
  546. };
  547. if(typeof args.headers !== 'undefined'){
  548. options.headers = args.headers;
  549. }
  550. if(typeof args.contentType !== 'undefined'){
  551. if(!options.headers){
  552. options.headers = {};
  553. }
  554. options.headers['Content-Type'] = args.contentType;
  555. }
  556. if(typeof ioArgs.query !== 'undefined'){
  557. options.data = ioArgs.query;
  558. }
  559. if(typeof args.sync !== 'undefined'){
  560. options.sync = args.sync;
  561. }
  562. dojo._ioNotifyStart(dfd);
  563. try{
  564. rDfd = _xhr(ioArgs.url, options, true);
  565. }catch(e){
  566. // If XHR creation fails, dojo/request/xhr throws
  567. // When this happens, cancel the deferred
  568. dfd.cancel();
  569. return dfd;
  570. }
  571. // sync ioArgs
  572. dfd.ioArgs.xhr = rDfd.response.xhr;
  573. rDfd.then(function(){
  574. dfd.resolve(dfd);
  575. }).otherwise(function(error){
  576. ioArgs.error = error;
  577. if(error.response){
  578. error.status = error.response.status;
  579. error.responseText = error.response.text;
  580. error.xhr = error.response.xhr;
  581. }
  582. dfd.reject(error);
  583. });
  584. return dfd; // dojo/_base/Deferred
  585. };
  586. dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
  587. // summary:
  588. // Sends an HTTP GET request to the server.
  589. return dojo.xhr("GET", args); // dojo/_base/Deferred
  590. };
  591. dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
  592. // summary:
  593. // Sends an HTTP POST request to the server. In addition to the properties
  594. // listed for the dojo.__XhrArgs type, the following property is allowed:
  595. // postData:
  596. // String. Send raw data in the body of the POST request.
  597. return dojo.xhr("POST", args, true); // dojo/_base/Deferred
  598. };
  599. dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
  600. // summary:
  601. // Sends an HTTP PUT request to the server. In addition to the properties
  602. // listed for the dojo.__XhrArgs type, the following property is allowed:
  603. // putData:
  604. // String. Send raw data in the body of the PUT request.
  605. return dojo.xhr("PUT", args, true); // dojo/_base/Deferred
  606. };
  607. dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
  608. // summary:
  609. // Sends an HTTP DELETE request to the server.
  610. return dojo.xhr("DELETE", args); // dojo/_base/Deferred
  611. };
  612. /*
  613. dojo.wrapForm = function(formNode){
  614. // summary:
  615. // A replacement for FormBind, but not implemented yet.
  616. // FIXME: need to think harder about what extensions to this we might
  617. // want. What should we allow folks to do w/ this? What events to
  618. // set/send?
  619. throw new Error("dojo.wrapForm not yet implemented");
  620. }
  621. */
  622. dojo._isDocumentOk = function(x){
  623. return util.checkStatus(x.status);
  624. };
  625. dojo._getText = function(url){
  626. var result;
  627. dojo.xhrGet({url:url, sync:true, load:function(text){
  628. result = text;
  629. }});
  630. return result;
  631. };
  632. // Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module
  633. lang.mixin(dojo.xhr, {
  634. _xhrObj: dojo._xhrObj,
  635. fieldToObject: domForm.fieldToObject,
  636. formToObject: domForm.toObject,
  637. objectToQuery: ioq.objectToQuery,
  638. formToQuery: domForm.toQuery,
  639. formToJson: domForm.toJson,
  640. queryToObject: ioq.queryToObject,
  641. contentHandlers: handlers,
  642. _ioSetArgs: dojo._ioSetArgs,
  643. _ioCancelAll: dojo._ioCancelAll,
  644. _ioNotifyStart: dojo._ioNotifyStart,
  645. _ioWatch: dojo._ioWatch,
  646. _ioAddQueryToUrl: dojo._ioAddQueryToUrl,
  647. _isDocumentOk: dojo._isDocumentOk,
  648. _getText: dojo._getText,
  649. get: dojo.xhrGet,
  650. post: dojo.xhrPost,
  651. put: dojo.xhrPut,
  652. del: dojo.xhrDelete // because "delete" is a reserved word
  653. });
  654. return dojo.xhr;
  655. });