Versjonering av et REST API

1. Problemet

Å utvikle et REST API er et vanskelig problem - en som mange alternativer er tilgjengelige for. Denne artikkelen diskuterer noen av disse alternativene.

2. Hva ligger i kontrakten?

Før noe annet, må vi svare på ett enkelt spørsmål: Hva er kontrakten mellom API og Klient?

2.1. URI er en del av kontrakten?

La oss først vurdere URI-strukturen til REST API - er det en del av kontrakten? Bør klienter bokmerke, hardkode og generelt stole på URI-er for API?

Hvis dette er tilfelle, vil interaksjonen mellom klienten og REST-tjenesten ikke lenger være drevet av selve tjenesten, men av det Roy Fielding kaller utenfor bandet informasjon:

En REST API bør legges inn uten forkunnskaper utover den opprinnelige URI (bokmerke) og sett med standardiserte mediatyper som passer for den tiltenkte målgruppen ... Feil her innebærer at informasjon utenfor bandet driver samhandling i stedet for hypertekst.

Så tydelig URI er ikke en del av kontrakten! Klienten skal bare kjenne en enkelt URI - inngangspunktet til API. Alle andre URI-er bør oppdages mens de bruker API-en.

2.2. Medietyper del av kontrakten?

Hva med informasjon om medietypen som brukes til representasjon av ressurser - er dette en del av kontrakten mellom klienten og tjenesten?

For å lykkes med å konsumere API-en, må klienten ha forkunnskaper om disse mediatypene. Definisjonen av disse mediatypene representerer faktisk hele kontrakten.

Derfor bør REST-tjenesten fokusere mest på dette:

En REST API bør bruke nesten all sin beskrivende innsats i å definere mediatypen (e) som brukes til å representere ressurser og kjøre applikasjonstilstand, eller å definere utvidede relasjonsnavn og / eller hypertekstaktivert påslag for eksisterende standardmedietyper.

Definisjoner av medietype er en del av kontrakten og skal være forkunnskap for klienten som bruker API. Det er her standardisering kommer inn.

Vi har nå en god ide om hva kontrakten er, la oss gå videre til hvordan vi faktisk kan takle versjonsproblemet.

3. Alternativer på høyt nivå

La oss nå diskutere tilnærminger på høyt nivå til versjonering av REST API:

  • URI versjonering - versjon av URI-rommet ved hjelp av versjonsindikatorer
  • Versjonering av medietype - versjon Representasjon av ressursen

Når vi introduserer versjonen i URI-rommet, anses Representations of Resources som uforanderlig. Så når endringer må innføres i API-et, må det opprettes et nytt URI-rom.

Si for eksempel at en API publiserer følgende ressurser - brukere og privilegier:

// vert / v1 / brukere // vert / v1 / privilegier

La oss nå vurdere at en bruddendring i brukere API krever innføring av en ny versjon:

// vert / v2 / brukere // vert / v2 / privilegier

Når vi verserer mediatypen og utvider språket, går vi gjennom innholdsforhandlinger basert på denne overskriften. REST API ville bruke tilpassede MIME-mediatyper i stedet for generiske medietyper som søknad / json. Vi skal versjon av disse mediatypene i stedet for URI-ene.

For eksempel:

===> GET / brukere / 3 HTTP / 1.1 Godta: applikasjon / vnd.myname.v1 + json <=== HTTP / 1.1 200 OK Innholdstype: applikasjon / vnd.myname.v1 + json {"bruker": {"name": "John Smith"}}

Vi kan sjekke ut denne artikkelen om 'Tilpassede mediatyper for hvile-APIer' for ytterligere informasjon og eksempler om dette emnet.

Det som er viktig å forstå her er at klienten legger ikke til grunn antagelser om responsen utover det som er definert i medietypen.

Dette er grunnen til at generiske medietyper ikke er ideelle. Disse ikke gi nok semantisk informasjon og tving klienten til å bruke krever ytterligere tips for å behandle den faktiske representasjonen av ressursen.

Et unntak fra dette er å bruke en annen måte å unikt identifisere semantikken til innholdet - for eksempel et XML-skjema.

4. Fordeler og ulemper

Nå som vi har et klart konsept av hva som er en del av kontrakten mellom klienten og tjenesten, samt en oversikt på høyt nivå av alternativene for versjon av API, la oss diskutere fordeler og ulemper ved hver tilnærming.

Først, introdusere versjonsidentifikatorer i URI fører til et veldig stort URI-fotavtrykk. Dette skyldes det faktum at enhver endring i noen av de publiserte API-ene vil introdusere et helt nytt representasjonstre for hele API-en. Over tid blir dette en byrde å vedlikeholde, så vel som et problem for klienten - som nå har flere muligheter å velge mellom.

Versjonsidentifikatorer i URI ER også svært fleksible. Det er ingen måte å bare utvikle API-en til en enkelt ressurs, eller en liten delmengde av den samlede API-en.

Som vi nevnte tidligere, er dette en alt eller ingenting tilnærming. Hvis en del av API-et flyttes til den nye versjonen, må hele API-en flytte sammen med den. Dette gjør også oppgradering av klienter fra v1 til v2 til et stort foretak - noe som fører til langsommere oppgraderinger og mye lengre solnedgangsperioder for de gamle versjonene.

