1 /* mw.Api objects represent the API of a particular MediaWiki server. */
3 ( function( $, mw
, undefined ) {
6 * @var defaultOptions {Object}
7 * We allow people to omit these default parameters from API requests
8 * there is very customizable error handling here, on a per-call basis
9 * wondering, would it be simpler to make it easy to clone the api object,
10 * change error handling, and use that instead?
12 var defaultOptions
= {
14 // Query parameters for API requests
20 // Ajax options for jQuery.ajax()
22 url
: mw
.util
.wikiScript( 'api' ),
26 // caller can supply handlers for http transport error or api errors
27 err: function( code
, result
) {
28 mw
.log( 'mw.Api error: ' + code
, 'debug' );
31 timeout
: 30000, // 30 seconds
38 * Constructor to create an object to interact with the API of a particular MediaWiki server.
40 * @todo Share API objects with exact same config.
43 * var api = new mw.Api();
48 * ok: function () { console.log( arguments ); }
53 * @param options {Object} See defaultOptions documentation above. Ajax options can also be
54 * overridden for each individual request to jQuery.ajax() later on.
56 mw
.Api = function( options
) {
58 if ( options
=== undefined ) {
62 // Force toString if we got a mw.Uri object
63 if ( options
.ajax
&& options
.ajax
.url
!== undefined ) {
64 options
.ajax
.url
= String( options
.ajax
.url
);
67 options
.parameters
= $.extend( {}, defaultOptions
.parameters
, options
.parameters
);
68 options
.ajax
= $.extend( {}, defaultOptions
.ajax
, options
.ajax
);
70 this.defaults
= options
;
76 * For api queries, in simple cases the caller just passes a success callback.
77 * In complex cases they pass an object with a success property as callback and
78 * probably other options.
79 * Normalize the argument so that it's always the latter case.
81 * @param {Object|Function} An object contaning one or more of options.ajax,
82 * or just a success function (options.ajax.ok).
83 * @return {Object} Normalized ajax options.
85 normalizeAjaxOptions: function( arg
) {
87 if ( typeof arg
=== 'function' ) {
91 throw new Error( 'ajax options must include ok callback' );
97 * Perform API get request
99 * @param {Object} request parameters
100 * @param {Object|Function} ajax options, or just a success function
103 get: function( parameters
, ajaxOptions
) {
104 ajaxOptions
= this.normalizeAjaxOptions( ajaxOptions
);
105 ajaxOptions
.type
= 'GET';
106 return this.ajax( parameters
, ajaxOptions
);
110 * Perform API post request
111 * @todo Post actions for nonlocal will need proxy
113 * @param {Object} request parameters
114 * @param {Object|Function} ajax options, or just a success function
117 post: function( parameters
, ajaxOptions
) {
118 ajaxOptions
= this.normalizeAjaxOptions( ajaxOptions
);
119 ajaxOptions
.type
= 'POST';
120 return this.ajax( parameters
, ajaxOptions
);
124 * Perform the API call.
126 * @param {Object} request parameters
127 * @param {Object} ajax options
130 ajax: function( parameters
, ajaxOptions
) {
132 parameters
= $.extend( {}, this.defaults
.parameters
, parameters
);
133 ajaxOptions
= $.extend( {}, this.defaults
.ajax
, ajaxOptions
);
135 // Ensure that token parameter is last (per [[mw:API:Edit#Token]]).
136 if ( parameters
.token
) {
137 token
= parameters
.token
;
138 delete parameters
.token
;
140 // Some deployed MediaWiki >= 1.17 forbid periods in URLs, due to an IE XSS bug
141 // So let's escape them here. See bug #28235
142 // This works because jQuery accepts data as a query string or as an Object
143 ajaxOptions
.data
= $.param( parameters
).replace( /\./g, '%2E' );
144 // If we extracted a token parameter, add it back in.
146 ajaxOptions
.data
+= '&token=' + encodeURIComponent( token
);
148 ajaxOptions
.error = function( xhr
, textStatus
, exception
) {
149 ajaxOptions
.err( 'http', {
151 textStatus
: textStatus
,
156 // Success just means 200 OK; also check for output and API errors
157 ajaxOptions
.success = function( result
) {
158 if ( result
=== undefined || result
=== null || result
=== '' ) {
159 ajaxOptions
.err( 'ok-but-empty',
160 'OK response but empty result (check HTTP headers?)' );
161 } else if ( result
.error
) {
162 var code
= result
.error
.code
=== undefined ? 'unknown' : result
.error
.code
;
163 ajaxOptions
.err( code
, result
);
165 ajaxOptions
.ok( result
);
169 return $.ajax( ajaxOptions
);
175 * @var {Array} List of errors we might receive from the API.
176 * For now, this just documents our expectation that there should be similar messages
180 // occurs when POST aborted
181 // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result
187 // really a warning, but we treat it like an error
191 // upload succeeded, but no image info.
192 // this is probably impossible, but might as well check for it
194 // remote errors, defined in API
203 'copyuploaddisabled',
211 'verification-error',
218 'fileexists-shared-forbidden',
224 * @var {Array} List of warnings we might receive from the API.
225 * For now, this just documents our expectation that there should be similar messages
233 })( jQuery
, mediaWiki
);