10 praktische tips voor het schrijven van REST API's van Node.js

In dit artikel behandelen we best practices voor het schrijven van Node.js REST API's, inclusief onderwerpen zoals het benoemen van uw routes, authenticatie, black-box testen en het gebruik van juiste cachekoppen voor deze bronnen.

Een van de meest populaire use-cases voor Node.js is het schrijven van RESTful API's. Hoewel we onze klanten helpen problemen met hun toepassingen met Trace te vinden, ervaren we met onze Node.js monitoringtool voortdurend dat ontwikkelaars veel problemen hebben met REST API's.

Ik hoop dat deze best practices die we bij RisingStack gebruiken, kunnen helpen:

# 1: Gebruik HTTP-methoden en API-routes

Stel je voor dat je een RESTful API van Node.js bouwt voor het maken, bijwerken, ophalen of verwijderen van gebruikers. Voor deze bewerkingen heeft HTTP al de juiste toolset: POST, PUT, GET, PATCH of DELETE.

Als best practice moeten uw API-routes altijd zelfstandige naamwoorden gebruiken als bronidentificaties. Over de bronnen van de gebruiker gesproken, de routing kan er zo uitzien:

  • POST / gebruiker of PUT / gebruiker: / id om een ​​nieuwe gebruiker te maken,
  • GET / gebruiker om een ​​lijst met gebruikers op te halen,
  • GET / user /: id om een ​​gebruiker op te halen,
  • PATCH / user /: id om een ​​bestaand gebruikersrecord te wijzigen,
  • DELETE / user /: id om een ​​gebruiker te verwijderen.

# 2: Gebruik HTTP-statuscodes correct

Als er iets misgaat tijdens het indienen van een verzoek, moet u daarvoor de juiste statuscode instellen in het antwoord:

  • 2xx, als alles in orde was,
  • 3xx, als de bron is verplaatst,
  • 4xx, als aan het verzoek niet kan worden voldaan vanwege een clientfout (zoals het aanvragen van een bron die niet bestaat),
  • 5xx, als er iets mis is gegaan aan de API-kant (er is een uitzondering opgetreden).

Als u Express gebruikt, is het instellen van de statuscode net zo eenvoudig als res.status (500) .send ({error: 'Interne serverfout is opgetreden'}). Op dezelfde manier met Restify: res.status (201).

Controleer de lijst met HTTP-statuscodes voor een volledige lijst

# 3: Gebruik HTTP-headers om metagegevens te verzenden

Gebruik HTTP-headers om metagegevens bij te voegen over de payload die u gaat verzenden. Headers zoals deze kunnen informatie zijn over:

  • paginering,
  • snelheidsbeperkend,
  • of authenticatie.

Een lijst met gestandaardiseerde HTTP-headers is hier te vinden.

Als u aangepaste metagegevens in uw kopteksten moet instellen, is het een goede gewoonte om ze vooraf te laten gaan met X. Als u bijvoorbeeld CSRF-tokens gebruikte, was dit een gebruikelijke (maar niet-standaard) manier om ze X-Csrf te noemen -Token. Met RFC 6648 werden ze echter verouderd. Nieuwe API's moeten hun best doen om geen kopnamen te gebruiken die in conflict kunnen komen met andere applicaties. OpenStack geeft bijvoorbeeld de kopteksten aan OpenStack:

OpenStack-Identity-Account-ID
OpenStack-Networking-Host-Name
OpenStack Object-Storage-beleid

Merk op dat de HTTP-standaard geen limiet definieert voor de headers; Node.js (vanaf het schrijven van dit artikel) legt echter om praktische redenen een limiet van 80 KB op aan het headers-object.

"Sta niet toe dat de totale grootte van de HTTP-headers (inclusief de statusregel) HTTP_MAX_HEADER_SIZE overschrijdt. Deze controle is hier om insluiters te beschermen tegen denial-of-service-aanvallen waarbij de aanvaller ons een eindeloze header toevoegt die de insluiter blijft bufferen. "
Van de HTTP-parser Node.js

# 4: Kies het juiste raamwerk voor uw Node.js REST API

Het is belangrijk om het kader te kiezen dat het meest geschikt is voor uw use-case.

Express, Koa of Hapi

Express, Koa en Hapi kunnen worden gebruikt om browsertoepassingen te maken en als zodanig ondersteunen ze sjablonen en rendering - om maar een paar functies te noemen. Als uw toepassing ook de gebruikersgerichte kant moet bieden, is het logisch om voor hen te kiezen.

Restify

