Web Diensten bouwen aan de hand van REST

Door Roger L. Costello

Na een korte introductie van REST volgt hieronder een omschrijving van het bouwen van web diensten aan de hand van REST.

Wat is REST?

De term REST is bedacht in het proefschrift van Roy Fielding [1] om een vorm van netwerk architectuur te beschrijven. Het is een acroniem voor Representational State Transfer.

Waarom wordt het Representational State Transfer genoemd?

Het Web bestaat uit bronnen. Een bron is daarbij ieder item dat op enige wijze interessant kan zijn. Zo kan bijvoorbeeld vliegtuigmaker Boeing een 747 als zijnde een bron aanmerken. In dat geval zou een client die bron aanspreken door middel van de URL:

http://www.boeing.com/aircraft/747

Er wordt vervolgens een bepaalde representatie van deze bron gegeven, zoals bijvoorbeeld de webpagina Boeing747.html. Deze representatie plaatst de client applicatie in een ‘staat’, oftewel een state. Wanneer diezelfde client binnen Boeing747.html een hyperlink gebruikt wordt een nieuwe bron aangesproken, een nieuwe weergave wordt gegeven en de client applicatie bereikt een nieuwe staat. De staat van de client applicatie verandert (transfers) dus met iedere nieuwe weergave (representation) van een bron -> Representational State Transfer!

Dit is de letterlijke vertaling van de betekenis van Representational State Transfer zoals gegeven door Roy Fielding:

“Representational State Transfer moet een beeld oproepen van de werking van een goed-ontworpen webapplicatie: een netwerk van webpagina’s (een virtual state-machine), waar de gebruiker door de applicatie navigeert door het selecteren van links (veranderingen in de staat, oftewel state transitions), waarna de volgende pagina wordt gegenereerd (de weergave van de nieuwe staat van de applicatie) en naar de gebruiker wordt gezonden.”

De motivatie voor REST

De motivatie voor het ontwikkelen van REST was het vangen van die eigenschappen van het Web die het Web succesvol maakten. Deze zelfde eigenschappen worden vervolgens gebruikt om de verdere ontwikkeling van het Web te sturen.

REST – Een stijl, geen standaard

REST is geen standaard. Je zal de W3C dan ook geen REST specificaties zien uitbrengen. IBM, Microsoft of SUN zullen geen REST ontwikkelkit uitbrengen. Waarom? Omdat REST een architectonische stijl is. Een stijl die niet in een fles te vangen is. Je kan de stijl echter wel begrijpen en web diensten ontwikkelen in de stijl. REST is hierin vergelijkbaar met de client-service stijl, die wederom geen standaard vormt.
Hoewel REST zelf geen standaard is, maakt REST wel gebruik van standaarden:

HTTP

URL

XML/HTML/GIF/JPEG/etc (weergave van bronnen)

Tekst/xml, tekst/html, afbeelding/gif, afbeelding/jpeg, etc (MIME Types)

Het klassieke REST systeem

Het Web is een REST systeem! Veel van de web diensten die je al jaren gebruikt – e-commerce sites, zoek diensten, online woordenboeken, etc – zijn op REST gebaseerde web diensten. Je gebruikt REST en hebt waarschijnlijk al REST diensten gebouwd zonder het te beseffen.

REST draait om het ‘grote plaatje’ van het Web. Het houdt zich niet bezig met de details van de implementaties, zoals Java Servlets of CGI. Laten we eens kijken naar een voorbeeld van een Web dienst door onze REST-bril.

Parts Depot Web Diensten

Parts Depot BV (een denkbeeldige onderneming) heeft web diensten ingezet zodat haar klanten het volgende kunnen:

Een lijst onderdelen opvragen

Gedetailleerde informatie over een specifiek onderdeel krijgen

Een bestelling plaatsen

Laten we kijken hoe we deze verschillende diensten in de stijl van REST implementeren.

Lijst Onderdelen Opvragen

De web dienst maakt de lijst met onderdelen door middel van een url beschikbaar als bron. Zo kan een client bijvoorbeeld door middel van de volgende URL de lijst met onderdelen opvragen:

http://www.parts-depot.com/parts

