Hoe bouw je een Rest API met NodeJS, Express, en MySQL

Met kennis van JavaScript en MySQL, kunnen we onze NodeJS API bouwen met Express.

Ik heb wat onderzoek gedaan, en ik probeerde een API vanaf nul te ontwikkelen.
Ik hou ervan om dingen te vereenvoudigen en probeer duplicatie van code te vermijden.

Deze gids zal u laten zien hoe u een API vanaf nul kunt bouwen:
U leert hoe u routes kunt maken,
hoe u mysql2 kunt gebruiken, hoe u de database kunt configureren en ermee verbinding kunt maken, en hoe u query’s kunt uitvoeren met voorbereide statements.
Hoe je een middleware maakt die een extra argument kan krijgen naast req, res, en next callback.
Je leert hoe je de data van het request object kunt controleren met behulp van de Express Validator module.
U leert hoe u de JWT-module kunt gebruiken om een token voor de gebruiker te maken, het token te verifiëren, en het object te krijgen dat in het token is opgeslagen.
Daarnaast leert u hoe u gebruikers toestemming kunt geven om toegang te krijgen tot een bepaalde route op basis van hun gebruikersrollen.

Technologieën en pakketten:

  • NodeJS
  • Express
  • mysql2
  • bcryptjs
  • jsonwebtoken
  • express-validator
  • dotenv
  • cors

Installeren van MySQL:

Ik gebruik WSL, en u kunt deze tutorial gebruiken om te zien hoe u MySQL in WSL installeert.
U moet ervoor zorgen dat MySQL draait met dit commando:

sudo service mysql status
Enter fullscreen mode Exit fullscreen mode

Als het niet draait, gebruik dan gewoon:

sudo service mysql start
Open schermmodus Sluit schermmodus af

Toepassingsoverzicht:

We bouwen een rest-API voor CRUD-bewerkingen: gebruikers aanmaken, lezen, bijwerken en verwijderen.

Maak de projectmap aan en installeer alle afhankelijkheden:

mkdir mysql-node-express && cd mysql-node-expressnpm init -ynpm i express express-validator mysql2 cors dotenv jsonwebtoken -Snpm i nodemon -D
Ga naar fullscreen-modus Sluit fullscreen-modus af

Ga naar het bestand package.json en verander de waarde “main” in “src/server.js” en voeg deze scripts toe aan het scriptsobject:

"start": "node src/server.js","dev": "nodemon"
Invoeren van de modus volledig scherm Uitgaan van de modus volledig scherm

package.json moet er als volgt uitzien:

Creëer .env bestand:

We zullen het .env-bestand gebruiken om al onze omgevingsvariabelen te beheren.
Het .env-bestand is een verborgen bestand waarmee we onze omgevingsvariabelen kunnen aanpassen met de syntaxis ENV VARIABLE = VALUE.
Deze variabelen worden geladen met behulp van de dotenv module die we al hebben geïnstalleerd.
Het .env-bestand kan in verschillende stadia van de omgeving worden gedefinieerd (ontwikkel- / stage- / productie-omgevingen).

Maak het .env-bestand aan, kopieer de volgende regels en werk het bestand bij met uw MySQL db_naam, db_gebruikersnaam en wachtwoord:

# DB ConfigurationsHOST=localhostDB_USER=db_usernameDB_PASS=db_passwordDB_DATABASE=db_name# local runtime configsPORT=3000SECRET_JWT=supersecret
Enter fullscreen mode Exit fullscreen mode

Maak het bestand nodemon.json aan:

Nodemon is een hulpprogramma dat helpt bij het ontwikkelen van toepassingen op basis van node.js door de node-toepassing automatisch opnieuw te starten wanneer bestandswijzigingen worden gedetecteerd in de doelmap.
De nodemon is een vervangende wrapper voor node. In plaats van het commando node te gebruiken, moeten we het commando nodemon op de opdrachtregel gebruiken om ons script uit te voeren.
We kunnen eenvoudig configuratieschakelaars toevoegen terwijl we nodemon op de opdrachtregel uitvoeren, zoals:

nodemon --watch src
Enter fullscreen mode Exit fullscreen mode

We kunnen ook een bestand gebruiken (nodemon.json) om alle schakelaars op te geven.
Als we meerdere bestanden in een directory willen bekijken, kunnen we de directory toevoegen aan de “watch” array.
Als we willen zoeken naar een bepaalde extensie (zoals een ts-bestand) kunnen we de “ext” eigenschap gebruiken.
Als we sommige bestanden willen negeren, kunnen we ze definiëren in de “ignore”‘ array, enzovoort…
Ik gebruik dit bestand meestal als ik een server maak met NodeJS op basis van typescript, maar ik denk dat het makkelijker is om meer plaatsen te hebben om onze app-configuraties op te nemen.
Dit bestand is optioneel.

Maak het bestand nodemon.json en voeg dit toe aan het bestand:

{ "watch": , "ext": ".js", "ignore": }
Enter fullscreen mode Exit fullscreen mode

Maak de map src aan:

mkdir src && cd src
Enter fullscreen mode Exit fullscreen mode

Maak in de src-map submappen aan: controllers, models, routes, middleware, db, en utils:

mkdir controllers models routes middleware db utils
Ga naar fullscreen-modus Sluit fullscreen-modus af

Stel Express-server in:

In de src-map maken we het bestand server.js aan en kopiëren we de volgende regels:

In dit bestand importeren we express om de rest-API’s te bouwen en gebruiken we express.json() om inkomende verzoeken met JSON payloads te parseren.

We importeren ook de dotenv-module om het .env config bestand om het poortnummer te krijgen om de server te draaien.

We importeren ook userRouter.

Daarna hebben we een middleware die 404 fouten afhandelt → als iemand naar een eindpunt zoekt dat niet bestaat, krijgt hij deze foutmelding: ‘Eindpunt niet gevonden’ met de 404 status code. Daarna gebruiken we error middleware die foutgegevens van de vorige routes krijgt. als next(err) wordt aangeroepen, kunt u de 404 middleware als voorbeeld zien.
We luisteren naar de poort uit het.env bestand en drukken het af op de console dat de server draait.

Mysql-database en gebruikerstabel aanmaken:

In de db-directory maken we het bestand create-user-db.sql en kopiëren-plakken we deze regels:

In dit script laten we eerst de database vallen als deze bestaat, zodat deze snel kan worden gereset in geval van een fout (u kunt deze regel desgewenst becommentariëren), vervolgens maken we de database aan als deze niet bestaat. We stellen het in als onze actieve database en maken een “gebruiker” tabel met alle kolommen (id, gebruikersnaam, enzovoort), opnieuw om een gemakkelijke reset mogelijk te maken indien nodig. U kunt deze query in uw databaseclient uitvoeren als u er een gebruikt.

Als u wsl gebruikt, kunt u in de db-directory het volgende uitvoeren:

mysql -u -p < create-user-db.sql
Enter fullscreen mode Exit fullscreen mode

Configureer en maak verbinding met de MySQL-database:

Maak een extra bestand aan in de db-directory genaamd db-connection.js, en copy-paste dit:

In dit bestand importeren we eerst de dotenv-module en gebruiken deze om databaseconfiguratie-info zoals db-host, db-gebruiker uit het.env-bestand te lezen.

We controleren de verbinding voor het geval er een probleem is met de database en geven vervolgens de verbinding weer vrij.

We hebben een query-methode die een belofte van het resultaat van de query retourneert.

We gebruiken een try-catch blok om veelvoorkomende MySQL fouten op te vangen en de juiste HTTP-statuscodes en berichten te retourneren.

Aan het einde van het bestand maken we een instantie van de DBConnection klasse en gebruiken we de query-methode, en in het model.js (dat we in de volgende stap zullen zien), zullen we de query-methode opnieuw gebruiken.

Maak een Error Handler:

Naar aanleiding hiervan gaan we onze foutafhandeling maken.

Daartoe maken we eerst het bestand HttpException.utils.js aan onder de map utils, en kopiëren-plakken we het volgende:

