produktivzone
6 Normseiten, geschätzte Lesezeit 5 Min.

REST (Representational State Transfer)

Was ist REST?

REST ist ein Programmierparadigma für verteilte Systeme, insbesondere für Webservices. Dabei geht es primär darum, die Kommunikation im Internet für eine automatisierte Maschine zu Maschine Kommunikation zu abstrahieren.

Was REST von anderen Paradigmen wie SOAP, WDSL und RPC unterscheidet, ist der Umstand, dass nur Technologien benötigt werden, die ohnehin schon im Internet verbreitet sind, wie HTTP, HTML, XML oder JSON. Das führt dazu, dass viele Webdienste sowieso schon REST-konform sind.

Eine Besonderheit von REST ist, dass keine Methodeninformationen in der URI gespeichert werden, sondern nur Ressourcen. Wenn der Webservice komplex ist, wird eine pfadgesteuerte Mehrschichtigkeit empfohlen.

Die Requests sollen möglichst konsistent und für Menschen lesbar (selbstbeschreibend) hinterlegt sein.

Um die Maschine zu Maschine Kommunikation zu vereinfachen, gilt das Prinzip der Zustandslosigkeit. Das bedeutet, es werden keine Cookies mitgeschickt, z.B. zur Identifikation des Clients. Der Nachteil ist natürlich, dass jeder Request einzeln authorisiert werden muss. Dies geschieht zugunsten einer besseren Skallierbarkeit und einer unkomplizierten Lastverteilung auf mehrere Server, falls nötig.

Das Paradigma empfiehlt servseitiges HTTP-Caching, um die Zugriffsgeschwindigkeit zu erhöhen.

Anders als SOAP sieht REST von Haus aus keine Verschlüsselungsmethode vor und verlässt sich voll auf HTTPS. Optional können weitere Verschlüsselungsmethoden verwendet werden, wie z.B. HMAC, OAuth oder OpenID.

Ein Restfull-Request sollte die Antwort in wellknown Formate zur Verfügung stellen, wie z.B. HTML, JSON oder XML.

Als Anwendungsschicht-Protokoll wird meist HTTP oder HTTPS eingesetzt. Die zu verwendenden Methoden entsprechen dem HTTP-Protokoll. Die Methoden dürfen sich in der Funktion nicht überschneiden. Dafür dürfen mehrere Anfragen in ein Request zusammengefasst werden (idempotent).

Methoden

in REST sind folgende Methoden möglich:

GET: eine Ressource (z.B. ein Datensatz) anfragen

POST: fügt in der angegeben Resource eine neue Subressource ein. Diese Methode wird oft eingesetzt, wenn keine andere Methode in Frage kommt.

PUT: es wird eine neue Ressource angelegt. Sollte sie bereits existieren, wird sie geändert.

PATCH: eine Ressource wird geändert. Nebeneffekte sind erlaubt.

DELETE: eine Ressource wird gelöscht

HEAD: fordert Metadaten zu einer Ressource an

OPTIONS: prüft, welche Methoden eine Ressource zur Verfügung stellt

CONNECT: stellt eine sichere Verbindung her (HTTPS-Tunnel)

TRACE: gibt die Anfrage zurück, wie sie beim Server ankommt, falls die Anfragen auf dem Weg z.B. über ein Proxy geändert werden.

weitere Methoden: eine Erweiterung das HTTP-Protokolls bildet WebDAV. Da REST an HTTP angelehnt ist, können Webservices auch WebDAV-Methoden beinhalten, wie COPY, MOVE, MKCOL, LOCK und UNLOCK. Auch LINK und UNLINK aus RFC 2068 können implementiert werden.

Jeder Request wird mit einem eigenen Statuscode gewürdigt. Dabei verwendet man dieselben Statuscodes, wie im HTTP-Protokoll.

REST ist ein einfaches und tolles Protokoll, das relativ einfach in PHP abgebildet werden kann. Entsprechende Bibliotheken sind klein und frei verfügbar.

OData (Open Data Protocol)

Für die Definition der Requests wird in der Windows-Welt oft ein eigenes Protokoll von Microsoft eingesetzt, nämlich OData. Wie von Microsoft gewohnt, erscheint das Protokoll unnötig komplex (ganz offensichtlich historisch gewachsen) und in Bezug auf die verfügbaren Methoden reichlich inkonsistent und redundant. Ohne SAP hätte sich das Protokoll vermutlich nie durchgesetzt.

OData wird naturgemäß hauptsächlich für die .NET Web API eingesetzt. Ausserhalb dieser API findet es kaum Anwendung. Es wird aufgrund seiner Komplexität von einem eigenen Gremium verwaltet (Oasis). Es liegt derzeit in Version 4 vor.

OData sieht vor, bei beliebigen HTTP basierten Client/Server-Architekturen CRUD-Operationen durchzufüren (CRUD = Create, Read, Update, Delete). Da sich die CRUD-Operationen thematisch mit den oben aufgeführten REST-Methoden überschneiden, ist anzunehmen, dass es sich bei OData im Grunde genommen um eine Erweiterung des REST-Protokolls handelt, weniger um eine Ergänzung. Denn wenn es sich nur um eine Ergänzung handeln würde, könnte die Kombination REST/ODATA zu inkonsistenten Abfragen führen.

