providing: API Level 2 // der REST ist ein Endpunkt

  • 13.02.2012
  • Support
  • keine Kommentare

Neues aus der Entwicklungsabteilung

Wer keine Lust hat, diesen Artikel zu lesen und einfach nur unsere neue DNS-API benutzen will, kann auch einfach seinen Client starten und den Rest auslassen 😎

„Die Galaxie bleibt nicht, wie sie ist. Sie ändert sich von Tag zu Tag und auch wir müssen uns ändern und stärker werden, um den neuen Herausforderungen gerecht zu werden. Als Jedi können wir es uns niemals erlauben, träge und selbstgefällig zu werden. Wir müssen stets wachsam bleiben, immer auf das achten, was um uns herum geschieht, und bereit sein, uns wechselnden Umständen anzupassen.“
Luke

Providing Interfaces

Inmitten all der aufregenden Abenteuer, die das Providerleben so bietet, haben wir bei http.net mal kurz die Zeit angehalten, um Bausteine für die Zukunft zu sortieren. Es liegen mehr als 10 Jahre Schnittstellentechnologie hinter uns, und mittlerweile ist ein bunter Zoo von Clients aller Art entstanden, die permanent mit Registrierungsstellen und Lieferanten aller Art und in aller Welt kommunizieren, damit wir selbst wiederum als Dienst unseren Partnern all diese Dienste in möglichst übersichtlicher Form zur Verfügung stellen können. Das Spannende am Internet ist, dass es noch lernt, und wir lernen mit ihm zusammen: wir lernen, in Schnittstellen zu denken.

http.net API

Denken wir mal über die Armaturen hinaus, also das User-Interface, das in Form von Weboberflächen, Robots oder SOAP-Diensten daherkommt, und nennen wir die Basis dahinter die API. Die API bietet einen Dienstvertrag, also eine Menge von Operationen zur Erhebung und Manipulation von Daten, die im weiteren Sinne in verteilten Datenbanken hinterlegt sind (wie z.B. Registries, DNS- oder Whois-Server). Unabhängig von der Kodierung (z.B. in XML, JSON oder als E-Mail-Template) kann man die Struktur der Daten am besten in Form von Objekten beschreiben.

Wie kann man Bedingungen beschreiben?

Der Client verwendet eine Operation, also er sendet ein Objekt unter Hinweis auf eine bestimmte Verabredung zur Verarbeitung an den Dienst und erhält ein Objekt als Antwort zurück. Das impliziert zunächst, dass die gesendeten Daten in vereinbarter Weise strukturiert sind, damit der Dienst überhaupt erkennt, welche Bedingungen erfüllt sein sollen. Wenn er die Daten erfolgreich einem Schema zugeordnet hat, schickt er sie durch einen vierstufigen Validierungsprozess:

  • Zugriffskontrolle für die Operation (OperationAccess)
  • Validierung der Daten gegen definierte Bedingungen (DataValidation)
  • Konsistenz von Operation, Daten und und Datenbank (DataConsistency)
  • Zugriffskontrolle für die Daten und die Datenbank (DataAccess)

Innerhalb dieser Stufen sind einzelne Bedingungen zu prüfen: z.B. ist der Wert eines Datenfeldes für Domainnamen gegen die syntaktischen Regeln zu validieren, die durch das RFC für Domainnamen und die zuständige Registry vorgegeben sind (DataValidation), während es eine Frage der Datenkonsistenz ist, dass eine bereits registrierte Domain nicht erneut registriert werden kann (DataConsistency), und schließlich sichergestellt sein muss, dass nur berechtigte Clients eine bestehende Domain verändern können (DataAccess).

Je nachdem, wie viele weitere Parteien in die Transaktion involviert sind und je nachdem, wie deterministisch sie ist, kann das Resultat kompliziert sein. Zum Beispiel birgt ein Domaintransfer einige Unwägbarkeiten, wenn mehrere Parteien mit mehr oder weniger vorhersagbarem Verhalten an einem Prozess beteiligt sind, der verschiedene Zustände annehmen kann. Das Anlegen einer DNS-Zone ist dagegen sehr einfach, denn die DNS-Server sind nur spezielle Datenbanken, die in unseren eigenen Rechenzentren stehen, so dass sich das Resultat im Wesentlichen aus den Anfangsbedingungen ergibt und unmittelbar zur Verfügung steht. Deshalb haben wir uns entschieden, die schon lange geplante DNS-API als Prototyp für einen neuen Architekturstil zu implementieren.

Gekoppelte Prozesse und implizite Abhängigkeiten

Früher hat man Dienste als Prozess programmiert, also irgendwo in den Tiefen verschachtelter Prozeduren Bedingungen in Form von IF-THEN-ELSE-Verzweigungen vergraben. Dann hat man hinterher den Programmierer gefragt, was er da gemacht hat, und das bestenfalls in eine Dokumentation geschrieben oder sich einfach gemerkt.

codinghorror1