Het valt daarbij op dat de manier waarop de web dienst de lijst met onderdelen gegenereerd compleet inzichtelijk is voor de client. De client weet dat wanneer de bovenstaande url wordt aangeroepen, een document met daarin een lijst met alle onderdelen wordt teruggezonden. Doordat deze implementatie voor de client inzichtelijk is, kan Parts Depot de onderliggende implementatie van de specifieke bron aanpassen zonder dat de client hier iets van merkt. Dit wordt ook wel een losse koppeling of ‘loose coupling’ genoemd.

Dit is het document dat de client ontvangt:

<?xml version="1.0"?>

<p:Parts xmlns:p="http://www.parts-depot.com"

xmlns:xlink="http://www.w3.org/1999/xlink">

<Part id="00345" xlink:href="http://www.parts-depot.com/parts/00345"/>

<Part id="00346" xlink:href="http://www.parts-depot.com/parts/00346"/>

<Part id="00347" xlink:href="http://www.parts-depot.com/parts/00347"/>

<Part id="00348" xlink:href="http://www.parts-depot.com/parts/00348"/>

</p:Parts>

We nemen hierbij voor het gemak aan dat de dienst dankzij content negotiation heeft vastgesteld dat de client de weergave in de vorm van een XML document wil ontvangen, om zo machine-naar-machine verwerking mogelijk te maken. Houd daarbij in de gaten dat de onderdelenlijst links bevat naar gedetailleerde informatie voor elk afzonderlijk onderdeel. Dit is een van de kenmerkende eigenschappen van REST. De client gaat van de ene staat over in de volgende door de URLs in het response document te bekijken en hier een keuze uit te maken.

Gedetailleerde informatie over onderdelen opvragen

De web dienst maakt elke bron die aan een onderdeel gekoppeld is beschikbaar door middel van een url. Dit is bijvoorbeeld hoe een client onderdeel 00345 op zou vragen:

http://www.parts-depot.com/parts/00345

<?xml version="1.0"?>

<p:Part xmlns:p="http://www.parts-depot.com"

<Part-ID>00345</Part-ID>

<Name>Widget-A</Name>

<Description>This part is used within the frap assembly</Description>

<Specification xlink:href="http://www.parts-depot.com/parts/00345/specification"/>

<UnitCost currency="USD">0.10</UnitCost>

<Quantity>10</Quantity>

</p:Part>

Het valt hierbij op hoe deze informatie weer gelinkt is met meer informatie – de specificaties voor dit onderdeel vind je door de gegeven hyperlink te volgen. Elk nieuw document staat de client toe om steeds gedetailleerdere informatie op te vragen.

Plaats bestelling

De web dienst biedt door middel van een url de mogelijkheid een bestelling te plaatsen. De client creëert vervolgens een besteldocument dat voldoet aan de documenteisen die door Parts Depot zijn vastgesteld en gepubliceerd in een WSDL document. De client geeft PO.xml vervolgens mee door middel van een HTTP POST.

De bestel web dienst beantwoord de HTTP POST met een URL die naar de geplaatste bestelling verwijst. Op die wijze kan de client op ieder moment de geplaatste bestelling ophalen om deze te wijzigen. De bestelling is hiermee een stuk informatie geworden dat wordt gedeeld door de client en de server. De gedeelde informatie (de bestelling) ontvangt een adres (URL) van de server en wordt daarmee onderdeel van een webdienst.

Logical URLs versus Fysieke URLs

Een bron is van zichzelf conceptueel. Een weergave is de fysieke manifestatie van die bron. Deze URL:

http://www.parts-depot.com/parts/00345

is een logical URL en geen fysieke URL. Dit neemt de noodzaak weg om, bijvoorbeeld, een statische HTML pagina voor ieder onderdeel aan te maken. Zouden er miljoenen onderdelen zijn, dan het gebruik van miljoenen statische HTML pagina’s bepaald geen aantrekkelijk ontwerp zijn.

[Implementatie detail: Parts Depot zou de dienst die gedetailleerde informatie over elk onderdeel ophaalt kunnen implementeren door middel van een Java Servlet die de string na de host name leest, het numerieke kenmerk van het onderdeel gebruikt om de onderdelen database een verzoek te sturen, de resultaten van dat verzoek omzet in XML en vervolgens diezelfde XML in een HTTP response terugzend.]

