Bygg ett REST API med Node.js och Express:Ansluta en databas
I den första handledningen, Understanding RESTful APIs, lärde vi oss vad REST-arkitekturen är, vad HTTP-begäransmetoder och -svar är och hur man förstår en RESTful API-slutpunkt. I den andra handledningen, Hur man ställer in en Express API-server, lärde vi oss hur man bygger servrar med båda Nodes inbyggda http
modulen och Express-ramverket, och hur man dirigerar appen vi skapade till olika URL-slutpunkter.
För närvarande använder vi statisk data för att visa användarinformation i form av ett JSON-flöde när API-slutpunkten träffas med en GET
begäran. I den här handledningen kommer vi att ställa in en MySQL-databas för att lagra all data, ansluta till databasen från vår Node.js-app och tillåta API:et att använda GET
, POST
, PUT
och DELETE
metoder för att skapa ett komplett API.
Installation
Hittills har vi inte använt en databas för att lagra eller manipulera någon data, så vi kommer att sätta upp en. Den här handledningen kommer att använda MySQL, och om du redan har MySQL installerat på din dator är du redo att gå vidare till nästa steg.
Om du inte har MySQL installerat kan du ladda ner MAMP för macOS och Windows, som ger en gratis lokal servermiljö och databas. När du har laddat ner detta öppnar du programmet och klickar på Starta servrar för att starta MySQL.
Förutom att ställa in själva MySQL, vill vi att GUI-programvaran ska se databasen och tabellerna. För Mac, ladda ner SequelPro och för Windows ladda ner SQLyog. När du har laddat ner och kört MySQL kan du använda SequelPro eller SQLyog för att ansluta till localhost
med användarnamnet root
och lösenord root
på port 3306
.
När allt är inställt här kan vi gå vidare till att ställa in databasen för vårt API.
Konfigurera databasen
Lägg till en ny databas i din databasvisningsprogramvara och kalla den api
. Se till att MySQL körs, annars kommer du inte att kunna ansluta till localhost
.
När du har api
databas skapad, flytta in i den och kör följande fråga för att skapa en ny tabell.
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;
Denna SQL-fråga kommer att skapa strukturen för våra users
tabell. Varje användare kommer att ha ett auto-inkrementerande ID, ett namn och en e-postadress.
Vi kan också fylla databasen med samma data som vi för närvarande visar genom en statisk JSON-array genom att köra en INSERT
fråga.
INSERT INTO users (name, email) VALUES ('Richard Hendricks', '[email protected]'), ('Bertram Gilfoyle', '[email protected]');
Du behöver inte ange id
fältet, eftersom det ökar automatiskt. Vid det här laget har vi strukturen för vår tabell samt några exempeldata att arbeta med.
Ansluter till MySQL
Tillbaka i vår app måste vi ansluta till MySQL från Node.js för att börja arbeta med datan. Tidigare installerade vi mysql
npm-modul, och nu ska vi använda den.
Skapa en ny katalog som heter data och gör en config.js fil.
Vi börjar med att kräva mysql
modul i data/config.js .
const mysql = require('mysql');
Låt oss skapa en config
objekt som innehåller värden, användaren, lösenordet och databasen. Detta bör referera till api
databas vi skapade och använder standardinställningarna för localhost.
// Set database connection credentials const config = { host: 'localhost', user: 'root', password: 'root', database: 'api', };
För effektivitetens skull kommer vi att skapa en MySQL-pool, som gör att vi kan använda flera anslutningar samtidigt istället för att manuellt behöva öppna och stänga flera anslutningar.
// Create a MySQL pool const pool = mysql.createPool(config);
Slutligen kommer vi att exportera MySQL-poolen så att appen kan använda den.
// Export the pool module.exports = pool;
Du kan se den färdiga databaskonfigurationsfilen i vår GitHub-repo.
Nu när vi ansluter till MySQL och våra inställningar är klara, kan vi gå vidare till att interagera med databasen från API:t.
Hämta API-data från MySQL
För närvarande är vår routes.js
filen skapar manuellt en JSON-array av användare, som ser ut så här.
const users = [{ ...
Eftersom vi inte längre kommer att använda statisk data, kan vi ta bort hela arrayen och ersätta den med en länk till vår MySQL-pool.
// Load the MySQL pool connection const pool = require('../data/config');
Tidigare var GET
för /users
sökvägen skickade de statiska users
data. Vår uppdaterade kod kommer att fråga databasen efter den datan istället. Vi kommer att använda en SQL-fråga för att SELECT
allt från users
tabell, som ser ut så här.
SELECT * FROM users
Här är vad våra nya /users
get route kommer att se ut med pool.query()
metod.
// Display all users app.get('/users', (request, response) => { pool.query('SELECT * FROM users', (error, result) => { if (error) throw error; response.send(result); }); });
Här kör vi SELECT
fråga och sedan skicka resultatet som JSON till klienten via /users
slutpunkt. Om du startar om servern och navigerar till /users
sida, kommer du att se samma data som tidigare, men nu är den dynamisk.
Använda URL-parametrar
Hittills har våra slutpunkter varit statiska vägar – antingen /
root eller /users
— men hur är det när vi bara vill se data om en specifik användare? Vi måste använda en variabel slutpunkt.
För våra användare kanske vi vill hämta information om varje enskild användare baserat på deras unika id. För att göra det skulle vi använda ett kolon (:
) för att ange att det är en ruttparameter.
// Display a single user by ID app.get('/users/:id', (request, response) => { ... }); });
Vi kan hämta parametern för denna sökväg med request.params
fast egendom. Eftersom vårt heter id
, det är så vi refererar till det.
const id = request.params.id;
Nu lägger vi till en WHERE
klausul till vår SELECT
för att bara få resultat som har det angivna id
.
Vi använder ?
som en platshållare för att undvika SQL-injektion och skicka igenom ID:t som en parameter, istället för att bygga en sammanlänkade sträng, vilket skulle vara mindre säkert.
pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send(result); });
Den fullständiga koden för vår individuella användarresurs ser nu ut så här:
// 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 starta om servern och navigera till https://localhost/users/2
för att bara se informationen för Gilfoyle. Om du får ett felmeddelande som Cannot GET /users/2
, betyder det att du måste starta om servern.
Att gå till den här webbadressen bör returnera ett enda resultat.
[{ id: 2, name: "Bertram Gilfoyle", email: "[email protected]" }]
Om det är vad du ser, grattis:du har framgångsrikt konfigurerat en dynamisk ruttparameter!
Skicka en POST-förfrågan
Hittills har allt vi har gjort använt GET
förfrågningar. Dessa förfrågningar är säkra, vilket innebär att de inte ändrar serverns tillstånd. Vi har helt enkelt tittat på JSON-data.
Nu ska vi börja göra API:t verkligt dynamiskt genom att använda en POST
begära att lägga till nya data.
Jag nämnde tidigare i Understanding REST-artikeln att vi inte använder verb som add
eller delete
i URL:en för att utföra åtgärder. För att lägga till en ny användare till databasen, POST
till samma URL som vi ser dem från, men ställ bara in en separat rutt för det.
// Add a new user app.post('/users', (request, response) => { ... });
Observera att vi använder app.post()
istället för app.get()
nu.
Eftersom vi skapar istället för att läsa, använder vi en INSERT
fråga här, ungefär som vi gjorde vid initieringen av databasen. Vi skickar hela request.body
till SQL-frågan.
pool.query('INSERT INTO users SET ?', request.body, (error, result) => { if (error) throw error;
Vi kommer också att ange status för svaret som 201
, som står för Created
. För att få ID för det senast infogade objektet använder vi insertId
egendom.
response.status(201).send(`User added with ID: ${result.insertId}`);
Hela vår POST
mottagningskoden kommer att se ut så här.
// 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 skicka en POST
begära igenom. För det mesta när du skickar en POST
begäran gör du det via ett webbformulär. Vi lär oss hur du ställer in det i slutet av den här artikeln, men det snabbaste och enklaste sättet att skicka ett test POST
är med cURL, med -d (--data)
flagga.
Vi kör curl -d
, följt av en frågesträng som innehåller alla nyckel/värdepar och begärans slutpunkt.
curl -d "name=Dinesh Chugtai&[email protected]" http://localhost:3002/users
När du har skickat igenom denna begäran bör du få ett svar från servern.
User added with ID: 3
Om du navigerar till http://localhost/users
, kommer du att se den senaste posten som lagts till i listan.
Skicka en PUT-förfrågan
POST
är användbart för att lägga till en ny användare, men vi vill använda PUT
för att ändra en befintlig användare. PUT
är idempotent, vilket innebär att du kan skicka samma begäran flera gånger och endast en åtgärd kommer att utföras. Detta är annorlunda än POST
, för om vi skickade igenom vår nya användarförfrågan mer än en gång, skulle den fortsätta att skapa nya användare.
För vårt API kommer vi att ställa in PUT
för att kunna hantera redigering av en enskild användare, så vi kommer att använda :id
ruttparameter den här gången.
Låt oss skapa en UPDATE
fråga och se till att den endast gäller det begärda ID:t med WHERE
klausul. Vi använder två ?
platshållare, och de värden vi skickar kommer att gå i sekventiell ordning.
// 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.'); }); });
För vårt test kommer vi att redigera användare 2
och uppdatera e-postadressen från [email protected] till [email protected]. Vi kan använda cURL igen, med [-X (--request)]
flagga, för att uttryckligen ange att vi skickar en PUT-förfrågan.
curl -X PUT -d "name=Bertram Gilfoyle" -d "[email protected]" http://localhost:3002/users/2
Se till att starta om servern innan du skickar begäran, annars får du Cannot PUT /users/2
fel.
Du bör se detta:
User updated successfully.
Användardata med id 2
bör nu uppdateras.
Skicka en DELETE-förfrågan
Vår sista uppgift för att slutföra CRUD-funktionaliteten i API:t är att skapa ett alternativ för att ta bort en användare från databasen. Denna begäran kommer att använda DELETE
SQL-fråga med WHERE
, och det kommer att ta bort en enskild användare specificerad av en ruttparameter.
// 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 använda -X
igen med cURL för att skicka bort raderingen. Låt oss ta bort den senaste användaren vi skapade.
curl -X DELETE http://localhost:3002/users/3
Du kommer att se framgångsmeddelandet.
User deleted.
Navigera till http://localhost:3002
, och du kommer att se att det bara finns två användare nu.
Grattis! Vid denna tidpunkt är API:et komplett. Besök GitHub-repo för att se den fullständiga koden för routes.js .
Skicka förfrågningar genom request
Modul
I början av den här artikeln installerade vi fyra beroenden, och ett av dem var request
modul. Istället för att använda cURL-förfrågningar kan du skapa en ny fil med all data och skicka igenom den. Jag skapar en fil som heter post.js som skapar en ny användare 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 kalla detta med node post.js
i ett nytt terminalfönster medan servern körs, och det kommer att ha samma effekt som att använda cURL. Om något inte fungerar med cURL, request
modulen är användbar eftersom vi kan se felet, svaret och texten.
Skicka förfrågningar via ett webbformulär
Vanligtvis POST
och andra HTTP-metoder som ändrar serverns tillstånd skickas med HTML-formulär. I detta mycket enkla exempel kan vi skapa en index.html fil var som helst och skapa ett fält för ett namn och en e-postadress. Formulärets åtgärd kommer att peka på resursen, i det här fallet http//localhost:3002/users
, och vi kommer att specificera metoden som post
.
Skapa index.html och lägg till följande kod till den:
<!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>
Öppna denna statiska HTML-fil i din webbläsare, fyll i den och skicka den medan servern körs i terminalen. Du bör se svaret från User added with ID: 4
, och du bör kunna se den nya listan med användare.