Requests for comment/API roadmap

Background
MediaWiki API has been steadily growing and adding features, and even though it provides most of the desired functionality, it has some areas in which it could be improved.

This RFC serves as an announcement of proposed breaking changes and a request for feedback on major new features. It's also Brad's todo list for after Wikimania.

Deprecation process
Discussion at the Architecture Summit in January 2014 was generally favorable to deprecations of major features, as long as we give people enough time to update. Minor changes will continue to be announced to the mediawiki-api-announce mailing list.

When it is possible for the new version of the feature to coexist with the old (e.g. prop=imageinfo and prop=fileinfo):
 * 1) The new feature will be implemented.
 * 2) The deprecation will be announced:
 * 3) * A message will be sent to the mediawiki-api-announce mailing list.
 * 4) * The old feature will report deprecation warnings.
 * 5) * Uses of the deprecated feature will be logged on the server (currently in WMF's case this is on fluorine where deployers have access).
 * 6) After a suitable timeframe (e.g. if the deprecation was in MediaWiki 1.24, during the 1.25 development cycle), usage of the deprecated feature on WMF wikis will be evaluated and the deprecated feature may be removed.

When it is not possible for the new version to coexist with the old (e.g. changing format=json):
 * 1) The new feature will be implemented, but must be explicitly requested by clients via a query parameter.
 * 2) The deprecation will be announced:
 * 3) * A message will be sent to the mediawiki-api-announce mailing list.
 * 4) * Deprecation warnings will be output when the parameter to request the new version is not given.
 * 5) * Uses of the deprecated feature will be logged privately.
 * 6) After a suitable timeframe, the new version will become the default and the old removed. The "request the new version" parameter will be silently ignored.
 * 7) The "request the new version" parameter will at some point be removed, leading to "unrecognized parameter" warnings.

When the default for a behavior is to be changed but the old behavior is not being removed (e.g. changing the default continuation to be the new easy-to-use style rather than the current query-continue):
 * 1) If not already present, a request parameter will be added to specifically request the old behavior.
 * 2) The change will be announced:
 * 3) * A message will be sent to the mediawiki-api-announce mailing list.
 * 4) * Deprecation warnings will be output when neither the select-new-version nor the select-old-version flags are used. Logs will also be made.
 * 5) After a suitable timeframe, the new version will become the default.
 * 6) Any flag to select the new version explicitly may at some point be removed, leading to "unrecognized parameter" warnings.

Remove obsolete output formats
The following output formats will be deprecated and removed:
 * wddx / wddxfm
 * yaml / yamlfm - it's identical to json anyway
 * txt / txtfm
 * dbg / dbgfm
 * dump / dumpfm

The following output formats will remain: json / jsonfm, xml / xmlfm, php / phpfm, rawfm, none.

JSON will be the preferred output format.

JSON output as default
The API currently defaults to xmlfm when no format parameter is given. This will be changed to jsonfm.

Note this will not affect modules that use their own custom output formatters. Also, action=help will be getting its own custom output formatter (see below).

As no client should be trying to parse the *fm formats, this probably won't follow a deprecation process. It'll just be done once action=help is rewritten.

Changes to JSON output format
The existing JSON format suffers from a number of shortcomings that make it more difficult to use than necessary. Many of these are inherited from the underlying data structure being designed for the XML format. Thus, the following changes are proposed.
 * The existing 'utf8' option will become the default.
 * A new 'ascii' request parameter will be introduced for clients who need all non-ASCII codepoints escaped.
 * Anything using '*' as a key will be renamed to something more natural. In some cases this may result in something like "query.page[1].foo['*']" becoming simply "query.page[1].foo", and in others something like "query.page[1].foo.content".
 * During the transition period, a 'sane=1' request parameter will request the new behavior.
 * Boolean result properties will use boolean true as the value, rather than the empty string. Whether a property will be present with a boolean false value or will continue to be entirely absent from the result when false will be determined on a case-by-case basis.
 * During the transition period, a 'sane=1' option will request the new behavior.
 * During the transition period, result parameters that are already being returned as booleans may accidentally change to the empty-string style in the non-sane output.
 * Page lists will be returned as arrays rather than objects with page_ids as keys. This will make it easier for clients to iterate over the results.
 * The 'indexpageids' parameter will be removed.
 * During the transition period, a 'pagesaslist=1' request parameter will request the new behavior.
 * The JSON formatter currently has a tendency to return values that are normally objects as arrays when empty (bug 10887). This will be fixable.

