REST API Discoverability og HATEOAS

REST Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

Denne artikel vil fokusere på Opdagbarheden af ​​REST API, HATEOAS og praktiske scenarier drevet af test.

2. Hvorfor gøre API'en synlig

Opdagbarheden af ​​en API er et emne, der ikke får tilstrækkelig velfortjent opmærksomhed. Som en konsekvens får meget få API'er det rigtigt. Det er også noget, der, hvis det gøres korrekt, kan gøre API'en ikke kun RESTful og brugbar, men også elegant.

For at forstå opdagelighed er vi nødt til at forstå begrænsningen af ​​Hypermedia som motoren i applikationstilstand (HATEOAS). Denne begrænsning af en REST API handler om fuldstændig opdagelse af handlinger / overgange på en ressource fra Hypermedia (virkelig Hypertext), som den eneste driver til applikationstilstand.

Hvis interaktionen skal drives af API'en gennem selve samtalen, konkret via Hypertext, kan der ikke være nogen dokumentation. Det ville tvinge klienten til at komme med antagelser, der faktisk ligger uden for API'ets sammenhæng.

Afslutningsvis, serveren skal være beskrivende nok til at instruere klienten, hvordan man bruger API'et kun via Hypertext. I tilfælde af en HTTP-samtale kunne vi opnå dette gennem Link header.

3. Opdagelsesscenarier (drevet af tests)

Så hvad betyder det, at en REST-tjeneste kan findes?

I hele dette afsnit vil vi teste individuelle træk ved opdagelighed ved hjælp af Junit, forsikret og Hamcrest. Da REST-tjenesten tidligere er sikret, skal hver test først godkendes, før API'en forbruges.

3.1. Oplev de gyldige HTTP-metoder

Når en REST-tjeneste forbruges med en ugyldig HTTP-metode, skal svaret være en 405 METOD, IKKE TILLADT.

API'en skal også hjælpe klienten med at finde de gyldige HTTP-metoder, der er tilladt for den pågældende ressource. For det, vi kan bruge Give lov til HTTP-overskrift i svaret:

@Test offentlig ugyldig nårInvalidPOSTIsSentToValidURIOfResource_thenAllowHeaderListsTheAllowedActions () {// givet streng uriOfExistingResource = restTemplate.createResource (); // Når svar res = givenAuth (). Post (uriOfExistingResource); // Derefter String allowHeader = res.getHeader (HttpHeaders.ALLOW); assertThat (allowHeader, AnyOf.anyOf (containString ("GET"), containString ("PUT"), containString ("SLET"))); }

3.2. Oplev URI for nyligt oprettet ressource

Funktionen til oprettelse af en ny ressource skal altid omfatte URI for den nyoprettede ressource i svaret. Til dette kan vi bruge Beliggenhed HTTP header.

Hvis klienten nu foretager en GET på den URI, skal ressourcen være tilgængelig:

@Test offentligt ugyldigt nårResourceIsCreated_thenUriOfTheNewlyCreatedResourceIsDiscoverable () {// When Foo newResource = new Foo (randomAlphabetic (6)); Svar createResp = givenAuth (). ContentType ("application / json") .body (unpersistedResource) .post (getFooURL ()); String uriOfNewResource = createResp.getHeader (HttpHeaders.LOCATION); // Derefter Svarrespons = givenAuth (). Header (HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .get (uriOfNewResource); Foo resourceFromServer = respons.body (). Som (Foo.class); assertThat (newResource, equalTo (resourceFromServer)); }

Testen følger et simpelt scenario: skabe et nyt Foo ressource og derefter bruge HTTP-svaret til at finde URI, hvor ressourcen nu er tilgængelig. Derefter foretager den også en GET på den URI for at hente ressourcen og sammenligne den med originalen. Dette er for at sikre, at det blev gemt korrekt.

3.3. Oplev URI for at få alle ressourcer af den type

Når vi får noget bestemt Foo ressource, skal vi være i stand til at finde ud af, hvad vi kan gøre næste gang: vi kan liste alle tilgængelige Foo ressourcer. Således skal operationen med at hente en ressource altid omfatte URI, hvor man skal hente alle ressourcerne af den type i sit svar.

Til dette kan vi igen gøre brug af Link header:

@Test offentlig ugyldig nårResourceIsRetrieved_thenUriToGetAllResourcesIsDiscoverable () {// givet streng uriOfExistingResource = createAsUri (); // Når svar getResponse = givenAuth (). Get (uriOfExistingResource); // Derefter String uriToAllResources = HTTPLinkHeaderUtil .extractURIByRel (getResponse.getHeader ("Link"), "collection"); Svar getAllResponse = givenAuth (). Get (uriToAllResources); assertThat (getAllResponse.getStatusCode (), er (200)); }

Bemærk, at den fulde lavniveau-kode for ekstraktURIByRel - ansvarlig for at udvinde URI'erne ved rel forhold vises her.

Denne test dækker det tornede emne for Link Relations i REST: URI til at hente alle ressourcer bruger rel = ”samling” semantik.

Denne type forbindelsesrelation er endnu ikke standardiseret, men er allerede i brug af flere mikroformater og foreslået til standardisering. Brug af ikke-standardiserede linkrelationer åbner for diskussionen om mikroformater og rigere semantik i RESTful webtjenester.

4. Andre potentielle synlige URI'er og mikroformater

Andre URI'er kunne potentielt blive opdaget via Link header, men der er kun så meget de eksisterende typer forbindelsesrelationer tillader uden at flytte til en rigere semantisk markering, såsom at definere brugerdefinerede linkrelationer, Atom Publishing Protocol eller mikroformater, som vil være emnet for en anden artikel.

For eksempel skal klienten være i stand til at opdage URI'en for at oprette nye ressourcer, når han laver en på en bestemt ressource. Desværre er der ingen forbindelsesrelation til model skab semantik.

Heldigvis er det en standardpraksis, at URI til oprettelse er den samme som URI for at FÅ alle ressourcer af den type, hvor den eneste forskel er POST HTTP-metoden.

5. Konklusion

Vi har set hvordan en REST API kan findes helt fra roden og uden forudgående viden - hvilket betyder, at klienten er i stand til at navigere i den ved at lave en GET på roden. Fremadrettet drives alle tilstandsændringer af klienten ved hjælp af de tilgængelige og synlige overgange, som REST API giver i repræsentationer (dermed Representativ statsoverførsel).

Denne artikel dækkede nogle af trækkene ved opdagelighed i forbindelse med en REST-webtjeneste, diskuterede opdagelse af HTTP-metoden, forholdet mellem opret og få, opdagelse af URI for at få alle ressourcer osv.

Implementeringen af ​​alle disse eksempler og kodestykker er tilgængelig på GitHub. Dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.

REST bunden

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

$config[zx-auto] not found$config[zx-overlay] not found