Daraus ergeben sich Dialoge wie dieser:

  • $Kunde an $Support: „Was hat diese Fehlermeldung zu bedeuten?“
  • $Support an $Programmierer: „Was hat diese Fehlermeldung zu bedeuten?“
  • $Programmierer an $Support: „Schwer zu sagem das hat $ExKollege1 so programmiert, wahrscheinlich weil $ExKollege2 das wollte.“
  • $Support an $Programmierer: „Kann man das nicht besser lösen?“
  • $Programmierer an $Support: „Hm, schon, aber wenn man das in $Modul1 ändert, könnte auch $Modul2 betroffen sein …“
  • $Support an $Kunde: „Bitte haben Sie etwas Geduld, die Technik arbeitet daran.“

Der Trick mit der deklarativen Architektur

Wir wollen, dass unser Support weniger Arbeit hat. Deshalb erfinden wir den Begriff der Bedingung neu. Wir erklären Bedingungen zu Attributen, die an Operationen, Datenobjekte oder Datenfelder gebunden werden können, also zu eigenständigen Objekten mit Eigenschaften und Fähigkeiten. Eine solche programmierte Bedingung nennen wir ein Constraint. (Den freundlichen Support wird es natürlich trotzdem weiterhin geben :-))

code

Dieser Ansatz mag auf den ersten Blick etwas akademisch wirken, doch er vereinfacht enorm die Verwaltung von Bedingungen und bildet die Basis für ein Höchstmaß an Flexibilität und Skalierbarkeit. Um es konkret zu machen, ein Constraint soll:

  • eine informelle technische Beschreibung seiner Bedingungen bieten,
  • eine Validierungsfunktion für bestimmte Eingangsdaten bereitstellen, und
  • im Fall des Fehlschlagens der Validierung eine genaue Begründung liefern.

Zum Beispiel definiert die API ein Datenobjekt namens ARecord, das ein Feld namens ipv4 enthält. Dies ist auf der Ebene der Schema-Definition nur eine beliebige Zeichenkette. Da jedoch nicht jede Zeichenkette als IPv4-Adresse interpretierbar ist, binden wir das Resultat ARecordInvalidIPv4 an dieses Feld:

75120 - ERROR: invalid IPv4 address in A record (654)

Alle Resultate sind einem 5-stellig nummerierten Katalog entnommen, der eine Erweiterung der alten 3-stelligen „Systemantworten“ des Robots bildet und in unserer alten Domain-API schon lange Anwendung findet. Zusammen mit dem Resultat wird nun auch der Constraint [DataValidation::IPAddress] an das Feld gebunden, um zu definieren, wann dieses Resultat zurückgegeben werden soll. Der Constraint implementiert die Validierungsfunktion und gibt darüber Auskunft, welche Zeichenketten er als IPv4-Adresse akzeptiert.

Auf diese Weise kann die API schon im Vorfeld mitteilen, unter genau welchen Umständen welche Resultate zurückgegeben werden, womit die ganze mühselige Arbeit der Schnittstellendokumentation vollständig automatisiert ist. Die gelieferte Beschreibung ist unabgängig vom Darstellungsformat, so dass die Dokumentation in beliebiger Form veröffentlichen werden kann, z.B. innerhalb einer HTML- oder PDF-Dokumentation.

constraint

Genauso kann die API auch z.B. dokumentierten Quellcode für Clients generieren.

clientcode1

Der Dienst, der die API implementiert, hat zu garantieren, dass eine Operation dann und nur dann zur Ausführung kommt, wenn auf jeder Stufe alle Bedingungen erfüllt sind. Andernfalls liefert er die einzelnen Resultate mit den zugehörigen Begründungen an den Client aus.

sample_error

Wie der Client die Antwortdaten verarbeitet oder darstellt, muss ihm überlassen bleiben. Die API bietet detailierte Resultate, die so weit wie möglich aufgeschlüsselt sind, um die Weiterverarbeitung z.B. in einem interaktiven Webseite oder dergleichen zu ermöglichen.

Und der REST?

Die API selbst ist zunächst die abstrakte Definition eines Dienstvertrags. Um sie zu nutzen, muss der Client sich für einen Endpunkt entscheiden. Ein Endpunkt besteht formell aus Adresse, Bindung und Dienstvertrag. Der Dienstvertrag ist für alle Endpunkte einer API-Instanz gleich. Die Bindung ist die Transportvereinbarung, wie z.B. SOAP via HTTPS mit verschiedenen Authentifizierungsmethoden oder auch SMTP. Kurz gesagt, der Client kann sich aussuchen, wie er mit der API sprechen will.

rest1

Zum Beispiel ist einer der Endpunkte so alt wie das HTTP-Protokoll selbst: REST ist einfach HTTP ohne eine weitere Protokollschicht. Man holt sich Daten mit GET, legt mit POST Objekte an, verändert sie mit PUT und löscht sie mit DELETE. Dieser Endpunkt ist momentan noch experimentell und unterstützt bis jetzt auch nur XML-kodierte Daten. Aber die API lernt ja noch …

Am besten einfach ausprobieren

Wer schnell einen PHP-Client für die DNS-API in Betrieb nehmen will, kann sich gerne den HttpNetSoapClient herunterladen. Mit Partner-ID und angemeldeter IP-Adresse kann es dann sofort losgehen.

Einen Kommentar schreiben

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>




* Pflichtfelder
  • Kategorien