On the MediaWiki code side, developers will see the following changes:
 * If anything is currently returning boolean values as actual booleans rather than the API standard empty-string, code will need to be changed to preserve this behavior in the non-sane output. The exact code change is yet to be decided, but will be something along the lines of having to pass such boolean values through some method on ApiResult.
 * There will be a way to explicitly tag a PHP array in the result as "array" or "object", much like how ApiResult::setIndexedTagName is used for the XML format.
 * Ambiguous cases, such as empty arrays or some kinds of arrays with integer keys, might throw an error if not explicitly tagged. If this would bother you, comment!

Changes to PHP output format
The changes described above for the JSON output format will also be applied to the PHP output format, where applicable.

Changes to XML output format
Changes here will mostly be on the back-end; the actual data output to clients is intended to remain the same wherever possible. However, clients should be prepared for the following:
 * Result structure may no longer match the JSON format.
 * Tag and attribute names may be encoded when not conforming to XML requirements.
 * Result structure may change depending on the specific query. For example, passing both rvprop=content and rvdiffto=prev to prop=revisions will currently omit the diff from the result (bug 55371) (it should be throwing an error, but that's another bug). In the future, it's likely that this will return the content as the value of the node when rvdiffto is not supplied and as the value of a subnode of the node when it is.

For example, bug 43221 was fixed by changing the names of attributes such as "4::foo" to fit XML's restrictions. In the future, this would be fixed by either encoding the name (e.g. "_4.3A..3A.foo") or by changing the structure of output in only the XML format (e.g.  ).

On the MediaWiki code side, developers will see the following changes:
 * The XML formatter will no longer die if ApiResult::setIndexedTagName is forgotten. Instead, it will act as if that were called with something generic (e.g. ApiResult::setIndexedTagName( $array, 'item' )).
 * The XML formatter will no longer (be supposed to) raise an error when a node has both node content (ApiResult::setContent) and non-scalar attributes. Instead, it will simply shove the intended node content into a subnode.
 * Anything that's hard-coding '*' instead of using ApiResult::setContent is going to break.
 * There may be additional ApiResult calls required in some cases.

Changes to pretty-printed HTML formats
The pretty-printed HTML formats (jsonfm, xmlfm, phpfm, rawfm) will likely lose the automatic linking of links and various other bits of fanciness. They will gain a hook to allow for syntax highlighting via extensions such as Extension:SyntaxHighlight_GeSHi.

Removal of certain data from action=paraminfo
The data returned by action=paraminfo includes two items that appear to be at best incomplete and seem to have almost no possible uses:
 * 'props' is supposed to contain some sort of data structure indicating which result properties correspond to which request parameters. But the format of this data isn't even specified and the existing examples seem to be ad-hoc without any real consistency.
 * The intended use of this data appears to be for automatically generating objects with property accessors to wrap access to the MediaWiki API. But given the lack of any specification as to the data structure, I expect this has at most one actual user.
 * 'errors' is supposed to contain a list of possible errors that the API module can return. But the lists are incomplete, and in some cases cannot ever be complete since additional errors can be raised by extension hooks in code far removed from anything related to the API.
 * I imagine the intended use of this data is again for automatically generating strongly-typed errors in some library trying to wrap the MediaWiki API. But since the data is complete, any such library is already going to have to have a generic fallback. It would probably be best for it to use that fallback in all cases.

HTMLizing action=help
The output from action=help is currently a plain-text document wrapped in the usual API output formatting, with a few links and bolding added in post-processing when viewed via xmlfm. This will be changed to output an HTML document intended for viewing in a browser.

The default view of api.php will provide only general information and documentation of the main module (i.e. the bits of the current page above the "*** Modules ***" line and the credits at the bottom), with the various module names in the documentation for the 'format' and 'action' parameters linking to documentation for those modules. The documentation for action=query will similarly document only the query module itself, with links to documentation for the various 'prop', 'list', and 'meta' modules. There will be an option to output documentation for all modules on one page, likely 'all=1'.

At the same time, the various bits of text in the API help should be made localizable.

The possibility of including a version of Special:ApiSandbox on the help pages is also under consideration, although that may be left for a later iteration.

If anyone is actually using action=help from a client, please comment about your use cases if they wouldn't be satisfied by this proposal.

Internationalizing API warnings and errors
API warnings and errors are currently returned in English, and further multiple warnings are concatenated into a single text string.

The error codes will generally not change, this will only control the human-readable messages.

The plan is for an error-language option with the following possibilities:
 * 'none' returns the message key and parameters, no human-readable message
 * 'user' uses the language in $wgLang to generate a human-readable message
 * A language code uses the specified language

The non-'none' options would have an additional option to specify whether the message should be returned as HTML, wikitext , or wikitext ignoring site-local customizations.

Errors and warnings will both be returned as arrays of objects, each object having a code, the source module (maybe not for errors?), and message data as above.

During the transition period, omitting the error-language option will produce backwards-compatible output. After, 'user' will likely be the default.

On the code side, this will entail a major reworking of the various error and warning methods in ApiBase.

Support uselang
Some bits of the API support 'uselang' since the underlying MediaWiki methods support it. Once errors and help can be localized, it would make sense for it to offically be listed.

Token handling
API modules that perform changes must use tokens for CSRF protection. Currently there are multiple ways to retrieve a token: action=tokens, action=query&prop=info&intoken=..., action=query&prop=revisions&rvtoken=..., action=query&list=users&ustoken=..., action=query&list=recentchanges&rctoken=.... Formerly some modules would implement their own "gettoken" parameter, although now only action=login does anything like this. Further, some modules have their own "type" of token and others use the generic "edit" token type, and which is required for a particular module is not always clear. And it's not possible to fetch both the token and the data of the page to be acted on at the same time.

The following changes will be made to token handling:
 * All existing methods of retrieving tokens will be deprecated.
 * A new meta=tokens will be added to action=query. It will work just like action=tokens does, but by virtue of being a submodule of action=query you can combine it with e.g. prop=revisions to fetch both the edit token and the page content being edited.
 * The help for every 'token' parameter will clearly indicate which token type is needed. The type will also be included in action=paraminfo.
 * Many of the existing token types will probably be merged into a single 'csrf' type, as they're already all the same token.
 * All tokens will be static, not varying based on the target of the action.
 * All tokens in core and WMF-deployed extensions are already static except for action=rollback, which depends on the title and user being rolled back. API action=rollback will accept both the existing title-and-user-based token and a new static rollback token. index.php action=rollback will continue to accept only the existing title-and-user-based token.

On the code side, the token-related methods in ApiBase will be changing. Details to come later.

Removal of long-deprecated parameters
Analysis will be done to determine whether anyone is still using the following:


 * "watch" and "unwatch" parameters that have been replaced with "watchlist".
 * "sessionkey" parameter to action=upload and prop=stashimageinfo that was replaced with "filekey".
 * "toponly" parameter to list=usercontributions.
 * "querymodules" parameter to action=help, replaced with extended syntax for the "modules" parameter.
 * action=paraminfo will get the same treatment.
 * "title" parameter to action=watch.
 * "url" parameter to prop=langlinks

Additional deprecated parameters may also be considered.

Simplified continuation as default for action=query
Currently, this must be requested by passing an empty 'continue' parameter in the initial request. This will be changed to be the default, and the current query-continue may be requested with a 'rawcontinue' parameter.

Simplified continuation should indicate "pause points"
With the hard-to-understand query-continue continuation, it's easy for the client to know when it has a full batch of results for the current batch from the generator, so it can pause and process that batch before continuing the continuation.

The simplified continuation should support this sort of batching without having to parse the 'continue' parameter; a 'batchcomplete' boolean property in the result should suffice.

Query item count
People sometimes request a count(*) functionality for various modules, and even though there is plenty of justification to get it, the fundamental database limitation has always stopped us - counting all items is an O(N) table traversal. As a result, the clients could only do a full client-side iteration of all the data and count it locally. This wastes both the server resources and bandwidth.

It would be relatively simple to allow modules to return an integer from 0 to the relevant limit. For example, if  then the result in "count" mode would be a number 0 to 100 or "101+".

Comments

 * -- great idea! ☠ MarkAHershberger ☢ (talk) ☣ 18:15, 21 October 2013 (UTC)

Rewrite prop=imageinfo from scratch as prop=fileinfo
The code is a mess, the limit semantics make no sense, and we have several other options that don't really fit non-images.

The best thing to do here is probably to just write a prop=fileinfo module from scratch so we don't have to worry about backwards compatibility, and then deprecate prop=imageinfo.

Change defaults for "prop" parameters
Many query modules take a 'prop' parameter to specify which bits of information the client actually wants. Defaults for these parameters may be cut back or eliminated entirely. Or the prop parameter may be made required with no default.

Comments

 * I'm not sure if this one is really worth the trouble. Anomie (talk) 19:13, 16 July 2014 (UTC)

Allow paging the "titles" parameter
If too many titles/pageids/revids are given to the query module (or generator), it should page through them rather than erroring out or issuing a warning and ignoring some. This way client does not need to worry about passing too many titles; the query will simply treat it just like a generator, returning an appropriate continuation value.

Comments

 * Do we really want the client to be passing us 10000 titles just for us to tell them to retry 9950 of them? The client can as easily handle that on the client side, and save bandwidth in the process. Anomie (talk) 19:13, 16 July 2014 (UTC)

Extension:SiteMatrix should create a query submodule
The action added by Extension:SiteMatrix, action=sitematrix, should really be a query submodule. In addition, it's output structure could be improved.

Further, this action seems to serve much the same purpose as. They could be merged somehow.

Comments

 * Actually replacing  isn't really feasible unless we can make the output entirely compatible. And doing so would be facilitated by the following proposal. Anomie (talk) 04:31, 12 September 2013 (UTC)

should be split up
Many of the options available to 's   should be split into their own meta submodules. This would be an interface cleanliness issue.

Comments

 * -- as long as there is some sort of versioning or backwards compatibility. -- ☠ MarkAHershberger ☢ (talk) ☣ 18:15, 21 October 2013 (UTC)

Module prefix limiting
Core modules should use two-letter prefixes and extension modules should use three-letter prefixes (with 'g' prohibited as the first character). The intent here is to avoid collisions between extensions and new core modules.

Comments

 * Seems unduly limiting; some core modules already use longer prefixes, and it does nothing to prevent collisions between extensions. Anomie (talk) 04:31, 12 September 2013 (UTC)

Embed the action in the URL
To facilitate directing particular actions to different API processing clusters, it would be advantageous to include the action in the URL even for POST requests. Embedding it in the PATH_INFO may make it easier to do this, but may not be possible on all hosts. As an alternative, the API could simply require that action be present in $_GET rather than $_POST.

General discussion

 * I basically everything in this. Please drop the 'may be dropped' ones. -- Krenair  (talk &bull; contribs) 20:56, 16 July 2014 (UTC)