OData ist hilfreich, wenn es darum geht, kurze, für Menschen lesbare Datenbankabfragen zu erstellen, die bei einer einfachen HTTP-Abfrage als POST oder GET-Variable mitgeschickt werden können. Nachfolgend werde ich kurz auf die Beschreibung der OData-Filter eingehen. Dieser ist ziemlich umfangreich:

Comparison Operators

2:eq = Equal (Address/City eq 'Redmond')

2:ne = Not equal (Address/City ne 'London')

2:gt = Greater than (Price gt 20

2:ge = Greater than or equal (Price ge 10)

2:lt = Less than (Price lt 20)

2:le = Less than or equal (Price le 100)

2:has = Has flags (Style has Sales.Color'Yellow'=

Logical Operators

2:and = Logical and (Price le 200 and Price gt 3.5)

2:or = Logical or (Price le 3.5 or Price gt 200)

2:not = Logical negation (not endswith(Description,'milk'))

Arithmetic Operators

2:add = Addition (Price add 5 gt 10)

2:sub = Subtraction (Price sub 5 gt 10)

2:mul = Multiplication (Price mul 2 gt 2000)

2:div = Division (Price div 2 gt 4)

2:mod = Modulo (Price mod 2 eq 0)

Grouping Operators

2:( ) = Precedence grouping ((Price sub 5) gt 10)

String Functions

2:contains (contains('Alfreds',CompanyName))

2:endswith (endswith(CompanyName,'Futterkiste'))

2:startswith (startswith(CompanyName,'Alfr'))

2:length (length(CompanyName) eq 19)

2:indexof (indexof(CompanyName,'lfreds') eq 1)

2:substring (substring(CompanyName,1) eq 'lfreds Futterkiste')

2:tolower (tolower(CompanyName) eq 'alfreds futterkiste')

2:toupper (toupper(CompanyName) eq 'ALFREDS FUTTERKISTE')

2:trim (trim(CompanyName) eq 'Alfreds Futterkiste')

2:concat (concat(concat(City,', '), Country) eq 'Berlin, Germany')

Date Functions

2:year (year(BirthDate) eq 0)

2:month (month(BirthDate) eq 12)

2:day (day(StartTime) eq 8)

2:hour (hour(StartTime) eq 1)

2:minute (minute(StartTime) eq 0)

2:second (second(StartTime) eq 0)

2:fractionalseconds (second(StartTime) eq 0)

2:date (date(StartTime) ne date(EndTime))

2:time (time(StartTime) le StartOfDay)

2:totaloffsetminutes (totaloffsetminutes(StartTime) eq 60)

2:now (StartTime ge now())

2:mindatetime (StartTime eq mindatetime())

2:maxdatetime (EndTime eq maxdatetime())

Math Functions

2:round (round(Freight) eq 32)

2:floor (floor(Freight) eq 32)

2:ceiling (ceiling(Freight) eq 33)

Type Functions

2:cast (cast(ShipCountry,Edm.String))

2:isof (isof(NorthwindModel.Order))

2:isof (isof(ShipCountry,Edm.String))

Geo Functions

2:geo.distance (geo.distance(CurrentPosition,TargetPosition))

2:geo.length (geo.length(DirectRoute))

2:geo.intersects (geo.intersects(Position,TargetArea))

Diese Parameter werden über eine Umgebungsvariable mit dem Namen $filter an den Webserver übergeben. Über folgende Variabeln sind weitere Eingrenzungen möglich, die z.B. das Paging steuern, sofern der Server eine Übersteuerung zulässt:

$search ($search=(mountain OR bike) AND NOT clothing ) = ein Such-Query absetzen

$count ($count=true) = Anzahl Datensätze an Query anhängen

$orderby ($orderby=ReleaseDate asc, Rating desc) = Sortierreihenfolge definieren

$skip ($top=5&$skip=2) = Datensätze ausklammern

$top ($top=5) = die ersten 5 Datensätze ausgeben

$expand = erweitert eine Ressource mehrdimensional mit einer relational verknüpften Ressource

$select = liefert die verfügbaren Eigenschaften und Methoden einer Ressource aus,

$format = definiert, in welchem Format eine Ressource ausgegeben werden soll

Achtung: Auf der offiziellen OData-Homepage wird nicht eine einzige PHP-Library aufgelistet. Das liegt schlicht daran, dass OData in der PHP-Welt als irrelevant bewertet wird, da es für Webservices wesentlich bessere CRUD-Paradigmen gibt. Tatsächlich konnte ich in der Open Source Welt nur eine einzige PHP-SDK finden. Die ist allerdings von 2010 und noch in PHP 4 geschrieben. Von dem Einsatz dieser Bibliothek wird abgeraten.

Datentypen

Folgende Datentypen werden unterstützt:

String (ohne Angabe von Länge)

Date/Time (nicht selten MS-Format)

Float

Blob (Binaries)

Integer

Bool

Time

Date

Unix Timestamp

August 2016/jw