Wikiup:Technik/Skin/JS/API
Auf dieser Seite wird dargestellt, wie sich API-Abfragen sowie Manipulationen mit JavaScript programmieren lassen.
Einen Einstieg zur API („Programmierschnittstelle“) für MediaWiki gibt Datenbank/API.
Überblick
Die grundlegende Technologie ist Ajax.
Dort steht das „A“ für ‚asynchron‘ – das bedeutet, dass die Aktion nur angestoßen wird. Sie läuft unabhängig im Hintergrund ab. Sofort nach dem Start wird mit der nächstfolgenden JavaScript-Anweisung fortgesetzt. In der Regel wünscht man, dass die ausgeführte Funktion wieder Kontakt mit dem auslösenden Skript aufnimmt; zumindest, um zu melden, ob die Aktion erfolgreich oder nicht ausgeführt wurde. Dies ist ausschließlich über eine Callback-Funktion möglich.
Primär ist nur der Kontakt mit derselben Domain möglich, von deren HTML-Seite im Browser das Skript gestartet wurde. Auf Wiki-Seiten sind jedoch Mechanismen aktiviert, mittels derer auch mit einem anderen Projekt kommuniziert werden kann; zumindest von einer anderen Wikipedia oder von Commons Daten abgerufen werden können.
Abfragen und Aktionen
Einfache Fragen nach öffentlich zugänglichen Informationen sind mit HTTP-GET möglich. Diese Fragen (query
) kann im Prinzip jeder Teilnehmer im Internet stellen.
Aktivitäten, die in irgendeiner Weise das Projekt verändern, sind sicherheitsrelevant und lassen sich ausschließlich mit HTTP-POST übermitteln; dies geht nicht mehr über eine einfache URL. Zur Verifizierung ist ein „Token“ erforderlich, der zuvor in der Arbeitsumgebung des Benutzers beschafft werden muss.[1] Zu den Aktivitäten gehören:
- Schreiben von Seiten-Inhalten (
editcsrf
) - Veränderungen der Beobachtungsliste (
watch
) - E-Mail verschicken
- Administrator-Funktionen (Seitenlöschung, Benutzersperrung usw.)
Bis 2015 waren für die nachstehenden Aktionen einzelne Tokens erforderlich gewesen:
edit
, move
, options
, email
sowie für Admins delete
, protect
, block
, unblock
, import
. Inzwischen ist stattdessen einheitlich csrf
(Cross-Site-Request-Forgery) zu benutzen.
Auch in eine einfache Abfrage gehen über HTTP immer Informationen über das zurzeit angemeldete Benutzerkonto ein, wenn sie aus einer Wiki-Seite heraus erfolgt; sie werden den Anmelde-Cookies entnommen: action=query&meta=tokens.
JSON
Für die Nutzung der API mit JavaScript empfiehlt sich durchgängig das JSON-Format; sowohl für Anfragen wie auch für die Interpretation der Antwort.
Die Abfrage (HTTP-GET) mit einer URL stimmt exakt überein mit der Übermittlung eines JS-Objekts, das die gleichen Parameterzuweisungen enthält.
jQuery
In allen Seiten von MediaWiki steht auch die Skriptbibliothek jQuery zur Verfügung. Sie vereinfacht das Arbeiten stark, indem eine Reihe von Basisfunktionen passend zum aktuellen Browser verfügbar gemacht werden. Diese werden auch laufend den Neuentwicklungen der Browser angepasst und können je nach deren Fähigkeiten geeignete Details festlegen, um eine möglichst effiziente Abarbeitung zu sichern.
- jQuery-Kategorie für Ajax
- jQuery.ajax() – Basisfunktion mit umfangreicher Dokumentation; aber eher nicht direkt anzuwenden.
- Besonders interessante Funktionen sind:
Allerdings empfiehlt es sich, die Unterstützung durch das mw
-Objekt in Anspruch zu nehmen, das die Handhabung weiter vereinfacht.
Vereinbarung von Callback-Funktionen
Die folgenden Funktionen können auf die Abfrage-Instanz angewendet werden:
- .done(fine)
- Definiere
fine
als Funktion, die bei erfolgreicher Ausführung aufgerufen wird. Es kann auch ein Array von Funktionen angeben werden; sogarnull
.fine(data, textStatus, jqXHR)
data
sind die erfragten Nutzdaten (JSON-Objekt).
- .fail(fault)
- Definiere
fault
als Funktion, die im Fehlerfall aufgerufen wird. Es kann auch ein Array von Funktionen angeben werden; sogarnull
.fault(jqXHR, textStatus, errorThrown)
- .always(facility)
- Definiere
facility
als Funktion, die immer aufgerufen wird (nach einer Antwort); sie erhält komplexe Informationen über Erfolg oder Misserfolg. - .then(facility)
- Definiere
facility
als Funktion, die immer sofort aufgerufen wird (auch bereits vor Eintreffen einer Antwort); sie erhält komplexe Informationen über Erfolg oder Misserfolg, falls bereits eine Antwort vorliegt.
Sowohl die mittels .done()
wie auch mittels .fail()
vereinbarte Funktion bieten zwei Parameterwerte, die bei Bedarf ausgewertet werden können:
jqXHR
gibt Details zum XMLHttpRequest an.textStatus
ist eine Zeichenkette, die in Fehlermeldungen und Protokollen vermerkt werden kann.
Technisch gesprochen geben die verschiedenen Abfrage-Funktionen ein Objekt vom Typ jQuery.Promise
zurück, das es erlaubt, beliebig viele Rückruf-Funktionen zu registrieren. Sollte man mit der Registrierung einer solchen Callback-Funktion zu spät kommen und das erwartete Ereignis bereits geschehen sein, wird trotzdem sofort zurückgerufen.
mw
-Objekt
In allen Seiten unter MediaWiki ist das mw
-Objekt vorhanden. Hier lässt sich ein besonderes Modul bereitstellen, das vereinfachte API-Abfragen unterstützt.
- Diese API-Kommunikation muss erst mittels
.loader
geladen werden; Modul:mediawiki.api
(Es könnte sein, dass es bereits vorhanden ist, weil ein anderes Skript es schon benutzt hatte; aber davon darf nicht ausgegangen werden.) - Die Programmierung in diesem Modul verwendet soweit möglich Funktionen aus jQuery und versieht sie mit Routine-Informationen zur Wiki-Anwendung.
- Quellcodes: resources/src/mediawiki/api.js
mw.Api
- .Api(defaults)
-
- Konstruiert ein neues API-Objekt, etwa: a
= new mw.Api();
oder a= new mw.Api(defaults);
. - Die Klasse
mw.Api
vereinfacht das Arbeiten insofern, als standardmäßig fünf Werte intern vorbelegt sind. Diese und beliebige andere können umdefiniert werden:
- Konstruiert ein neues API-Objekt, etwa: a
defaults.parameters
|
.action |
'query' |
API-Aktion, auch 'edit' , 'watch' und viele andere möglich.
|
.format |
'json' |
Anfrageformat | |
defaults.ajax
|
.url
|
mw.util.wikiScript('api')
|
/w/api.php String, aber auch mw.Uri |
.dataType |
'json' |
Antwort des Servers (MIME etc.) formatieren | |
.timeout |
30000 |
30 Sekunden |
Danach sind für a folgende Funktionen verfügbar:
- .abort()
- Abbruch aller noch nicht beendeten Anfragen für dieses Objekt.
- .ajax(pars, opts)
- Frei konfigurierbare Abfrage; sollte nicht direkt benutzt werden.
- .get(pars, opts)
- Abfrage mit GET-Methode starten.
- Gibt ein Objekt vom Typ
jQuery.Promise
zurück, auf das Callback-Vereinbarungen angewendet werden können. - .getToken(tokenType)
- Stelle einen Token bereit.
- .normalizeAjaxOptions()
- (eher intern benutzt)
- .post(pars, opts)
- Abfrage mit POST-Methode starten.
- Gibt ein Objekt vom Typ
jQuery.Promise
zurück, auf das Callback-Vereinbarungen angewendet werden können. - .postWithToken(tokenType, pars, opts)
- Abfrage mit POST-Methode starten, dabei automatisch für erforderlichen Token sorgen.
- pars – Objekt mit aktuellen Parametern der Abfrage: Was soll abgefragt werden?
- Konkrete Angaben sind notwendig.
- Die Parameter sind gerade die, die in den Wiki-Dokumentationen zur API beschrieben sind. pars ist in erster Näherung die Umsetzung des Query-String in ein JavaScript-Objekt.
- defaults
.parameters
ermöglicht Vorgabewerte.
- opts – Objekt mit Ajax-Optionen: Wie soll abgefragt werden?
- Früher war die Angabe von opts zwingend notwendig. Mittlerweile ist dieser Parameter optional. Wenn opts angegeben wird, darf es nicht
null
sein.- opts
.url
– Optional; Standard: Vorgabe beinew mw.Api()
- In opts
.ok
war früher die Erfolgsfunktion zu vereinbaren. Das ist inzwischen nachträglich zuzuweisen.- Es war früher eine Kurzform möglich: Erfolgsfunktion
function
als opts → opts.ok
- Es war früher eine Kurzform möglich: Erfolgsfunktion
- Genauso war als opts
.err
die Funktion für den Fehlerfall vereinbar, was ebenfalls inzwischen weggefallen ist.
- opts
- defaults
.ajax
ermöglicht Vorgabewerte. - Im Übrigen entsprechen die möglichen Optionen denen, die auch bei jQuery.ajax() als
settings
dokumentiert sind.
- Früher war die Angabe von opts zwingend notwendig. Mittlerweile ist dieser Parameter optional. Wenn opts angegeben wird, darf es nicht
- tokenType – Zeichenkette: "csrf", "login", "watch", "patrol", "rollback",
"edit", …
Generell sind bei mw.Api
noch einige statische Informationen erhältlich:
- .Api.errors[]
- Liste der schweren Fehler, die auftreten können
- .Api.warnings[]
- Liste der Warnmeldungen, die auftreten können
Elementares Beispiel
Das folgende kleine Beispiel fragt nach Informationen über das aktuelle Wiki:
var a = new mw.Api();
a.get( { meta: 'siteinfo' } )
.done( function ( answer ) { console.log( answer ); } );
- Zunächst wird als Variable
a
eine Instanz generiert. - Auf diese Instanz wird eine get-Abfrage angewendet.
- Die Vorgabe für die Aktion ist
'query'
(Abfrage). Es muss nur noch näher spezifiziert werden, was für eine Abfrage erfolgen soll; hier das Objekt:{ meta: 'siteinfo' }
- Auf den Abfrage-Aufruf
.get()
wird die Funktion.done()
angewendet. Dies ist eine von mehreren Möglichkeiten, die Callback-Funktion zu vereinbaren.- Als Argument von
.done()
wurde eine anonyme Funktion gewählt. Sie protokolliert das Resultat auf einer Konsole. Genauso könnte hier der Name einer separat definierten Funktion angegeben werden.
- Als Argument von
Dies entspricht der Abfrage: de.wikipedia.org/w/api.php?action=query&meta=siteinfo
- Die Antwort ist analog strukturiert.
mw.user
In der Komponente mw.user
des mw
-Objekts gibt es eine Funktion, mittels der sich schnell und einfach der für die Ausführung von Aktionen erforderliche Token gewinnen lässt:
mw.user.tokens.get("editToken")
- Für Seitenbearbeitung und Neuanlage von Seiten.
mw.user.tokens.get("watchToken")
- Um Seiten zu beobachten oder nicht mehr zu beobachten.
Je nachdem, mit welchen Rechten Benutzer ausgestattet sind und wie das Projekt konfiguriert ist, sind weitere Arten möglich.
- Die Komponente
mw.user
steht möglicherweise nicht von Beginn an zur Verfügung. Es empfiehlt sich, die eigentlichen Funktionen erst auszuführen, nachdem alle Module geladen sind. Weilmediawiki.api
ohnehin geladen werden muss, kann gleichzeitig auchmediawiki.user
abgefordert werden.
Zusatzmodule für mw.Api
Wenn die Aufgaben über Abfragen hinausgehen, sind unter mw:ResourceLoader/Default modules #mediawiki.api weitere Unterstützungsmodule dargestellt. Sie mussten bis Juni 2018 beim Laden der Ressourcen in die Liste aufgenommen werden. Mittlerweile wurden sie jedoch in das generelle JS-API-Modul integriert, und separate Modul-Anforderungen müssten eliminiert werden.
Die nachstehenden Funktionen können nach Laden des Moduls benutzt werden.
- Sie sind auf ein mit
a=new mw.Api();
generiertes a anzuwenden. - Sie hatten gemeinsame Parameter:
ok
– Callback-Funktion im Erfolgsfall (optional; meist empfehlenswert). Sie erhält ggf. die gewünschten Daten durch Aufruf alsok(arg)
übermittelt.err
– Callback-Funktion im Fehlerfall (optional)
- Diese Funktionsparameter
ok
underr
sind durch eine Neuerung überholt worden. Sofortiger Rückgabewert aller dieser Aufrufe ist ein Objekt vom TypjQuery.Promise
– auf dieses Objekt r kann man die jQuery-Callback-Funktionen anwenden, also mit r.done(
fine)
beliebig viele eigeneok
-Funktionen registrieren, die aufgerufen werden, sobald das Ergebnis vom Server eintrifft.
- .getCategories(title
, ok, err, async) - Finde alle Kategorien, zu denen eine bestimmte Seite
title
gehört.- Hinweis: Für die aktuell betrachtete Seite ist dies auch über
wgCategories
feststellbar.
- Hinweis: Für die aktuell betrachtete Seite ist dies auch über
- Mit
async=false
ließ sich eine synchrone Abfrage ausführen; diese konnte jegliche Browser-Aktion blockieren, bis eine Antwort eintrifft. - An
ok(arg)
wurde ein Array mit allen Titeln übergeben, sonstfalse
. Modul:mediawiki.api.category
- .getCategoriesByPrefix(prefix
, ok, err) - Finde alle Kategorien, deren Titel mit
prefix
beginnt. - An
ok(arg)
wurde ein Array mit allen Titeln übergeben. Modul:mediawiki.api.category
- .getMessages(messages)
- Frage einen Satz von Systemnachrichten in der Benutzersprache ab.
- Parameter-Format wie
ammessages
– Zeichenkette mit durch Pipes getrennter Liste von Bezeichnern, oder"*"
für ziemlich viele, oder Array mit Zeichenketten.
- Parameter-Format wie
Modul:mediawiki.api.messages
- .getUserInfo()
- Benutzergruppen und Rechte des momentanen Benutzers abfragen
Modul:mediawiki.api.user
- .isBlacklisted(title
, ok, err) - Stelle fest, ob der Seitenname
title
auf einer schwarzen Liste steht.- Mehr unter mw:Extension:TitleBlacklist
- An
ok(arg)
wurdetrue
oderfalse
übergeben. - Modul:
mediawiki.api.titleblacklist
- .isCategory(title
, ok, err) - Stelle fest, ob eine Kategorie
title
existiert. - An
ok(arg)
wurdetrue
oderfalse
übergeben. Modul:mediawiki.api.category
- .loadMessages(messages)
- Lädt einen Satz von Nachrichten in der aktuellen Benutzersprache und fügt sie
mw.messages
hinzu.- Parameter wie .getMessages()
Modul:mediawiki.api.messages
- .loadMessagesIfMissing(messages)
- Lädt einen Satz von bislang fehlender Nachrichten in der aktuellen Benutzersprache und fügt sie
mw.messages
hinzu.- Parameter wie .getMessages()
Modul:mediawiki.api.messages
- .newSection(title, header, message
, ok, err) - Hänge einen neuen Abschnitt an eine Seite an; kümmere dich selbst um einen geeigneten Token.
- Der Seiten-Name wird über
title
gesucht,header
ist die Abschnittsüberschrift undmessage
der Wikitext. Modul:mediawiki.api.edit
- .parse(wikitext
, ok, err) - Transformiere den
wikitext
analog mw:API:Parsing wikitext #parse. - An
ok(arg)
wurde ein HTML-Text übergeben. Modul:mediawiki.api.parse
- .postWithEditToken(params
, ok, err) - Führe eine Seitenbearbeitung aus; kümmere dich selbst um einen geeigneten Token.
params
ist ein JS-Objekt mit Einzelheiten (identisch mit denen, die bei einem Aufruf von.post()
anzugeben wären; also Seiten-Identifikation und neuer Text, auch Bearbeitungskommentar und „Kleine Änderung“).Modul:mediawiki.api.edit
- .saveOption(single, value)
- Wert einer Benutzereinstellung setzen
- single Schlüsselwort für die Einstellung
- value Zeichenkette oder
null
Modul:mediawiki.api.options
- .saveOptions(options)
- Werte von Benutzereinstellungen setzen
- options object als
{ name1: value1, name2: value2, ... }
- options object als
Modul:mediawiki.api.options
- .unwatch(page
, ok, err) - Entferne
page
von der persönlichen Beobachtungsliste. Modul:mediawiki.api.watch
- .watch(page
, ok, err) - Setze
page
auf die persönliche Beobachtungsliste. Modul:mediawiki.api.watch
Quellcodes:
Der logischen Vollständigkeit halber ist mediawiki.util
hier explizit mit angegeben. Tatsächlich würde bei der Auflösung der Anforderung durch den ResourceLoader die jeweils erforderliche Basis-Software auch selbsttätig nachgefordert werden; mediawiki.api
stellt mediawiki.util
sicher. Eine höhere Funktionalität wie mediawiki.api.edit
sorgt automatisch für das Laden von mediawiki.api
– es schadet aber auch nicht, dies von vornherein anzugeben, und könnte möglicherweise Abläufe beschleunigen.
Auswertung des Ergebnisses
In vielen Fällen will man dem Ergebnis Daten entnehmen; namentlich bei einer query
. Auch bei Aktivitäten liefert die Callback-Funktion eine Erfolgsmeldung.
Egal, auf welche Weise (mit oder ohne Nutzung der Funktionen in mw.Api
) erhält die Callback-Funktion für eine erfolgreiche Abfrage ein strukturiertes Objekt; vorausgesetzt, dass bei der Anfrage das Resultat als JSON zurückgeliefert werden soll, wie das standardmäßig der Fall ist.
Je nach gestellter Frage ist der erste Parameter data
in der Callback-Funktion unterschiedlich strukturiert. Die oberste Ebene ist immer ein Objekt; aber die erwarteten Komponenten sind möglicherweise nicht vorhanden, weil vermutete Seiten usw. überhaupt nicht existieren. Der direkte Zugriff auf Unterkomponenten würde dann einen Laufzeitfehler auslösen. Besser ist es, die Existenz der vermuteten Komponente jeweils abzuprüfen.
Einen ersten Überblick über die zu erwartende Struktur gibt eine interaktive Abfrage, deren XML-Ergebnis auf einer HTML-Seite dargestellt wird. Wie bei den im Manual als Beispiele angegebenen URL kann man sich an die sinnvolle Fragestellung herantasten; die Struktur des Ergebnisses wird dann identisch sein. Das Element <query>
in XML ist gleichzeitig die Komponente data.query
in JSON. Eine weitere Hilfe ist es, das eintreffende Objekt in einem JS-Debugger strukturiert darzustellen und dementsprechend die Programmstruktur zu entwickeln.
In vielen Fällen ist es sinnvoll, bei Definition einer Abfrage nach Seiten indexpageids:true
aufzunehmen. Das Ergebnis enthält dann auch ein Array mit den Seiten-Nummern, mit dessen Hilfe sich ggf. einfacher durch die einschlägige Komponente des Ergebnisses iterieren lässt.
Wenn auf die Abfrage mehr Einzelantworten lieferbar sind als mit einer Frage allein zulässigerweise beantwortet werden können, gibt es in der Antwort ein Element data["query-continue"]
– diese Komponente enthält einen Hinweis, ab welcher Seiten-Nummer usw. eine Nachfolge-Abfrage beginnen soll.
Wenn man eine unbestimmte Anzahl von Einzelergebnissen erwartet, gibt es die Möglichkeit, den jeweiligen Parameter xxlimit auf "max"
zu setzen; dies bewirkt im Regelfall 500
. Außerdem wird zurückgemeldet, zu wie vielen Einzeldaten dieser Benutzer bei diesem Typ von Abfrage berechtigt ist. Ist man tatsächlich etwa nur an dem allerjüngsten Einzelergebnis interessiert, sollte das entsprechende xxlimit auf 1
gesetzt werden, um Netzwerk-Verkehr, Server-Belastung und Antwortzeit möglichst gering zu halten.
Ausführliches Beispiel
var found = function ( data ) {
// Erfolgreich. Ergebnis analysieren.
var i, page, pageids, pages, revisions,
id = -1,
query = data.query,
k = 0;
if ( query ) {
pageids = query.pageids;
if ( pageids ) {
id = pageids[ 0 ];
}
pages = query.pages;
if ( pages && id > 0 ) {
page = pages[ id ];
if ( page ) {
revisions = page.revisions;
if ( revisions ) {
for ( i = 0; i < revisions.length; i++ ) {
if ( revisions[ i ].comment.indexOf( "rückgängig gemacht" ) > 0 ) {
k++;
}
} // for i
}
}
}
}
window.console.info( "Die Hauptseite wurde " + k + " Mal zurückgesetzt." );
if ( data[ "query-continue" ] ) {
window.console.info( "Die Hauptseite wurde mehr als 100 Mal geändert." );
}
}; // found()
var fault = function ( uhff ) {
// Fehlgeschlagen.
window.console.warn( "API-Abfrage hat nicht geklappt." );
window.console.log( uhff );
}; // fault()
var fire = function () {
// Löse eine Abfrage aus: Was sind die letzten 100 Versionen der Hauptseite?
var p = { prop: "revisions",
rvlimit: 100,
indexpageids: true,
titles: "Wikipedia:Hauptseite"
},
q = new mw.Api();
q.get( p ).done( found ).fail( fault );
}; // fire()
mw.loader.using( [ "mediawiki.api",
"mediawiki.util" ],
fire );
- Zunächst stehen die Deklarationen der Einzelfunktionen.
- Abschließend, nachdem alle Einzelfunktionen bekannt sind, werden mit mw.loader.using die Module abgefordert. Sobald sie bereit sind, wird die Funktion
fire()
aufgerufen, die ja zuvor definiert wurde. - Diese Abfrage wird gestartet.
- In der Funktion
found()
wird das Ergebnis analysiert. Dabei wird konservativ vorgegangen und das Fehlen jeder Komponente in Betracht gezogen. - Das Argument
data
enthält die Komponentequery
, die der gleichnamigen Komponente der XML-Antwort entspricht. - Weil die Anfrage
indexpageids
gefordert hatte, ist unterquery.pageids
ein Array verfügbar, das diecurid
aller gefundener Seiten aufführt. Es kommt vor, dass auch negative Seitennummern auftauchen, weil Seiten unzugänglich sind. - Die Komponente
query.pages
ist zurzeit kein Array, sondern ein Objekt. Damit sind die einzelnen Seiten nicht unmittelbar zugreifbar. Es kann iteriert werden, oder das Arrayquery.pageids
für den Zugriff genutzt werden. - Im konkreten Fall enthält
query.pageids
genau ein Element, das die momentane Seitennummer zum NamenWikipedia:Hauptseite
wiedergibt. - Nachdem damit auf die (hier einzige) Seite
page
zugegriffen wurde, kann mitpage.revisions
ein Array ausgewertet werden. - Falls eine Abfrage fortgesetzt werden soll, ist das durch Auswertung von
data[ "query-continue" ].revisions.rvcontinue
möglich; damit kann eine neue Abfrage konstruiert werden. - Wenn die Abfrage völlig fehlschlägt, wird die Funktion
fault()
aufgerufen. Sie protokolliert das Objekt mit Details. Das Fehlen von zutreffenden Daten ist in diesem Sinne kein Fehlschlag, jedoch ungültige Parametersyntax oder unerreichbarer Server.
Code-Beispiel zu query-continue
var api = new mw.Api(),
carryon = function( queryContinue ) {
var params = { action: "query",
generator: "watchlistraw",
prop: "info",
gwrlimit: "max",
gwrnamespace: "0"
},
page;
if ( queryContinue ) {
params.gwrcontinue = queryContinue;
}
api.get( params, {
Ok: function( args ) {
for ( page in args.query.pages ) {
if ( args.query.pages[ page ].missing === "" ) {
Api.unwatch( args.query.pages[ page ].title );
}
} // for
if ( args["query-continue"] ) {
carryon( args["query-continue"].watchlistraw.gwrcontinue );
} else {
alert( "all done" );
}
} // Ok()
} );
}; // carryon()
Führt eine Ent-Beobachtung im ANR aus. Es wird das maximale Limit beobachteter Artikel abgerufen, diese werden auf unbeobachtet gesetzt; sollte es mehr als das Limit geben, dann wird erneut bis zum maximalen Limit abgerufen usw.
Andere Wiki-Projekte
Mit einigen Einschränkungen ist es möglich, per API mit dem Inhalt eines anderen WMF-Projektes zu kommunizieren.
Aus Sicherheitsgründen sind derartige Aktionen außerhalb des eigenen Projektes an strikte Regeln gebunden. Die Erlaubnis zum Cross-Domain-Scripting öffnet eine fundamentale Sicherheitslücke im Konzept der Same-Origin-Policy. Ein von einer beliebigen fremden Website untergeschobener JavaScript-Code könnte fatale Folgen haben. Projektseiten der WMF kommunizieren jedoch, welchen anderen Domains sie vertrauen und ermöglichen in diesem Rahmen Cross-Origin Resource Sharing (CORS).
Insbesondere ist zur Einhaltung der Sicherheitsregeln auch streng auf das identische Protokoll http
bzw. https
zu achten.
Am einfachsten ist es, ein fremdes Projekt lediglich abzufragen.
Beispiel für eine Abfrage in einer anderen Wikipedia
var fire = function ( about, abroad ) {
// Löse eine Frage nach der jüngsten Versionsgeschichte einer Interlanguage-Seite aus.
// @param {string} about -- Name/n der gewünschten Seite/n
// @param {string} abroad -- Zwei/Drei-Buchstaben-Code der anderen Wikipedia, etwa "en"
var h = document.location.hostname,
o = { url: "//" + abroad + h.substr( h.indexOf( "." ) )
+ mw.util.wikiScript( "api" )
},
p = { prop: "revisions",
titles: about
},
q = new mw.Api();
p.origin = document.location.protocol + "//" + h;
q.get( p, o ).done( found ).fail( fault );
}; // fire()
- Die Option
o
setzt die URL der anderen Wikipedia zusammen.- Genau genommen ist es ein Interlanguage, also die gleiche (beliebige) Projekt-Art in einer anderen Sprache.
- Mit
o.url
ist anzugeben, dass eine andere URL als die in.Api
standardmäßig für das eigene Wiki vorgegebene benutzt werden soll. - Die protokoll-relative URL ist hier möglich und sinnvoll; es wird das Protokoll der umgebenden Seite geerbt.
mw.util.wikiScript("api")
holt den gültigen Pfad-Namen für API-Abfragen.- Genauso hätte dies in den
new mw.Api(defaults)
bei Bildung der Instanz angegeben werden können, wennq
mehrfach zu diesem Zweck benutzt werden soll.
- Die aktuelle Frage wird wie üblich in
p
formuliert.- Hinzu kommt aber eine Komponente
p.origin
zur Angabe des Absenders der Anfrage. - Diese Objekt-Komponente wird beim Server daraufhin geprüft, ob sie exakt mit der umgebenden HTTP-Kommunikation übereinstimmt, und ob sie den Erwartungen entspricht.
- Dabei muss das aktuelle Protokoll festgestellt werden;
wgServer
ist protokoll-relativ und eignet sich nicht.
- Hinzu kommt aber eine Komponente
- Danach kann die normale Abfrage erfolgen; das Ergebnis wird an
found()
übermittelt, bei Misserfolgfault()
aufgerufen.
mediawiki.ForeignApi
Das zuvor anzufordernde Modul mediawiki.ForeignApi
stellt Hilfsfunktionen bereit, die den Vorgang unterstützen.
Insbesondere wäre new mw.Api(defaults)
durch new mw.ForeignApi(URL,defaults)
zu ersetzen. Anschließend stehen alle Hilfsfunktionen bereit, die oben für das eigene Wiki erläutert sind.
var fire = function ( about, abroad ) {
// Löse eine Frage nach der jüngsten Versionsgeschichte einer Interlanguage-Seite aus.
// @param {string} about -- Name/n der gewünschten Seite/n
// @param {string} abroad -- Zwei/Drei-Buchstaben-Code der anderen Wikipedia, etwa "en"
var host = document.location.hostname,
url = document.location.protocol + "//"
+ abroad + host.substr( host.indexOf( "." ) )
+ mw.util.wikiScript( "api" ),
prop = { prop: "revisions",
titles: about
},
qobj = new mw.ForeignApi( url );
qobj.get( prop ).done( found ).fail( fault );
}; // fire()
REST
Um 2017 wurde eine auf REST basierende Schnittstelle produktiv eingeführt. Ob das klassische Format dann langfristig weiterhin voll unterstützt werden würde, steht dahin. Bei Verwendung der Funktionen im mw-Objekt wäre aber anzunehmen, dass Änderungen im Format der Anforderungen und des Ablaufs sich hier innerhalb der von MediaWiki programmierten Software abspielen und die JS-Objekte für Auftrag und Rückmeldung auf Anwenderseite kompatibel bleiben. Ohnehin würde eine Umschaltung von einem Tag auf den anderen alle WMF-Projekte dauerhaft zusammenbrechen lassen; es wäre also zunächst nur eine zusätzliche Technologie.
- mw:RESTBase
- v1 – Verfügbare Funktionen
- mw:API/REST proposal
Weiterentwicklung
api2.php
Es gibt Wünsche, die vorhandene Schnittstelle besser nutzbar zu machen. Dazu gehören Versionsinformationen, auf die sich eine Anforderung verlässt, und lokalisierte Nachrichten, sowie Verbesserungen in den Auswertungsmöglichkeiten des Ergebnisses. Wenn bei der Kontaktaufnahme mitgeteilt wird, auf welche API-Version sich die Programmierung verlässt, ist es möglich, dies völlig kompatibel umzusetzen, indem beim Fehlen einer derartigen Angabe konservativ geantwortet wird.
Weitere Informationen
- Wikipedia:Technik/Datenbank/API
- mw:API – englischsprachige Dokumentation der Kernfunktionen; Stammseite auf MediaWiki.
- nicht immer vollständig und aktuell
- Erweiterungen mit eigenen API-Abfragen unter mw:API extensions.
- api.php – automatisch generierte Dokumentation, die stets aktuell ist und neben Kernfunktionen auch die gültigen Erweiterungen enthält (englisch).
Anmerkungen
- ↑
Zurzeit haben alle Benutzer, also auch ohne namentliche Anmeldung, das Recht
writeapi
. Allerdings ist zumindest der aktuelle Kontext einer Wiki-Seite erforderlich (Cookies), um Tokens zu generieren. Dieser Sitzungs-Kontext entsteht automatisch durch bloßes Betrachten einer Wiki-Seite. Über das Cookie wird eine Sitzung zugeordnet, die noch nicht veraltet sein darf.