]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/_base/xhr.js.uncompressed.js
1 define("dojo/_base/xhr", [
6 /*===== "./declare", =====*/
19 ], function(dojo, has, require, ioq, /*===== declare, =====*/ dom
, domForm
, Deferred
, config
, json
, lang
, array
, on
, aspect
, watch
, _xhr
, util
){
24 dojo._xhrObj = function(){
26 // does the work of portably generating a new XMLHTTPRequest object.
29 dojo
._xhrObj
= _xhr
._create
;
31 var cfg
= dojo
.config
;
33 // mix in io-query and dom-form
34 dojo
.objectToQuery
= ioq
.objectToQuery
;
35 dojo
.queryToObject
= ioq
.queryToObject
;
36 dojo
.fieldToObject
= domForm
.fieldToObject
;
37 dojo
.formToObject
= domForm
.toObject
;
38 dojo
.formToQuery
= domForm
.toQuery
;
39 dojo
.formToJson
= domForm
.toJson
;
41 // need to block async callbacks from snatching this thread as the result
42 // of an async callback might call another sync XHR, this hangs khtml forever
43 // must checked by watchInFlight()
45 dojo
._blockAsync
= false;
47 // MOW: remove dojo._contentHandlers alias in 2.0
48 var handlers
= dojo
._contentHandlers
= dojo
.contentHandlers
= {
50 // A map of available XHR transport handle types. Name matches the
51 // `handleAs` attribute passed to XHR calls.
53 // A map of available XHR transport handle types. Name matches the
54 // `handleAs` attribute passed to XHR calls. Each contentHandler is
55 // called, passing the xhr object for manipulation. The return value
56 // from the contentHandler will be passed to the `load` or `handle`
57 // functions defined in the original xhr call.
59 // Creating a custom content-handler:
60 // | xhr.contentHandlers.makeCaps = function(xhr){
61 // | return xhr.responseText.toUpperCase();
66 // | handleAs:"makeCaps",
67 // | load: function(data){ /* data is a toUpper version of foo.txt */ }
70 "text": function(xhr
){
72 // A contentHandler which simply returns the plaintext response data
73 return xhr
.responseText
;
75 "json": function(xhr
){
77 // A contentHandler which returns a JavaScript object created from the response data
78 return json
.fromJson(xhr
.responseText
|| null);
80 "json-comment-filtered": function(xhr
){
82 // A contentHandler which expects comment-filtered JSON.
84 // A contentHandler which expects comment-filtered JSON.
85 // the json-comment-filtered option was implemented to prevent
86 // "JavaScript Hijacking", but it is less secure than standard JSON. Use
87 // standard JSON instead. JSON prefixing can be used to subvert hijacking.
89 // Will throw a notice suggesting to use application/json mimetype, as
90 // json-commenting can introduce security issues. To decrease the chances of hijacking,
91 // use the standard `json` contentHandler, and prefix your "JSON" with: {}&&
93 // use djConfig.useCommentedJson = true to turn off the notice
94 if(!config
.useCommentedJson
){
95 console
.warn("Consider using the standard mimetype:application/json."
96 + " json-commenting can introduce security issues. To"
97 + " decrease the chances of hijacking, use the standard the 'json' handler and"
98 + " prefix your json with: {}&&\n"
99 + "Use djConfig.useCommentedJson=true to turn off this message.");
102 var value
= xhr
.responseText
;
103 var cStartIdx
= value
.indexOf("\/*");
104 var cEndIdx
= value
.lastIndexOf("*\/");
105 if(cStartIdx
== -1 || cEndIdx
== -1){
106 throw new Error("JSON was not comment filtered");
108 return json
.fromJson(value
.substring(cStartIdx
+2, cEndIdx
));
110 "javascript": function(xhr
){
112 // A contentHandler which evaluates the response data, expecting it to be valid JavaScript
114 // FIXME: try Moz and IE specific eval variants?
115 return dojo
.eval(xhr
.responseText
);
117 "xml": function(xhr
){
119 // A contentHandler returning an XML Document parsed from the response data
120 var result
= xhr
.responseXML
;
123 if((!result
|| !result
.documentElement
)){
124 //WARNING: this branch used by the xml handling in dojo.io.iframe,
125 //so be sure to test dojo.io.iframe if making changes below.
126 var ms = function(n
){ return "MSXML" + n
+ ".DOMDocument"; };
127 var dp
= ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
128 array
.some(dp
, function(p
){
130 var dom
= new ActiveXObject(p
);
132 dom
.loadXML(xhr
.responseText
);
134 }catch(e
){ return false; }
139 return result
; // DOMDocument
141 "json-comment-optional": function(xhr
){
143 // A contentHandler which checks the presence of comment-filtered JSON and
144 // alternates between the `json` and `json-comment-filtered` contentHandlers.
145 if(xhr
.responseText
&& /^[^{\[]*\/\*/.test(xhr
.responseText
)){
146 return handlers
["json-comment-filtered"](xhr
);
148 return handlers
["json"](xhr
);
155 // kwargs function parameter definitions. Assigning to dojo namespace rather than making them local variables
156 // because they are used by dojo/io modules too
158 dojo.__IoArgs = declare(null, {
160 // URL to server endpoint.
162 // Contains properties with string values. These
163 // properties will be serialized as name1=value2 and
164 // passed in the request.
166 // Milliseconds to wait for the response. If this time
167 // passes, the then error callbacks are called.
169 // DOM node for a form. Used to extract the form values
170 // and send to the server.
171 // preventCache: Boolean?
172 // Default is false. If true, then a
173 // "dojo.preventCache" parameter is sent in the request
174 // with a value that changes with each request
175 // (timestamp). Useful only with GET-type requests.
177 // Acceptable values depend on the type of IO
178 // transport (see specific IO calls for more information).
180 // Sets the raw body for an HTTP request. If this is used, then the content
181 // property is ignored. This is mostly useful for HTTP methods that have
182 // a body to their requests, like PUT or POST. This property can be used instead
183 // of postData and putData for dojo/_base/xhr.rawXhrPost and dojo/_base/xhr.rawXhrPut respectively.
184 // ioPublish: Boolean?
185 // Set this explicitly to false to prevent publishing of topics related to
186 // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
187 // will be published via dojo/topic.publish() for different phases of an IO operation.
188 // See dojo/main.__IoPublish for a list of topics that are published.
190 load: function(response, ioArgs){
192 // This function will be
193 // called on a successful HTTP response code.
194 // ioArgs: dojo/main.__IoCallbackArgs
195 // Provides additional information about the request.
197 // The response in the format as defined with handleAs.
200 error: function(response, ioArgs){
202 // This function will
203 // be called when the request fails due to a network or server error, the url
204 // is invalid, etc. It will also be called if the load or handle callback throws an
205 // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications
206 // to continue to run even when a logic error happens in the callback, while making
207 // it easier to troubleshoot while in debug mode.
208 // ioArgs: dojo/main.__IoCallbackArgs
209 // Provides additional information about the request.
211 // The response in the format as defined with handleAs.
214 handle: function(loadOrError, response, ioArgs){
216 // This function will
217 // be called at the end of every request, whether or not an error occurs.
218 // loadOrError: String
219 // Provides a string that tells you whether this function
220 // was called because of success (load) or failure (error).
222 // The response in the format as defined with handleAs.
223 // ioArgs: dojo/main.__IoCallbackArgs
224 // Provides additional information about the request.
228 dojo.__IoCallbackArgs = declare(null, {
230 // the original object argument to the IO call.
231 // xhr: XMLHttpRequest
232 // For XMLHttpRequest calls only, the
233 // XMLHttpRequest object that was used for the
236 // The final URL used for the call. Many times it
237 // will be different than the original args.url
240 // For non-GET requests, the
241 // name1=value1&name2=value2 parameters sent up in
244 // The final indicator on how the response will be
247 // For dojo/io/script calls only, the internal
248 // script ID used for the request.
249 // canDelete: Boolean
250 // For dojo/io/script calls only, indicates
251 // whether the script tag that represents the
252 // request can be deleted after callbacks have
253 // been called. Used internally to know when
254 // cleanup can happen on JSONP-type requests.
256 // For dojo/io/script calls only: holds the JSON
257 // response for JSONP-type requests. Used
258 // internally to hold on to the JSON responses.
259 // You should not need to access it directly --
260 // the same object should be passed to the success
261 // callbacks directly.
264 dojo.__IoPublish = declare(null, {
266 // This is a list of IO topics that can be published
267 // if djConfig.ioPublish is set to true. IO topics can be
268 // published for any Input/Output, network operation. So,
269 // dojo.xhr, dojo.io.script and dojo.io.iframe can all
270 // trigger these topics to be published.
272 // "/dojo/io/start" is sent when there are no outstanding IO
273 // requests, and a new IO request is started. No arguments
274 // are passed with this topic.
276 // "/dojo/io/send" is sent whenever a new IO request is started.
277 // It passes the dojo.Deferred for the request with the topic.
279 // "/dojo/io/load" is sent whenever an IO request has loaded
280 // successfully. It passes the response and the dojo.Deferred
281 // for the request with the topic.
283 // "/dojo/io/error" is sent whenever an IO request has errored.
284 // It passes the error and the dojo.Deferred
285 // for the request with the topic.
287 // "/dojo/io/done" is sent whenever an IO request has completed,
288 // either by loading or by erroring. It passes the error and
289 // the dojo.Deferred for the request with the topic.
291 // "/dojo/io/stop" is sent when all outstanding IO requests have
292 // finished. No arguments are passed with this topic.
297 dojo
._ioSetArgs = function(/*dojo/main.__IoArgs*/args,
298 /*Function*/canceller
,
299 /*Function*/okHandler
,
300 /*Function*/errHandler
){
302 // sets up the Deferred and ioArgs property on the Deferred so it
303 // can be used in an io call.
305 // The args object passed into the public io call. Recognized properties on
306 // the args object are:
308 // The canceller function used for the Deferred object. The function
309 // will receive one argument, the Deferred object that is related to the
312 // The first OK callback to be registered with Deferred. It has the opportunity
313 // to transform the OK response. It will receive one argument -- the Deferred
314 // object returned from this function.
316 // The first error callback to be registered with Deferred. It has the opportunity
317 // to do cleanup on an error. It will receive two arguments: error (the
318 // Error object) and dfd, the Deferred object returned from this function.
320 var ioArgs
= {args
: args
, url
: args
.url
};
322 //Get values from form if requested.
323 var formObject
= null;
325 var form
= dom
.byId(args
.form
);
326 //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
327 //so use it for all. See #2844
328 var actnNode
= form
.getAttributeNode("action");
329 ioArgs
.url
= ioArgs
.url
|| (actnNode
? actnNode
.value
: null);
330 formObject
= domForm
.toObject(form
);
333 // set up the query params
337 // potentially over-ride url-provided params w/ form values
338 miArgs
.push(formObject
);
341 // stuff in content over-rides what's set by form
342 miArgs
.push(args
.content
);
344 if(args
.preventCache
){
345 miArgs
.push({"dojo.preventCache": new Date().valueOf()});
347 ioArgs
.query
= ioq
.objectToQuery(lang
.mixin
.apply(null, miArgs
));
349 // .. and the real work of getting the deferred in order, etc.
350 ioArgs
.handleAs
= args
.handleAs
|| "text";
351 var d
= new Deferred(function(dfd
){
353 canceller
&& canceller(dfd
);
355 var err
= dfd
.ioArgs
.error
;
357 err
= new Error("request cancelled");
358 err
.dojoType
="cancel";
359 dfd
.ioArgs
.error
= err
;
363 d
.addCallback(okHandler
);
365 //Support specifying load, error and handle callback functions from the args.
366 //For those callbacks, the "this" object will be the args object.
367 //The callbacks will get the deferred result value as the
368 //first argument and the ioArgs object as the second argument.
370 if(ld
&& lang
.isFunction(ld
)){
371 d
.addCallback(function(value
){
372 return ld
.call(args
, value
, ioArgs
);
375 var err
= args
.error
;
376 if(err
&& lang
.isFunction(err
)){
377 d
.addErrback(function(value
){
378 return err
.call(args
, value
, ioArgs
);
381 var handle
= args
.handle
;
382 if(handle
&& lang
.isFunction(handle
)){
383 d
.addBoth(function(value
){
384 return handle
.call(args
, value
, ioArgs
);
388 // Attach error handler last (not including topic publishing)
389 // to catch any errors that may have been generated from load
390 // or handle functions.
391 d
.addErrback(function(error
){
392 return errHandler(error
, d
);
395 //Plug in topic publishing, if dojo.publish is loaded.
396 if(cfg
.ioPublish
&& dojo
.publish
&& ioArgs
.args
.ioPublish
!== false){
399 dojo
.publish("/dojo/io/load", [d
, res
]);
403 dojo
.publish("/dojo/io/error", [d
, res
]);
407 d
.addBoth(function(res
){
408 dojo
.publish("/dojo/io/done", [d
, res
]);
415 // FIXME: need to wire up the xhr object's abort method to something
416 // analogous in the Deferred
420 var _deferredOk = function(/*Deferred*/dfd
){
422 // okHandler function for dojo._ioSetArgs call.
424 var ret
= handlers
[dfd
.ioArgs
.handleAs
](dfd
.ioArgs
.xhr
);
425 return ret
=== undefined ? null : ret
;
427 var _deferError = function(/*Error*/error
, /*Deferred*/dfd
){
429 // errHandler function for dojo._ioSetArgs call.
431 if(!dfd
.ioArgs
.args
.failOk
){
432 console
.error(error
);
437 //Use a separate count for knowing if we are starting/stopping io calls.
438 var _checkPubCount = function(dfd
){
441 if(cfg
.ioPublish
&& dojo
.publish
&& (!dfd
|| dfd
&& dfd
.ioArgs
.args
.ioPublish
!== false)){
442 dojo
.publish("/dojo/io/stop");
448 aspect
.after(watch
, "_onAction", function(){
451 aspect
.after(watch
, "_onInFlight", _checkPubCount
);
453 dojo
._ioCancelAll
= watch
.cancelAll
;
455 dojo._ioCancelAll = function(){
457 // Cancels all pending IO requests, regardless of IO type
458 // (xhr, script, iframe).
462 dojo
._ioNotifyStart = function(/*Deferred*/dfd
){
464 // If dojo.publish is available, publish topics
465 // about the start of a request queue and/or the
466 // the beginning of request.
468 // Used by IO transports. An IO transport should
469 // call this method before making the network connection.
470 if(cfg
.ioPublish
&& dojo
.publish
&& dfd
.ioArgs
.args
.ioPublish
!== false){
472 dojo
.publish("/dojo/io/start");
475 dojo
.publish("/dojo/io/send", [dfd
]);
479 dojo
._ioWatch = function(dfd
, validCheck
, ioCheck
, resHandle
){
481 // Watches the io request represented by dfd to see if it completes.
483 // The Deferred object to watch.
484 // validCheck: Function
485 // Function used to check if the IO request is still valid. Gets the dfd
486 // object as its only argument.
488 // Function used to check if basic IO call worked. Gets the dfd
489 // object as its only argument.
490 // resHandle: Function
491 // Function used to process response. Gets the dfd
492 // object as its only argument.
494 var args
= dfd
.ioArgs
.options
= dfd
.ioArgs
.args
;
496 response
: dfd
.ioArgs
,
497 isValid: function(response
){
498 return validCheck(dfd
);
500 isReady: function(response
){
503 handleResponse: function(response
){
504 return resHandle(dfd
);
512 var _defaultContentType
= "application/x-www-form-urlencoded";
514 dojo
._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs
){
516 // Adds query params discovered by the io deferred construction to the URL.
517 // Only use this for operations which are fundamentally GET-type operations.
518 if(ioArgs
.query
.length
){
519 ioArgs
.url
+= (ioArgs
.url
.indexOf("?") == -1 ? "?" : "&") + ioArgs
.query
;
525 dojo.__XhrArgs = declare(dojo.__IoArgs, {
527 // In addition to the properties listed for the dojo._IoArgs type,
528 // the following properties are allowed for dojo.xhr* methods.
530 // Acceptable values are: text (default), json, json-comment-optional,
531 // json-comment-filtered, javascript, xml. See `dojo/_base/xhr.contentHandlers`
533 // false is default. Indicates whether the request should
534 // be a synchronous (blocking) request.
536 // Additional HTTP headers to send in the request.
538 // false is default. Indicates whether a request should be
539 // allowed to fail (and therefore no console error message in
540 // the event of a failure)
541 // contentType: String|Boolean
542 // "application/x-www-form-urlencoded" is default. Set to false to
543 // prevent a Content-Type header from being sent, or to a string
544 // to send a different Content-Type.
548 dojo
.xhr = function(/*String*/ method
, /*dojo.__XhrArgs*/ args
, /*Boolean?*/ hasBody
){
550 // Deprecated. Use dojo/request instead.
552 // Sends an HTTP request with the given method.
553 // See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
554 // for those HTTP methods. There are also methods for "raw" PUT and POST methods
555 // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
557 // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase.
559 // If the request has an HTTP body, then pass true for hasBody.
562 //Make the Deferred object for this xhr request.
563 var dfd
= dojo
._ioSetArgs(args
, function(dfd
){
564 rDfd
&& rDfd
.cancel();
565 }, _deferredOk
, _deferError
);
566 var ioArgs
= dfd
.ioArgs
;
568 //Allow for specifying the HTTP body completely.
569 if("postData" in args
){
570 ioArgs
.query
= args
.postData
;
571 }else if("putData" in args
){
572 ioArgs
.query
= args
.putData
;
573 }else if("rawBody" in args
){
574 ioArgs
.query
= args
.rawBody
;
575 }else if((arguments
.length
> 2 && !hasBody
) || "POST|PUT".indexOf(method
.toUpperCase()) === -1){
576 //Check for hasBody being passed. If no hasBody,
577 //then only append query string if not a POST or PUT request.
578 dojo
._ioAddQueryToUrl(ioArgs
);
584 timeout
: args
.timeout
,
585 withCredentials
: args
.withCredentials
,
589 if(typeof args
.headers
!== 'undefined'){
590 options
.headers
= args
.headers
;
592 if(typeof args
.contentType
!== 'undefined'){
593 if(!options
.headers
){
594 options
.headers
= {};
596 options
.headers
['Content-Type'] = args
.contentType
;
598 if(typeof ioArgs
.query
!== 'undefined'){
599 options
.data
= ioArgs
.query
;
601 if(typeof args
.sync
!== 'undefined'){
602 options
.sync
= args
.sync
;
605 dojo
._ioNotifyStart(dfd
);
607 rDfd
= _xhr(ioArgs
.url
, options
, true);
609 // If XHR creation fails, dojo/request/xhr throws
610 // When this happens, cancel the deferred
616 dfd
.ioArgs
.xhr
= rDfd
.response
.xhr
;
618 rDfd
.then(function(){
620 }).otherwise(function(error
){
621 ioArgs
.error
= error
;
623 error
.status
= error
.response
.status
;
624 error
.responseText
= error
.response
.text
;
625 error
.xhr
= error
.response
.xhr
;
629 return dfd
; // dojo/_base/Deferred
632 dojo
.xhrGet = function(/*dojo.__XhrArgs*/ args
){
634 // Sends an HTTP GET request to the server.
635 return dojo
.xhr("GET", args
); // dojo/_base/Deferred
638 dojo
.rawXhrPost
= dojo
.xhrPost = function(/*dojo.__XhrArgs*/ args
){
640 // Sends an HTTP POST request to the server. In addition to the properties
641 // listed for the dojo.__XhrArgs type, the following property is allowed:
643 // String. Send raw data in the body of the POST request.
644 return dojo
.xhr("POST", args
, true); // dojo/_base/Deferred
647 dojo
.rawXhrPut
= dojo
.xhrPut = function(/*dojo.__XhrArgs*/ args
){
649 // Sends an HTTP PUT request to the server. In addition to the properties
650 // listed for the dojo.__XhrArgs type, the following property is allowed:
652 // String. Send raw data in the body of the PUT request.
653 return dojo
.xhr("PUT", args
, true); // dojo/_base/Deferred
656 dojo
.xhrDelete = function(/*dojo.__XhrArgs*/ args
){
658 // Sends an HTTP DELETE request to the server.
659 return dojo
.xhr("DELETE", args
); // dojo/_base/Deferred
663 dojo.wrapForm = function(formNode){
665 // A replacement for FormBind, but not implemented yet.
667 // FIXME: need to think harder about what extensions to this we might
668 // want. What should we allow folks to do w/ this? What events to
670 throw new Error("dojo.wrapForm not yet implemented");
674 dojo
._isDocumentOk = function(x
){
675 return util
.checkStatus(x
.status
);
678 dojo
._getText = function(url
){
680 dojo
.xhrGet({url
:url
, sync
:true, load:function(text
){
686 // Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module
687 lang
.mixin(dojo
.xhr
, {
688 _xhrObj
: dojo
._xhrObj
,
689 fieldToObject
: domForm
.fieldToObject
,
690 formToObject
: domForm
.toObject
,
691 objectToQuery
: ioq
.objectToQuery
,
692 formToQuery
: domForm
.toQuery
,
693 formToJson
: domForm
.toJson
,
694 queryToObject
: ioq
.queryToObject
,
695 contentHandlers
: handlers
,
696 _ioSetArgs
: dojo
._ioSetArgs
,
697 _ioCancelAll
: dojo
._ioCancelAll
,
698 _ioNotifyStart
: dojo
._ioNotifyStart
,
699 _ioWatch
: dojo
._ioWatch
,
700 _ioAddQueryToUrl
: dojo
._ioAddQueryToUrl
,
701 _isDocumentOk
: dojo
._isDocumentOk
,
702 _getText
: dojo
._getText
,
706 del
: dojo
.xhrDelete
// because "delete" is a reserved word