HTTP-hurtigbufring er også en stor bekymring når det gjelder versjonering.

Fra perspektivet til proxy-cacher i midten har hver tilnærming fordeler og ulemper. Hvis URI er versjonert, må hurtigbufferen beholde flere kopier av hver ressurs - en for hver versjon av API. Dette legger en belastning på hurtigbufferen og reduserer trefffrekvensen for hurtigbufferen siden forskjellige klienter vil bruke forskjellige versjoner.

Også noen mekanismer for ugyldiggjøring av hurtigbuffer vil ikke lenger fungere. Hvis medietypen er den som er versjonert, må både klienten og tjenesten støtte Vary HTTP-overskriften for å indikere at det er flere versjoner som blir bufret.

Fra perspektiv på klientbufring Imidlertid innebærer løsningen som versjoner medietypen, litt mer arbeid enn den der URI-er inneholder versjonsidentifikatoren. Dette er fordi det ganske enkelt er lettere å cache noe når nøkkelen er en URL enn en medietype.

La oss avslutte denne delen med å definere noen mål (rett ut av API Evolution):

  • holde kompatible endringer utenfor navn
  • unngå nye store versjoner
  • gjør endringer bakoverkompatible
  • tenk på fremoverkompatibilitet

5. Mulige endringer i API

Deretter skal vi vurdere hvilke typer endringer i REST API - disse blir introdusert her:

  • representasjonsformat endres
  • ressursendringer

5.1. Legger til representasjonen av en ressurs

Formatdokumentasjonen for medietypen skal utformes med tanke på fremoverkompatibilitet. Spesielt bør en klient ignorere informasjon som den ikke forstår (hvilken JSON gjør bedre enn XML).

Nå, å legge til informasjon i representasjonen av en ressurs vil ikke bryte eksisterende klienter hvis disse er riktig implementert.

For å fortsette vårt tidligere eksempel, legger du til beløp i representasjonen av bruker vil ikke være en bruddendring:

{"user": {"name": "John Smith", "amount": "300"}}

5.2. Fjerne eller endre en eksisterende representasjon

Å fjerne, gi nytt navn eller generelt omstrukturere informasjon i utformingen av eksisterende representasjoner er en avgjørende forandring for klienter. Dette er fordi de allerede forstår og stoler på det gamle formatet.

Det er her innholdsforhandling kommer inn. For slike endringer, vi kan legge til en ny MIME-medietype fra leverandøren.

La oss fortsette med forrige eksempel. Si at vi vil bryte Navn av bruker inn i fornavn og etternavn:

===> GET / brukere / 3 HTTP / 1.1 Godta: applikasjon / vnd.myname.v2 + json <=== HTTP / 1.1 200 OK Innholdstype: applikasjon / vnd.myname.v2 + json {"bruker": {"firstname": "John", "lastname": "Smith", "amount": "300"}}

Som sådan representerer dette en inkompatibel endring for klienten - som må be om den nye representasjonen og forstå den nye semantikken. URI-rommet vil imidlertid forbli stabilt og vil ikke bli påvirket.

5.3. Store semantiske endringer

Dette er endringer i betydningen av ressursene, forholdet mellom dem eller hva kartet til i backend. Denne typen endringer kan kreve en ny medietype, eller de kan kreve publisering av en ny søskenressurs ved siden av den gamle og bruk av lenking for å peke på den.

Selv om dette høres ut som å bruke versjonsidentifikatorer i URI igjen, er det viktige skillet at den nye ressursen publiseres uavhengig av andre ressurser i API og vil ikke forkaste hele API-en ved roten.

REST API bør overholde HATEOAS-begrensningen. I følge dette skal de fleste URI'S OPPDAGES av klienter, ikke hardkodet. Endring av en slik URI skal ikke betraktes som en inkompatibel endring. Den nye URI kan erstatte den gamle, og klienter vil kunne gjenoppdage URI og fortsatt fungere.

Det er imidlertid verdt å merke seg at det er problematisk å bruke versjonsidentifikatorer i URI av alle disse grunnene, det er ikke un-RESTful på noen måte.

6. Konklusjon

Denne artikkelen prøvde å gi en oversikt over det svært mangfoldige og vanskelige problemet med utvikle en REST-tjeneste. Vi diskuterte de to vanlige løsningene, fordeler og ulemper ved hver enkelt, og måter å resonnere om disse tilnærmingene i sammenheng med REST.

Artikkelen avsluttes med å gjøre saken til den andre løsningen - versjonering av medietypene mens du undersøker mulige endringer i et RESTful API.

Den fulle implementeringen av denne veiledningen finner du i GitHub-prosjektet.

7. Videre lesing

Vanligvis er disse leseressursene knyttet til hele artikkelen, men i dette tilfellet er det ganske enkelt for mange gode:

    • REST API-er må være hypertekstdrevet
    • API Evolution
    • Kobling for en HTTP API
    • Kompatibilitetsstrategier

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