Byg en REST API med Node.js og Express:Tilslutning af en database
I den første tutorial, Understanding RESTful API'er, lærte vi, hvad REST-arkitekturen er, hvad HTTP-anmodningsmetoder og -svar er, og hvordan man forstår et RESTful API-slutpunkt. I den anden vejledning, Sådan opsætter du en Express API-server, lærte vi, hvordan man bygger servere med begge Nodes indbyggede http
modul og Express-rammen, og hvordan man dirigerer den app, vi oprettede, til forskellige URL-endepunkter.
I øjeblikket bruger vi statiske data til at vise brugeroplysninger i form af et JSON-feed, når API-endepunktet rammes med en GET
anmodning. I denne vejledning skal vi opsætte en MySQL-database til at gemme alle data, oprette forbindelse til databasen fra vores Node.js-app og tillade API'en at bruge GET
, POST
, PUT
og DELETE
metoder til at skabe en komplet API.
Installation
Indtil nu har vi ikke brugt en database til at gemme eller manipulere nogen data, så vi vil oprette en. Denne vejledning vil bruge MySQL, og hvis du allerede har MySQL installeret på din computer, er du klar til at gå videre til næste trin.
Hvis du ikke har MySQL installeret, kan du downloade MAMP til macOS og Windows, som giver et gratis, lokalt servermiljø og database. Når du har downloadet dette, skal du åbne programmet og klikke på Start servere for at starte MySQL.
Ud over at konfigurere selve MySQL, vil vi have GUI-software til at se databasen og tabellerne. Til Mac skal du downloade SequelPro, og til Windows skal du downloade SQLyog. Når du har MySQL downloadet og kørt, kan du bruge SequelPro eller SQLyog til at oprette forbindelse til localhost
med brugernavnet root
og adgangskode root
på port 3306
.
Når alt er sat op her, kan vi gå videre til opsætning af databasen til vores API.
Opsætning af databasen
Tilføj en ny database i din databasevisningssoftware og kald den api
. Sørg for, at MySQL kører, ellers vil du ikke være i stand til at oprette forbindelse til localhost
.
Når du har api
database oprettet, flyt ind i den og kør følgende forespørgsel for at oprette en ny tabel.
CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT '', `email` varchar(50) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Denne SQL-forespørgsel vil skabe strukturen for vores users
bord. Hver bruger vil have et auto-inkrementerende id, et navn og en e-mailadresse.
Vi kan også fylde databasen med de samme data, som vi i øjeblikket viser gennem et statisk JSON-array ved at køre en INSERT
forespørgsel.
INSERT INTO users (name, email) VALUES ('Richard Hendricks', '[email protected]'), ('Bertram Gilfoyle', '[email protected]');
Det er ikke nødvendigt at indtaste id
felt, da det er automatisk inkrementerende. På dette tidspunkt har vi strukturen i vores tabel samt nogle eksempeldata at arbejde med.
Opretter forbindelse til MySQL
Tilbage i vores app skal vi oprette forbindelse til MySQL fra Node.js for at begynde at arbejde med dataene. Tidligere installerede vi mysql
npm-modul, og nu skal vi bruge det.
Opret en ny mappe kaldet data og lav en config.js fil.
Vi starter med at kræve mysql
modul i data/config.js .
const mysql = require('mysql');
Lad os oprette en config
objekt, der indeholder værten, brugeren, adgangskoden og databasen. Dette bør referere til api
database, vi har lavet og bruger standardindstillingerne for localhost.
// Set database connection credentials const config = { host: 'localhost', user: 'root', password: 'root', database: 'api', };
For effektivitetens skyld vil vi oprette en MySQL-pool, som giver os mulighed for at bruge flere forbindelser på én gang i stedet for manuelt at skulle åbne og lukke flere forbindelser.
// Create a MySQL pool const pool = mysql.createPool(config);
Til sidst eksporterer vi MySQL-puljen, så appen kan bruge den.
// Export the pool module.exports = pool;
Du kan se den færdige databasekonfigurationsfil i vores GitHub-repo.
Nu hvor vi opretter forbindelse til MySQL, og vores indstillinger er færdige, kan vi gå videre til at interagere med databasen fra API'et.
Hent API-data fra MySQL
I øjeblikket er vores routes.js
fil opretter manuelt en JSON-array af brugere, som ser sådan ud.
const users = [{ ...
Da vi ikke længere kommer til at bruge statiske data, kan vi slette hele det array og erstatte det med et link til vores MySQL-pool.
// Load the MySQL pool connection const pool = require('../data/config');
Tidligere var GET
for /users
stien sendte de statiske users
data. Vores opdaterede kode vil i stedet forespørge databasen om disse data. Vi skal bruge en SQL-forespørgsel til at SELECT
alt fra users
tabel, som ser sådan ud.
SELECT * FROM users
Her er hvad vores nye /users
get-ruten vil se ud ved at bruge pool.query()
metode.
// Display all users app.get('/users', (request, response) => { pool.query('SELECT * FROM users', (error, result) => { if (error) throw error; response.send(result); }); });
Her kører vi SELECT
forespørgsel og derefter sende resultatet som JSON til klienten via /users
endepunkt. Hvis du genstarter serveren og navigerer til /users
side, vil du se de samme data som før, men nu er det dynamisk.
Brug af URL-parametre
Indtil videre har vores endepunkter været statiske stier – enten /
root eller /users
— men hvad med, når vi kun vil se data om en bestemt bruger? Vi bliver nødt til at bruge et variabelt slutpunkt.
For vores brugere ønsker vi måske at hente oplysninger om hver enkelt bruger baseret på deres unikke id. For at gøre det, ville vi bruge et kolon (:
) for at angive, at det er en ruteparameter.
// Display a single user by ID app.get('/users/:id', (request, response) => { ... }); });
Vi kan hente parameteren for denne sti med request.params
ejendom. Da vores hedder id
, det vil være sådan, vi omtaler det.
const id = request.params.id;
Nu tilføjer vi en WHERE
klausul til vores SELECT
sætning for kun at få resultater, der har det angivne id
.
Vi bruger ?
som en pladsholder for at undgå SQL-injektion og sende id'et igennem som en parameter i stedet for at bygge en sammenkædet streng, hvilket ville være mindre sikkert.
pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send(result); });
Den fulde kode for vores individuelle brugerressource ser nu sådan ud:
// Display a single user by ID app.get('/users/:id', (request, response) => { const id = request.params.id; pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send(result); }); });
Nu kan du genstarte serveren og navigere til https://localhost/users/2
for kun at se oplysningerne om Gilfoyle. Hvis du får en fejl som Cannot GET /users/2
, betyder det, at du skal genstarte serveren.
Hvis du går til denne URL, skulle det returnere et enkelt resultat.
[{ id: 2, name: "Bertram Gilfoyle", email: "[email protected]" }]
Hvis det er det, du ser, tillykke:du har opsat en dynamisk ruteparameter!
Send en POST-anmodning
Indtil videre har alt, hvad vi har lavet, brugt GET
anmodninger. Disse anmodninger er sikre, hvilket betyder, at de ikke ændrer serverens tilstand. Vi har simpelthen set JSON-data.
Nu skal vi begynde at gøre API'en virkelig dynamisk ved at bruge en POST
anmode om at tilføje nye data.
Jeg nævnte tidligere i artiklen Understanding REST, at vi ikke bruger verber som add
eller delete
i URL'en for at udføre handlinger. For at tilføje en ny bruger til databasen, POST
til den samme URL, som vi ser dem fra, men opsæt bare en separat rute for det.
// Add a new user app.post('/users', (request, response) => { ... });
Bemærk, at vi bruger app.post()
i stedet for app.get()
nu.
Da vi opretter i stedet for at læse, bruger vi en INSERT
forespørgsel her, ligesom vi gjorde ved initialiseringen af databasen. Vi sender hele request.body
videre til SQL-forespørgslen.
pool.query('INSERT INTO users SET ?', request.body, (error, result) => { if (error) throw error;
Vi vil også angive status for svaret som 201
, som står for Created
. For at få id'et for det sidst indsatte element, bruger vi insertId
ejendom.
response.status(201).send(`User added with ID: ${result.insertId}`);
Hele vores POST
modtage kode vil se sådan ud.
// Add a new user app.post('/users', (request, response) => { pool.query('INSERT INTO users SET ?', request.body, (error, result) => { if (error) throw error; response.status(201).send(`User added with ID: ${result.insertId}`); }); });
Nu kan vi sende en POST
anmodning igennem. Det meste af tiden, når du sender en POST
anmodning, gør du det via en webformular. Vi lærer, hvordan du sætter det op i slutningen af denne artikel, men den hurtigste og nemmeste måde at sende en test POST
på er med cURL ved hjælp af -d (--data)
flag.
Vi kører curl -d
, efterfulgt af en forespørgselsstreng, der indeholder alle nøgle/værdi-parrene og anmodningens slutpunkt.
curl -d "name=Dinesh Chugtai&[email protected]" http://localhost:3002/users
Når du har sendt denne anmodning igennem, bør du få et svar fra serveren.
User added with ID: 3
Hvis du navigerer til http://localhost/users
, vil du se den seneste post tilføjet til listen.
Send en PUT-anmodning
POST
er nyttig til at tilføje en ny bruger, men vi vil gerne bruge PUT
at ændre en eksisterende bruger. PUT
er idempotent, hvilket betyder, at du kan sende den samme anmodning igennem flere gange, og kun én handling vil blive udført. Dette er anderledes end POST
, for hvis vi sendte vores nye brugeranmodning igennem mere end én gang, ville den blive ved med at oprette nye brugere.
For vores API skal vi konfigurere PUT
for at kunne håndtere redigering af en enkelt bruger, så vi kommer til at bruge :id
ruteparameter denne gang.
Lad os oprette en UPDATE
forespørgsel og sørg for, at den kun gælder for det anmodede id med WHERE
klausul. Vi bruger to ?
pladsholdere, og de værdier, vi videregiver, vil gå i sekventiel rækkefølge.
// Update an existing user app.put('/users/:id', (request, response) => { const id = request.params.id; pool.query('UPDATE users SET ? WHERE id = ?', [request.body, id], (error, result) => { if (error) throw error; response.send('User updated successfully.'); }); });
Til vores test vil vi redigere bruger 2
og opdater e-mailadressen fra [email protected] til [email protected]. Vi kan bruge cURL igen med [-X (--request)]
flag, for eksplicit at angive, at vi sender en PUT-anmodning igennem.
curl -X PUT -d "name=Bertram Gilfoyle" -d "[email protected]" http://localhost:3002/users/2
Sørg for at genstarte serveren, før du sender anmodningen, ellers får du koden Cannot PUT /users/2
fejl.
Du bør se dette:
User updated successfully.
Brugerdataene med id 2
skal nu være opdateret.
Send en SLETTE-anmodning
Vores sidste opgave for at fuldføre API'ets CRUD-funktionalitet er at lave en mulighed for at slette en bruger fra databasen. Denne anmodning vil bruge DELETE
SQL-forespørgsel med WHERE
, og det vil slette en individuel bruger angivet af en ruteparameter.
// Delete a user app.delete('/users/:id', (request, response) => { const id = request.params.id; pool.query('DELETE FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send('User deleted.'); }); });
Vi kan bruge -X
igen med cURL for at sende sletningen igennem. Lad os slette den seneste bruger, vi har oprettet.
curl -X DELETE http://localhost:3002/users/3
Du vil se succesmeddelelsen.
User deleted.
Naviger til http://localhost:3002
, og du vil se, at der kun er to brugere nu.
Tillykke! På dette tidspunkt er API'en færdig. Besøg GitHub-reposen for at se den komplette kode for routes.js .
Send anmodninger gennem request
Modul
I begyndelsen af denne artikel installerede vi fire afhængigheder, og en af dem var request
modul. I stedet for at bruge cURL-anmodninger kan du lave en ny fil med alle data og sende den igennem. Jeg opretter en fil kaldet post.js der vil oprette en ny bruger via POST
.
const request = require('request'); const json = { "name": "Dinesh Chugtai", "email": "[email protected]", }; request.post({ url: 'http://localhost:3002/users', body: json, json: true, }, function (error, response, body) { console.log(body); });
Vi kan kalde dette ved at bruge node post.js
i et nyt terminalvindue, mens serveren kører, og det vil have samme effekt som at bruge cURL. Hvis noget ikke virker med cURL, skal du request
modul er nyttigt, da vi kan se fejlen, svaret og brødteksten.
Afsendelse af anmodninger via en webformular
Normalt POST
og andre HTTP-metoder, der ændrer serverens tilstand, sendes ved hjælp af HTML-formularer. I dette meget enkle eksempel kan vi oprette en index.html fil hvor som helst, og lav et felt til et navn og en e-mailadresse. Formularens handling vil pege på ressourcen, i dette tilfælde http//localhost:3002/users
, og vi angiver metoden som post
.
Opret index.html og tilføj følgende kode til det:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Node.js Express REST API</title> </head> <body> <form action="http://localhost:3002/users" method="post"> <label for="name">Name</label> <input type="text" name="name"> <label for="email">Email</label> <input type="email" name="email"> <input type="submit"> </form> </body> </html>
Åbn denne statiske HTML-fil i din browser, udfyld den, og send den, mens serveren kører i terminalen. Du bør se svaret fra User added with ID: 4
, og du bør være i stand til at se den nye liste over brugere.