Anderzijds richt Restify zich op het helpen van REST-services. Het bestaat om u "strikte" API-services te laten bouwen die onderhoudbaar en waarneembaar zijn. Restify wordt ook geleverd met automatische DTrace-ondersteuning voor al uw handlers.

Restify wordt gebruikt in productie in grote applicaties zoals npm of Netflix.

# 5: Black-Box Test uw Node.js REST API's

Een van de beste manieren om uw REST API's te testen, is ze als zwarte dozen te behandelen.

Black-box testen is een testmethode waarbij de functionaliteit van een toepassing wordt onderzocht zonder de kennis van de interne structuren of werking. Dus geen van de afhankelijkheden worden bespot of verstopt, maar het systeem wordt als geheel getest.

Een van de modules die u kunnen helpen bij het testen van Black-box Node.js REST API's is supertest.

Een eenvoudige testcase die controleert of een gebruiker wordt geretourneerd met de testrunner mokka kan als volgt worden geïmplementeerd:

const request = vereisen ('supertest')
 
beschrijven ('GET / user /: id', function () {
  it ('retourneert een gebruiker', function () {
    // nieuwere mokka-versies accepteren ook beloften
    retourverzoek (app)
      .get ( '/ gebruiker)
      .set ('Accept', 'application / json')
      . verwachten (200, {
        id: '1',
        naam: 'John Math'
      }, gedaan)
  })
})

U vraagt ​​zich misschien af: hoe worden de gegevens ingevuld in de database die de REST API bedient?

Over het algemeen is het een goede benadering om uw tests zo te schrijven dat ze zo min mogelijk aannames maken over de status van het systeem. Toch kunt u zich in sommige scenario's op een plek bevinden waar u precies moet weten wat de status van het systeem is, zodat u beweringen kunt doen en een hogere testdekking kunt bereiken.

Dus op basis van uw behoeften, kunt u de database op een van de volgende manieren vullen met testgegevens:

  • voer uw black-box testscenario's uit op een bekende subset van productiegegevens,
  • vul de database met bewerkte gegevens voordat de testcases worden uitgevoerd.

Black-box-testen betekent natuurlijk niet dat u geen unit-testen hoeft uit te voeren, u moet nog steeds unit-testen voor uw API's schrijven.

# 6: Voer op JWT gebaseerde, staatloze authenticatie uit

Omdat uw REST-API's stateloos moeten zijn, doet uw authenticatielaag dat ook. Hiervoor is JWT (JSON Web Token) ideaal.

JWT bestaat uit drie delen:

  • Koptekst, met het type token en het hashing-algoritme
  • Payload, met de claims
  • Handtekening (JWT versleutelt de lading niet, maar ondertekent het gewoon!)

Het is heel eenvoudig om op JWT gebaseerde authenticatie aan uw applicatie toe te voegen:

const koa = vereisen ('koa')
const jwt = vereisen ('koa-jwt')
const app = koa ()
app.use (JWT ({
  geheim: 'zeer geheim'
}))
// Beschermde middleware
app.use (function * () {
  // inhoud van het token zal beschikbaar zijn op this.state.user
  this.body = {
    geheim: '42'
  }
})

Daarna worden de API-eindpunten beschermd met JWT. Om toegang te krijgen tot de beschermde eindpunten, moet u het token opgeven in het veld Autorisatieheader.

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

Een ding dat je zou kunnen opmerken is dat de JWT-module niet afhankelijk is van een databaselaag. Dit is het geval omdat alle JWT-tokens zelf kunnen worden geverifieerd en ze ook tijd kunnen bevatten om te leven.

U moet er ook altijd voor zorgen dat al uw API-eindpunten alleen toegankelijk zijn via een beveiligde verbinding met HTTPS.

In een vorig artikel hebben we de methoden voor webauthenticatie gedetailleerd uitgelegd - ik raad je aan dit te bekijken!

# 7: Gebruik voorwaardelijke verzoeken

Voorwaardelijke aanvragen zijn HTTP-aanvragen die anders worden uitgevoerd, afhankelijk van specifieke HTTP-headers. Je kunt deze headers beschouwen als voorwaarden: als ze worden vervuld, worden de aanvragen op een andere manier uitgevoerd.

Deze headers proberen te controleren of een versie van een bron die is opgeslagen op de server overeenkomt met een bepaalde versie van dezelfde bron. Om deze reden kunnen deze headers zijn:

  • het tijdstempel van de laatste wijziging,
  • of een entiteitstag, die voor elke versie verschilt.

Deze headers zijn:

  • Laatst gewijzigd (om aan te geven wanneer de resource voor het laatst is gewijzigd),
  • Etag (om de entiteitstag aan te geven),
  • Indien-gewijzigd-sinds (gebruikt met de kop Laatste gewijzigd),
  • Indien-geen-overeenkomst (gebruikt met de Etag-koptekst),

Laten we een voorbeeld bekijken!

De onderstaande client had geen eerdere versies van de doc-bron, dus noch de If-Modified-Since, noch de If-None-Match-koptekst werd toegepast toen de resource werd verzonden. Vervolgens reageert de server met de Etag en Last-Modified headers correct ingesteld.

Uit de MDN voorwaardelijke aanvraagdocumentatie

De client kan de headers If-Modified-Since en If-None-Match instellen zodra deze probeert dezelfde bron aan te vragen, aangezien deze nu een versie heeft. Als het antwoord hetzelfde zou zijn, antwoordt de server eenvoudig met de status 304 - Niet gewijzigd en verzendt de bron niet opnieuw.

Uit de MDN voorwaardelijke aanvraagdocumentatie

# 8: Omarm snelheidsbeperking

Tariefbeperking wordt gebruikt om te bepalen hoeveel aanvragen een bepaalde consument naar de API kan verzenden.

Om uw API-gebruikers te vertellen hoeveel aanvragen ze nog hebben, stelt u de volgende headers in:

  • X-snelheid-limiet-limiet, het aantal aanvragen dat binnen een bepaald tijdsinterval is toegestaan
  • X-snelheid-limiet-resterend, het aantal resterende aanvragen in hetzelfde interval,
  • X-snelheid-limiet-reset, het tijdstip waarop de snelheidslimiet opnieuw wordt ingesteld.

De meeste HTTP-frameworks ondersteunen het direct (of met plug-ins). Als u bijvoorbeeld Koa gebruikt, is er het koa-ratelimit-pakket.

Merk op dat het tijdvenster kan variëren op basis van verschillende API-providers - GitHub gebruikt bijvoorbeeld een uur daarvoor, terwijl Twitter 15 minuten duurt.

# 9: Maak een juiste API-documentatie

U schrijft API's zodat anderen ze kunnen gebruiken en ervan kunnen profiteren. Het leveren van een API-documentatie voor uw Node.js REST API's is cruciaal.

De volgende open-sourceprojecten kunnen u helpen bij het maken van documentatie voor uw API's:

  • API-blauwdruk
  • Branie

Als alternatief, als u gehoste producten wilt gebruiken, kunt u voor bijenteelt kiezen.

# 10: Mis de toekomst van API's niet

In de afgelopen jaren zijn er twee belangrijke query-talen voor API's ontstaan ​​- namelijk GraphQL van Facebook en Falcor van Netflix. Maar waarom hebben we ze zelfs nodig?

Stelt u zich het volgende RESTful resource-verzoek voor:

/ Org / 1 / ruimte / 2 / docs / 1 / medewerkers?
include = email & page = 1 & limit = 10

Dit kan vrij gemakkelijk uit de hand lopen - omdat je altijd dezelfde responsindeling voor al je modellen wilt krijgen. Dit is waar GraphQL en Falcor kunnen helpen.

Over GraphQL

GraphQL is een querytaal voor API's en een runtime voor het uitvoeren van die vragen met uw bestaande gegevens. GraphQL biedt een complete en begrijpelijke beschrijving van de gegevens in uw API, geeft klanten de mogelijkheid om precies te vragen wat ze nodig hebben en niets meer, maakt het eenvoudiger om API's in de loop van de tijd te evolueren en maakt krachtige ontwikkelaarstools mogelijk. - Lees hier meer.

Over Falcor

Falcor is het innovatieve dataplatform dat de Netflix UI's aanstuurt. Met Falcor kunt u al uw backend-gegevens modelleren als één Virtual JSON-object op uw Node-server. Op de client werkt u met uw externe JSON-object met behulp van bekende JavaScript-bewerkingen zoals ophalen, instellen en aanroepen. Als u uw gegevens kent, kent u uw API. - Lees hier meer.

Verbazingwekkende REST API's voor inspiratie

Als u op het punt staat een Node.js REST API te ontwikkelen of een nieuwe versie van een oudere versie te maken, hebben we vier voorbeelden uit de praktijk verzameld die het bekijken waard zijn:

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

Ik hoop dat je nu een beter begrip hebt van hoe API's moeten worden geschreven met behulp van Node.js. Laat het me in de reacties weten als je iets mist!

Oorspronkelijk gepubliceerd op blog.risingstack.com op 21 februari 2017.