De klasse HttpException erft de klasse Error.
De constructor krijgt de status, het bericht en de gegevens. We geven de berichtvariabele door aan de bovenliggende constructor met behulp van super(bericht), en initialiseren vervolgens de instantievariabelen status, bericht en gegevens.

Daarna maken we een middleware-foutafhandeling in de middleware-directory.
We maken een bestand error. middleware.js bestand en copy-pasten het volgende:

We kunnen onderaan het bestand zien hoe het object eruit komt te zien.

De middleware krijgt req, res, en next callback, maar het krijgt ook een extra argument, error (door next(error) te gebruiken voordat we bij deze middleware komen).

We gebruiken destructuring om de variabelen uit het error-object te halen en zetten de status op 500 als dat nog niet eerder is ingesteld.

Daarna, of de status nu 500 is, zorgen we ervoor dat we het bericht veranderen, zodat de gebruiker een generieke interne serverfoutmelding krijgt zonder de exacte aard van de fout te onthullen.

Daarna maken we een foutobject met de eigenschappen type, status en bericht (gegevens zijn optioneel).

Maken utils (helpers) bestanden:

In de directory utils maken we nog twee bestanden, common.utils.js, en userRoles.utils.js.

common.utils.js:

Deze functie helpt bij het instellen van meerdere velden voor voorbereide query’s met sleutel-waardeparen.
ColumnSet de array van key =? paren,
De waarden moeten daarom in dezelfde volgorde staan als de columnSet array.

userRoles.utils.js:

module.exports = { Admin: 'Admin', SuperUser: 'SuperUser'}
Invoeren fullscreen-modus Verlaten fullscreen-modus

Async-functie maken:

Maak in de middleware-map een ander bestand aan met de naam awaitHandlerFactory.middleware.js en copy-paste dit:

In het algemeen weten we dat middleware alleen een asynchrone methode is die de req, de res en de volgende argumenten krijgt, dus als we willen dat deze middleware een extra argument krijgt, doen we het op deze manier (we zullen dit in de volgende stap ook in de auth middleware gebruiken).

Deze functie krijgt een callback, voert het middleware script uit, en zal proberen deze callback te triggeren in het try blok.
Als hier iets fout gaat, zal het de fout opvangen en zullen we de next(err) gebruiken (die het zal overbrengen naar de volgende middleware => error.middleware.js).

Maak Authenticatie Middleware:

Een andere middleware die we nodig hebben, is de auth-middleware die we zullen gebruiken om gebruikersmachtigingen te controleren via de JWT-module.

Gelijk aan de middleware awaitHandlerFactory.middleware.js, hebben we hier een middleware die een extra argument vereist (dat optioneel is) => rollen.

Ik heb try-catch gebruikt om de foutstatus in het vanggebied aan te passen naar 401 (als het token is verlopen, bijvoorbeeld).

In eerste instantie zoeken we naar req.headers.authorization – als het niet is gedefinieerd in de header of als de header niet begint met “Bearer “, krijgt de gebruiker een 401-antwoord. Als het begint met “Bearer “, krijgen we het token en gebruiken we de geheime sleutel uit het.env bestand om het te ontcijferen.

We verifiëren het token door gebruik te maken van de jwt.verify synchrone functie, die het token, en de geheime sleutel, als argumenten krijgt en de gedecodeerde payload retourneert, of de handtekening geldig is en of de optionele expiratie, publiek of emittent velden geldig zijn. Anders geeft het een foutmelding.

Nu kunnen we de gebruiker met dit token vinden door de user id op te zoeken.
Als de gebruiker niet meer bestaat, krijgen ze een exception van 401 zonder enige informatie.
Als de gebruiker bestaat, zullen we controleren of de huidige gebruiker is de eigenaar die het zoeken naar zijn routes of dat de gebruiker heeft de rol om deze route te openen.
We slaan de huidige gebruiker voor het geval hij wil zijn gegevens op de volgende middleware (zoals de “whoami” route) te krijgen.

Validatie van gegevens met behulp van Express Validator module:

In de middleware directory, zullen we een extra bestand maken dat we zullen gebruiken om de req.body eigenschappen te verifiëren.

Maak een submap in de middleware directory genaamd validators en maak een bestand in deze directory, userValidator.middleware.js. Copy-paste dit:

In dit bestand heb ik de express-validator module gebruikt, die heel gemakkelijk te gebruiken is wanneer we een aantal eigenschappen moeten controleren, moeten controleren of de eigenschap bestaat, of aangepaste controles moeten maken met een aangepast bericht aan de gebruiker als een waarde van een eigenschap niet geldig is.

Nu kunnen we beginnen met het maken van onze route-, controller- en modelbestanden.

Routes definiëren:

Maak het bestand user.route.js aan in de map routes en kopieer-plak dit:

Het bovenstaande voorbeeld laat zien hoe u routes definieert. Laten we proberen het in stukjes op te splitsen:

  • U kunt een router maken met express.Router().Elke route kan een middleware-functie laden die de bedrijfslogica afhandelt.UserController, bijvoorbeeld, draagt alle belangrijke middlewares.Om de router te gebruiken, moet de router worden geëxporteerd als een module en worden gebruikt in de belangrijkste app met behulp van app.use(router_module).
  • We hebben auth middleware gebruikt voor gebruikersauthenticatie en -autorisatie, voor het controleren van gebruikerstoken of gebruikersrol voor de route.In ons voorbeeld gebruiken sommige van de routes de auth middleware voor het controleren van de authenticatie en autorisatie van de gebruiker.Deze middleware wordt getriggerd vóór de belangrijkste middleware (degene die de business logica bevat).De volgende callback moet worden aangeroepen om de controle door te geven aan de volgende middleware methode.Anders zal het verzoek blijven hangen.
  • awaitHandlerFactory (try-catch middleware) wordt gebruikt om alle asynchrone middleware te wikkelen. Op deze manier, als een van de middleware gooit een fout, zal awaitHandlerFactory vangen die fout.U kunt zien dat al onze middleware functies zijn verpakt met awaitHandlerFactory middleware, die ons helpt om onze fouten af te handelen door het gebruik van try-catch op een plaats.
  • Daarnaast hebben we het createUserSchema, updateUserSchema en validateLogin schema om de body te valideren voordat we de volgende middleware starten.

De syntax van de HTTP-methode is:

Maak de Controller:

Maak het bestand user.controller.js aan in de map controllers en kopieer-plak dit:

Zoals hierboven vermeld, bevat het controllerbestand onze bedrijfslogica voor het afhandelen van onze routes.
In ons voorbeeld gebruiken sommige methoden de UserModel-klasse om de database te ondervragen voor het verkrijgen van de gegevens.
Om de gegevens in elke middleware terug te sturen, gebruiken we res.send(result) om een reactie naar de client te sturen.

Maak het model:

En maak het bestand user.model.js in de map models en copy-paste dit:

Deze klasse maakt de verbinding tussen de controller en de database.
Hier bevinden zich alle methoden die de argumenten van de controller krijgen, een query maken, verklaringen voorbereiden, verbinding maken met de database met behulp van de query-methode uit de klasse db-connection, het verzoek met de array met voorbereide verklaringen verzenden en het resultaat terugkrijgen.
Elke functie retourneert het resultaat naar de controller.

.gitIgnore:

In het geval dat je besluit dit project aan je GitHub toe te voegen, vergeet dan niet om een .gitignore bestand aan te maken en dit te copy-pasten:

node_modules.env
Enter fullscreen mode Exit fullscreen mode

Dit bestand vertelt Git alleen welke bestanden het moet negeren.
Je zou de node_modules directory moeten vermijden omdat het zwaar is en niet nodig voor het archief.
Wanneer iemand deze repository cloned, zal hij het commando “npm I” gebruiken om alle afhankelijkheden te installeren.
Het .env-bestand is om je privé-configuraties te verbergen voor andere ontwikkelaars die je code gebruiken.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.