Om ontwikkelaars vrij te laten om in de toekomst de implementatie te wijzigen, is het binnen REST aan te raden de wijze van implementatie niet in de opmaak van URLs te tonen. Dit voorkomt dat bij toekomstige wijzigingen in de implementatie clients hinder ondervinden of dat URLs als misleidend worden ervaren.

De Eigenschappen van REST Web Diensten

Dit zijn de eigenschappen van REST:

Client-Server: Een interactie die op ‘pulls’ of oproepen gebaseerd is: De consumerende onderdelen roepen weergaven op.

Zonder opgeslagen staat: Iedere oproep van client naar server moet alle informatie bevatten die het begrijpen van die oproep mogelijk maakt, zonder dat informatie over de context op een server aangesproken hoeft te worden.

Cache: Om netwerkperformance te optimaliseren moeten alle responses als cacheable of niet-cacheable gelabeld kunnen worden.

Uniforme interface: Alle bronnen kunnen door middel van een generieke interface (zoals HTTP GET, POST, PUT, DELETE) aangesproken worden.

Genaamde bronnen: het systeem is opgebouwd uit bronnen die elk door middel van een url van een naam voorzien zijn.

Verbonden bron weergaven: De verschillende weergaven van bronnen zijn allen door middel van URLs met elkaar verbonden, waarmee de client van de ene staat in de andere staat over kan gaan.

Gelaagde onderdelen: Middelen als proxy servers, cache servers, gateways en dergelijke kunnen allen tussen clients en bronnen worden geplaatst om daarmee performance, beveiliging en meer te ondersteunen.

De Principes van REST Web Dienst Design

1.     De sleutel tot het ontwikkelen van web diensten binnen een REST netwerk (oftewel het Web), is het identificeren van alle conceptuele bronnen die je in de vorm van diensten beschikbaar wil maken. Hierboven zagen we al enkele voorbeelden van dergelijke bronnen: De onderdelen lijst, gedetailleerde informatie per onderdeel of het bestel formulier.

2.     Zorg voor een URL per bron. Deze bronnen moeten door middel van zelfstandig naamwoorden omschreven zijn, niet door werkwoorden. Gebruik bijvoorbeeld niet dit:
http://www.parts-depot.com/parts/getPart=id00345
Het werkwoord ‘get’ in getPart hoort hier niet. Gebruik dit:
http://www.parts-depot.com/parts/00345

3.     Verdeel je bronnen in bronnen die enkel op te vragen zijn door de client en bronnen waar de client aan kan bijdragen, oftewel wijzigingen in kan aanbrengen. De eerste hiervan maak je beschikbaar door middel van een HTTP GET, terwijl de laatste hiervan door middel van HTTP POST, PUT en/of DELETE aanspreekbaar moeten zijn.

4.     Alle bronnen die door middel van HTTP GET oproepbaar zijn, moeten enkel een weergave van deze bron teruggeven zonder dat hier wijzigingen in worden aangebracht.

5.     Elke bron dient hyperlinks te bevatten zodat een client meer informatie over een bron kan opvragen of gerelateerde informatie kan bekijken.

6.     Ontwerp een dienst om informatie gelaagd weer te geven. Geef niet alle informatie in een enkel response document, maar gebruik hyperlinks om meer en meer details te geven.

7.     Specificeer welk schema wordt gebruikt voor het weergeven van response data (DTD, W3C Schema, RelaxNG of Schematron). Voor diensten die POST of PUT input vereisen specificeer je ook het schema dat gebruikt moet worden om de response vorm te geven.

8.     Omschrijf hoe je dienst moet worden opgeroepen door middel van een WSDL of HTML document.

Samenvatting

In dit artikel wordt REST omschrijven als een architectonische stijl. Het is in feite dé stijl van het web. REST omschrijft hetgeen dat zorgt dat het Web werkt. Het volgen van REST principes zal zorgen dat je diensten binnen het Web goed werken.

In een toekomstig artikel zal ik verder uitweiden over de evolutie van het Web aan de hand van de REST principes.

Dankwoord

Mijn dank gaat uit naar Robert Leftwich en Philip Eskelin voor hun zeer behulpzame feedback bij het schrijven van dit document.

Referenties

[1] http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm