10 beste fremgangsmåter for å skrive Node.js REST APIs

I denne artikkelen dekker vi beste fremgangsmåter for å skrive Node.js REST API-er, inkludert emner som å navngi ruter, autentisering, svartboks-testing og bruk av riktige cache-overskrifter for disse ressursene.

En av de mest populære brukssakene for Node.js er å skrive RESTful APIer ved å bruke det. Selv om vi hjelper våre kunder med å finne problemer i applikasjonene deres med Trace, vårt Node.js overvåkingsverktøy, opplever vi stadig at utviklere har mange problemer med REST API-er.

Jeg håper disse beste praksisene vi bruker på RisingStack kan hjelpe:

# 1: Bruk HTTP-metoder og API-ruter

Se for deg at du bygger et Node.js RESTful API for å opprette, oppdatere, hente eller slette brukere. For disse operasjonene har HTTP allerede tilstrekkelig verktøysett: POST, PUT, GET, PATCH eller DELETE.

Som en god praksis bør API-rutene dine alltid bruke substantiv som ressursidentifikatorer. Når vi snakker om brukerens ressurser, kan rutingen se slik ut:

  • POST / bruker eller PUT / user: / id for å opprette en ny bruker,
  • FÅ / bruker for å hente en liste over brukere,
  • GET / bruker /: id for å hente en bruker,
  • PATCH / bruker /: id for å endre en eksisterende brukerpost,
  • SLETT / bruker /: id for å fjerne en bruker.

# 2: Bruk HTTP-statuskoder riktig

Hvis noe går galt mens du serverer en forespørsel, må du angi riktig statuskode for den i svaret:

  • 2xx, hvis alt var i orden,
  • 3xx, hvis ressursen ble flyttet,
  • 4xx, hvis forespørselen ikke kan oppfylles på grunn av en klientfeil (som å be om en ressurs som ikke eksisterer),
  • 5xx, hvis noe gikk galt på API-siden (som et unntak skjedde).

Hvis du bruker Express, er det så enkelt å angi statuskode som res.status (500) .send ({error: 'Internal server error occurred'}). Tilsvarende med Restify: res.status (201).

For en fullstendig liste, sjekk listen over HTTP-statuskoder

# 3: Bruk HTTP-overskrifter for å sende metadata

Hvis du vil legge ved metadata om nyttelasten du skal sende, bruker du HTTP-overskrifter. Overskrifter som dette kan være informasjon om:

  • paginering,
  • takstbegrensning,
  • eller autentisering.

En liste over standardiserte HTTP-overskrifter finner du her.

Hvis du trenger å angi noen tilpassede metadata i overskriftene dine, var det en god praksis å prefiksere dem med X. Hvis du for eksempel brukte CSRF-symboler, var det en vanlig (men ikke-standard) måte å navngi dem X-Csrf -Token. Imidlertid ble de avskrevet med RFC 6648. Nye API-er bør gjøre sitt beste for å ikke bruke overskriftsnavn som kan komme i konflikt med andre applikasjoner. For eksempel prefikser OpenStack overskriftene sine med OpenStack:

Openstack-Identity-konto-ID
Openstack-Nettverk-Host-navn
Openstack-Object-Storage-politikk

Merk at HTTP-standarden ikke definerer noen størrelsesgrense for topptekstene. Imidlertid pålegger Node.js (fra skriving av denne artikkelen) en størrelsesgrense på 80 kB på headers-objektet av praktiske årsaker.

"Ikke la totalstørrelsen på HTTP-overskriftene (inkludert statuslinjen) overstige HTTP_MAX_HEADER_SIZE. Denne sjekken er her for å beskytte innbyggere mot angrepsnektangrep der angriperen mater oss en uendelig overskrift som innebyggeren fortsetter å buffere. "
Fra Node.js HTTP-parser

# 4: Velg riktig rammeverk for Node.js REST API

Det er viktig å velge de rammene som passer din brukssak mest.

Express, Koa eller Hapi

Express, Koa og Hapi kan brukes til å lage nettleserapplikasjoner, og som sådan støtter de templering og gjengivelse - bare for å nevne noen funksjoner. Hvis applikasjonen din også må gi den brukervendte siden, er det fornuftig å gå for dem.

Restify

