En introduksjon til REST
REST er forkortelse for "REpresentational State Transfer", og er et sett med regler som kan brukes for å designe et system. REST er først beskrevet av Roy Fielding i en PhD oppgave som ble publisert i 2000. Les mer om REST historien her: http://en.wikipedia.org/wiki/Representational_State_Transfer
Følgende punkter må være oppfyllt for at vi skal få et RESTful system:
- Det må være et klient-server system.
- Det må være tilstandsløst (stateless), med andre ord skal det ikke være behov for tjenesten å huske sesjoner. Hvert kall skal være uavhengig av hverandre.
- Det må støtte cache system.
- Hver ressurs må ha en unik adresse og et gyldig akesesspunkt.
- Det må være lagdelt og skalerbart.
- Det bør tilby "code on demand", men dette er valgfritt.
Et viktig poeng er at punktene ikke sier noe om teknologien som brukes. De definerer utelukkende hvordan data sendes mellom komponenter. På bakgrunn av dette kan et RESTful system implementeres i hvilken som helst nettverksarkitektur.
Et eksempel på et RESTful system er den statiske weben. Den støtter caching, er tilstandsløs og URLer peker til spesifikke filer (f.eks html) på webserveren. Dynamisk web derimot bryter som oftest med et eller flere av punktene over, som oftest grunnet bruk av sessions (på serversiden) eller cookies (på klientsiden).
Bestanddelene i et RESTful system
Vi har fire bestanddeler i et system som er RESTful. Under kommer en liten forklaring på hver av de.
Ressurser
En ressurs er noe som er adresserbart over web. Med andre ord noe som kan aksesseres og overføres mellom klient og server. En ressurs kan blant annet være en htmlfil, en flashfilm eller et bilde. Hvilken type ressurs det er snakk om bestemmes ved å sette content-type i headeren.
Represantasjoner
En representasjon er det som overføres mellom klient og server. Det består av en binærstøm og metadata som beskriver hvordan strømmen skal tolkes av klient / server. En representasjon kan f.eks være et bilde, en tekstfil, xmlstrøm eller en jsonstrøm. Er klienten en nettleser får vi ofte tilbake representasjonen av ressursen i form av en nettside (htmldokument), mens kommunikasjon imellom webservices gjerne benytter seg av en mer effektiv representasjon som xml.
URIs
URI er en forkortelse for "Uniform Resource Identifier" og er en link til en ressurs. Dette er den eneste måten klient og server kan snakke sammen på. Når vi snakker om RESTful webtjenester, er URI en hyperlink siden vi bruker web for å implementere webtjenester. Når vi snakker REST, er URI ment å være konstant over tid så lenge tjenesten kjører og ressursens kontekst er den samme.
Uten REST begrensingene vil vi som oftest aksessere ressurser basert på lokalisering, f.eks vanlige webadreser. Om vi endrer navnet på en fil på webserveren, må også URI endres.
HTTP request types
I en RESTful webtjeneste har vi fire hendelser vi kan utføre på en ressurs, i motsetning til en vanlig webtjeneste hvor vi har uendelig mange hendelser tilgjengelig. Ved å minimere antallet får man begrenset uklarheter / misforståelser i design og implementasjon.
De fire hendelsene vi har tilgjengelig er Create, Retrieve, Update og Delete (CRUD). Disse finner vi igjen i HTTP protokollen som Post, Get, Put og Delete.
Jeg skal nå prøve å vise et eksempel på hvordan vi kan bruke HTTP requests for å endre tilstand på en ressurs.
Anta at vi har en webtjeneste som holder styr på ansatte i en bedrift.
En typisk ansatt vil da se slik ut:
{codecitation class="brush: xml; gutter: false;" }
<ansatt>
<navn>Kristian</navn>
<alder>29</alder>
<katalog>/ansatte/kristian</katalog>
</ansatt>
Og en liste med ansatte:
{codecitation class="brush: xml; gutter: false;" }
<ansatte>
<ansatt>
<navn>Kristian</navn>
<alder>29</alder>
<katalog>/ansatte/kristian</katalog>
</ansatt>
<ansatt>
<navn>Tove</navn>
<alder>31</alder>
<katalog>/ansatte/tove</katalog>
</ansatt>
<katalog>/ansatte</katalog>
</ansatte>
Videre kan vi nå definere noen URIs:
http://minwebtjeneste.no/ansatte <--- gir oss en liste over ansatte
http://minwebtjeneste.no/ansatte/{navn} <--- gir oss en spesifikk ansatt identifisert på unikt navn.
Vi kan så prøve å gå til de definerte URI og resultatet er forhåpentligvis ikke direkte overraskende.
Eksempel 1 GET Request: http://minwebtjeneste.no/ansatte/kristian
Eksempel 1 Resultat:
{codecitation class="brush: xml; gutter: false;" }
<ansatt><navn>Kristian</navn><alder>29</alder><katalog>/ansatte/kristian</katalog></ansatt>
Eksempel 2 GET Request: http://minwebtjeneste/ansattte
Eksempel 2 Resultat:
{codecitation class="brush: xml; gutter: false;" }
<ansatte>
<ansatt><navn>Kristian</navn><alder>29</alder><katalog>/ansatte/kristian</katalog></ansatt>
<ansatt><navn>Tove</navn><alder>31</alder><katalog>/ansatte/tove</katalog></ansatt>
<katalog>/ansatte</katalog>
</ansatte>
En kort forklaring på hva som skjer i eksempel 1:
1: En javaklient gjør en HTTP request med type 'GET', og identifier 'kristian'.
2: Webserveren sender denne requesten til et RESTful rammeverk som behandler forespørselen.
3: REST rammeverket sender så dette videre til den domenespesifikke koden / programmet.
4: Programmet som kjører på serveren har ansvar for å grave frem data om en ansatt med navn Kristian, og returnere det tilbake i et passende format som klienten kan forstå. Vi får også en HTTP Status 200 dersom alt har gått greit, e.v.t en feilkode dersom noe har oppstått.
Fremgangsmåten i eksempel 2 er nærmest identisk, bare at vi har en annen identifier.
Vi bruker altså GET for å hente representasjoner.
Eksempel 3 POST / CREATE Request: http://minwebtjeneste/ansatte/kristian
Eksempel 3 Resultat: HTTP Status 200 (e.v.t HTTP Error Code)
En kort forklaring på det som skjer i eksempel 3:
1: En javaklient gjør en HTTP request med type 'POST'.
2: POST requesten sendes sammen med en XML representasjon av 'Kristian'.
3: Webserveren mottar og videresender til REST rammeverket, hvor koden for å lagre / opprette den nye ansatte blir kjørt.
4: Når den nye ressursen er lagret returneres en HTTP Status 200 om alt har gått greit, e.v.t en feilkode dersom noe har oppstått.
Vi bruker altså POST for å opprette representasjoner.
Eksempel 4 PUT / UPDATE Request:http://minwebtjeneste/ansatte/kristian
Eksempel 4 Resultat: HTTP Status 200 (e.v.t HTTP Error Code)
En kort forklaring på det som skjer i eksempel 4:
1: En javaklient gjør først en GET (utelatt siden den er identisk med eksempel 1). Dette gir oss mulighet til å se hvilken data som skal endres, og endre de.
2: Klienten sender en PUT request til http://minwebtjeneste/ansatte/kristian med de oppdaterte dataene i XML format.
3: Webserveren mottar og videresender til REST rammeverket, hvor koden for å oppdatere representasjonen blir kjørt.
4: Når representasjonen er oppdatert returneres det en status kode.
Vi bruker altså PUT for å oppdatere representasjoner.
Eksempel 5 DELETE Request: http://minwebtjeneste/ansatte/kristian
Eksempel 5 Resultat: HTTP Status 200 (e.v.t HTTP Error Code)
En kort forklaring på det som skjer i eksempel 5:
1: En javaklient gjør en DELETE request til http://minwebtjeneste/ansatte/kristian.
2: Webserveren mottar og videresender til REST rammeverket, hvor koden for å slette representasjonen blir kjørt.
3: Når representasjonen er slettet returneres det en status kode.
Vi bruker altså DELETE for å slette representasjoner.
Vi har altså hentet, oppdatert og slettet en ansatt ved hjelp av en URI, og tre allerede eksisterende HTTP kall.
Webservices i praksis
W3C definerer en webtjeneste som et system som utveksler XML med andre systemer via HTTP protokollen.
I praksis brukes ofte webtjenester av firma som ønsker å gjøre sin API tilgjengelig for andre utviklere. F.eks Google, Yahoo!, Amazon og Facebook tilbyr webservices.
Eksempeler: Flickr API, Amazon REST API, Google Search REST API
Det finnes flere REST rammeverk for Java dersom du ønsker å prøve selv. Vi kommer tilbake til disse i senere artikler.