På den annen side fokuserer Restify på å hjelpe deg med å bygge REST-tjenester. Det eksisterer for å la deg bygge "strenge" API-tjenester som er vedlikeholdbare og observerbare. Restify kommer også med automatisk DTrace-støtte for alle dine behandlere.

Restify brukes i produksjonen i store applikasjoner som npm eller Netflix.

# 5: Black-Box Test Node.js REST API-ene

En av de beste måtene å teste REST API-er på er å behandle dem som svarte bokser.

Black-box testing er en metode for testing hvor funksjonaliteten til en applikasjon blir undersøkt uten kunnskap om dens interne strukturer eller virkninger. Ingen avhengighetene blir hånet eller stoppet, men systemet testes som en helhet.

En av modulene som kan hjelpe deg med black-box-testing av Node.js REST API-er er supertest.

En enkel test case som sjekker om en bruker blir returnert ved hjelp av testløperen mokka, kan implementeres slik:

const request = krever ('supertest')
 
beskrive ('GET / user /: id', function () {
  it ('returnerer en bruker', funksjon () {
    // nyere mokka-versjoner godtar også løfter
    returforespørsel (app)
      .Få ( '/ bruker')
      .set ('Godta', 'applikasjon / json')
      . forventning (200, {
        id: '1',
        navn: 'John Math'
      }, ferdig)
  })
})

Du kan spørre: hvordan blir dataene befolket i databasen som serverer REST API?

Generelt er det en god tilnærming å skrive testene dine på en slik måte at de tar så få antakelser om tilstanden til systemet som mulig. Likevel, i noen scenarier kan du finne deg selv et sted når du trenger å vite hva som er tilstanden i systemet nøyaktig, slik at du kan komme med påstander og oppnå høyere testdekning.

Så basert på dine behov, kan du fylle databasen med testdata på en av følgende måter:

  • kjør black-tests test-scenariene på et kjent undergruppe av produksjonsdata,
  • fyll databasen med lagde data før testsakene kjøres.

Selvfølgelig betyr ikke svarteboks-testing at du ikke trenger å gjøre enhetstesting, du må fortsatt skrive enhetstester for API-ene dine.

# 6: Gjør JWT-basert, statsløs autentisering

Ettersom REST-APIene dine må være statsløse, gjør også autentiseringslaget ditt. For dette er JWT (JSON Web Token) ideell.

JWT består av tre deler:

  • Topptekst, som inneholder typen token og hashingsalgoritmen
  • Nyttelast, med kravene
  • Signatur (JWT krypterer ikke nyttelasten, bare signerer den!)

Det er veldig enkelt å legge til JWT-basert godkjenning til applikasjonen din:

const koa = krever ('koa')
const jwt = krever ('koa-jwt')
const app = koa ()
app.use (jwt ({
  hemmelighet: 'veldig-hemmelig'
}))
// Beskyttet mellomvare
app.use (funksjon * () {
  // innholdet i tokenet vil være tilgjengelig på this.state.user
  this.body = {
    hemmelighet: '42'
  }
})

Etter det blir API-endepunktene beskyttet med JWT. For å få tilgang til de beskyttede sluttpunktene, må du oppgi symbolet i Autoriseringshode-feltet.

curl --header "Autorisasjon: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwI
iwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30
RMHrHDcEfxjoYZgeFONFh7HgQ "my-website.com

En ting du kan legge merke til er at JWT-modulen ikke er avhengig av noe databasesjikt. Dette er tilfelle fordi alle JWT-symboler kan verifiseres på egen hånd, og de kan også inneholde tid til å leve verdier.

Du må også alltid sørge for at alle API-endepunktene bare er tilgjengelige via en sikker tilkobling ved hjelp av HTTPS.

I en forrige artikkel forklarte vi nettgodkjenningsmetoder i detaljer - jeg anbefaler å sjekke det ut!

# 7: Bruk betingede forespørsler

Betingede forespørsler er HTTP-forespørsler som utføres på en annen måte, avhengig av spesifikke HTTP-overskrifter. Du kan tenke på disse overskriftene som forutsetninger: hvis de blir oppfylt, vil forespørslene bli utført på en annen måte.

Disse overskriftene prøver å sjekke om en versjon av en ressurs som er lagret på serveren samsvarer med en gitt versjon av den samme ressursen. Av denne grunn kan disse overskriftene være:

  • tidsstemplet for den siste modifiseringen,
  • eller en enhetskode, som er forskjellig for hver versjon.

Disse overskriftene er:

  • Sist endret (for å indikere når ressursen sist ble endret),
  • Etag (for å indikere entitetskoden),
  • Hvis-modifisert-siden (brukt sammen med den sist-modifiserte overskriften),
  • If-None-Match (brukt med Etag-overskriften),

La oss se på et eksempel!

Klienten nedenfor hadde ingen tidligere versjoner av doc-ressursen, så verken If-Modified-Since eller If-None-Match-overskriften ble brukt da ressursen ble sendt. Deretter svarer serveren med Etag og Last-Modified-overskriftene riktig satt.

Fra dokumentasjonen om betinget forespørsel fra MDN

Klienten kan stille inn overskriftene Hvis-modifisert-siden og hvis-ingen-match når den prøver å be om den samme ressursen - siden den har en versjon nå. Hvis svaret ville være det samme, svarer serveren ganske enkelt med statusen 304 - Not Modified og sender ikke ressursen igjen.

Fra dokumentasjonen om betinget forespørsel fra MDN

# 8: Omfavnelsesbegrensning

Takstbegrensning brukes til å kontrollere hvor mange forespørsler en gitt forbruker kan sende til API.

For å fortelle API-brukerne dine hvor mange forespørsler de har igjen, angi følgende overskrifter:

  • X-Rate-Limit-Limit, antallet forespørsler tillatt i et gitt tidsintervall
  • X-Rate-Limit-Resting, antall forespørsler som gjenstår i samme intervall,
  • X-Rate-Limit-Reset, tiden da takstgrensen blir tilbakestilt.

De fleste HTTP-rammer støtter det ut av esken (eller med plugins). Hvis du for eksempel bruker Koa, er det koa-ratelimit-pakken.

Merk at tidsvinduet kan variere basert på forskjellige API-leverandører - for eksempel bruker GitHub en time på det, mens Twitter 15 minutter.

# 9: Lag en riktig API-dokumentasjon

Du skriver APIer slik at andre kan bruke dem, dra nytte av dem. Å levere en API-dokumentasjon for Node.js REST API-er er avgjørende.

Følgende open source-prosjekter kan hjelpe deg med å lage dokumentasjon for APIene dine:

  • API Blueprint
  • Swagger

Hvis du vil bruke vertsbaserte produkter, kan du alternativt gå til Apiary.

# 10: Ikke gå glipp av fremtiden for APIer

I løpet av de siste årene oppsto to store spørrespråk for API-er - nemlig GraphQL fra Facebook og Falcor fra Netflix. Men hvorfor trenger vi dem til og med?

Se for deg følgende RESTful ressursforespørsel:

/ org / 1 / plass / 2 / docs / 1 / samarbeidspartnere?
inkluderer = email & page = 1 & limit = 10

Dette kan komme ut av hånden ganske enkelt - siden du ønsker å få det samme svarformatet for alle modellene dine hele tiden. Det er her GraphQL og Falcor kan hjelpe.

Om GraphQL

GraphQL er et spørrespråk for APIer og en kjøretid for å oppfylle disse spørsmålene med eksisterende data. GraphQL gir en fullstendig og forståelig beskrivelse av dataene i API-en din, gir klienter makten til å be om nøyaktig hva de trenger og ingenting mer, gjør det enklere å utvikle API-er over tid og muliggjør kraftige utviklerverktøy. - Les mer her.

Om Falcor

Falcor er den innovative dataplattformen som styrker Netflix UI-er. Falcor lar deg modellere alle backenddataene dine som et enkelt virtuelt JSON-objekt på Node-serveren. På klienten jobber du med det eksterne JSON-objektet ditt ved å bruke kjente JavaScript-operasjoner som få, angi og ringe. Hvis du kjenner dataene dine, kjenner du API-en din. - Les mer her.

Fantastiske REST APIer for inspirasjon

Hvis du skal begynne å utvikle et Node.js REST API eller lage en ny versjon av en eldre, har vi samlet fire eksempler fra det virkelige liv som er verdt å sjekke ut:

  • GitHub API
  • Twilio API
  • Stripe API
  • DigitalOcean API

Jeg håper at du nå har en bedre forståelse av hvordan APIer skal skrives ved å bruke Node.js. Gi meg beskjed i kommentarene hvis du savner noe!

Opprinnelig publisert på blog.risingstack.com 21. februar 2017.