How To Build Rest API With NodeJS, Express, and MySQL

Mit Kenntnissen in JavaScript und MySQL können wir unsere NodeJS-API mit Express erstellen.

Ich habe einige Nachforschungen angestellt und versucht, eine API von Grund auf zu entwickeln.
Ich mag es, die Dinge zu vereinfachen und versuche, Code-Duplizierung zu vermeiden.

Dieser Leitfaden wird Ihnen zeigen, wie Sie eine API von Grund auf aufbauen:
Sie werden lernen, wie man Routen erstellt,
wie man mysql2 verwendet, wie man die Datenbank konfiguriert und sich mit ihr verbindet, und wie man Abfragen mit vorbereiteten Anweisungen ausführt.
Sie werden lernen, wie man eine Middleware erstellt, die neben req, res und next callback ein zusätzliches Argument erhält.
Sie werden lernen, wie man die Daten des Request-Objekts mit dem Express Validator-Modul überprüft.
Sie werden lernen, wie Sie das JWT-Modul verwenden, um ein Token für den Benutzer zu erstellen, das Token zu verifizieren und das im Token gespeicherte Objekt abzurufen.
Zusätzlich werden Sie lernen, wie Sie Benutzern die Berechtigung zum Zugriff auf eine bestimmte Route basierend auf ihren Benutzerrollen erteilen.

Technologien und Pakete:

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

Installation von MySQL:

Ich verwende WSL, und Sie können diese Anleitung verwenden, um zu sehen, wie man MySQL in WSL installiert.
Sie müssen sicherstellen, dass MySQL mit diesem Befehl läuft:

sudo service mysql status
Vollbildmodus eingeben Vollbildmodus beenden

Wenn es nicht läuft, verwenden Sie einfach:

sudo service mysql start
Vollbildmodus aufrufen Vollbildmodus beenden

Anwendungsübersicht:

Wir werden eine Rest-API für CRUD-Operationen erstellen: Erstellen, Lesen, Aktualisieren und Löschen von Benutzern.

Erstellen Sie den Projektordner und installieren Sie alle Abhängigkeiten:

mkdir mysql-node-express && cd mysql-node-expressnpm init -ynpm i express express-validator mysql2 cors dotenv jsonwebtoken -Snpm i nodemon -D
Vollbildmodus aufrufen Vollbildmodus beenden

Gehen Sie zur Datei package.json und ändern Sie den Wert “main” in “src/server.js” und fügen Sie diese Skripte zum Skripte-Objekt hinzu:

"start": "node src/server.js","dev": "nodemon"
Vollbildmodus betreten Vollbildmodus verlassen

package.json sollte wie folgt aussehen:

.env-Datei erstellen:

Wir werden die .env-Datei verwenden, um alle unsere Umgebungsvariablen zu verwalten.
Die .env-Datei ist eine versteckte Datei, mit der wir unsere Umgebungsvariablen mit der Syntax ENV VARIABLE = VALUE anpassen können.
Diese Variablen werden mit dem Modul dotenv geladen, das wir bereits installiert haben.
Die .env-Datei kann in verschiedenen Stadien der Umgebung definiert werden (Entwicklungs-/Stadium-/Produktionsumgebungen).

Erstellen Sie die .env-Datei, kopieren Sie die folgenden Zeilen und aktualisieren Sie die Datei mit Ihrem MySQL db_name, db_username und Passwort:

# DB ConfigurationsHOST=localhostDB_USER=db_usernameDB_PASS=db_passwordDB_DATABASE=db_name# local runtime configsPORT=3000SECRET_JWT=supersecret
Vollbildmodus betreten Vollbildmodus verlassen

Erstellen Sie die Datei nodemon.json:

Nodemon ist ein Tool, das bei der Entwicklung von Anwendungen auf Basis von node.js hilft, indem es die node-Anwendung automatisch neu startet, wenn Dateiänderungen im Zielverzeichnis erkannt werden.
Der Nodemon ist ein Ersatz-Wrapper für node. Anstatt den Befehl node zu verwenden, sollten wir den Befehl nodemon auf der Befehlszeile verwenden, um unser Skript auszuführen.
Wir können ganz einfach Konfigurationsschalter hinzufügen, während wir nodemon auf der Befehlszeile ausführen, wie zum Beispiel:

nodemon --watch src
Vollbildmodus eingeben Vollbildmodus beenden

Wir können auch eine Datei (nodemon.json) verwenden, um alle Schalter zu spezifizieren.
Wenn wir mehrere Dateien in einem Verzeichnis überwachen wollen, können wir das Verzeichnis im Array “watch” hinzufügen.
Wenn wir nach einer bestimmten Erweiterung (z.B. einer ts-Datei) suchen wollen, können wir die “ext”-Eigenschaft verwenden.
Wenn wir einige Dateien ignorieren wollen, können wir sie im “ignore”-Array definieren, und so weiter…
Ich verwende diese Datei meistens, wenn ich einen Server mit NodeJS auf der Basis von Typescript erstelle, aber ich denke, es ist einfacher, mehr Orte zu haben, um unsere App-Konfigurationen aufzunehmen.
Diese Datei ist optional.

Erstellen Sie die Datei nodemon.json und fügen Sie Folgendes hinzu:

{ "watch": , "ext": ".js", "ignore": }
Vollbildmodus eingeben Vollbildmodus beenden

Erstellen Sie den Ordner src:

mkdir src && cd src
Vollbildmodus betreten Vollbildmodus verlassen

Im src-Ordner Unterordner erstellen: controllers, models, routes, middleware, db, and utils:

mkdir controllers models routes middleware db utils
Vollbildmodus aufrufen Vollbildmodus beenden

Express-Server einrichten:

Erstellen Sie im src-Verzeichnis die Datei server.js und kopieren Sie diese Zeilen:

In dieser Datei importieren wir express, um die Rest-APIs zu erstellen, und verwenden express.json(), um eingehende Anfragen mit JSON-Nutzdaten zu parsen.

Wir importieren auch das dotenv-Modul, um die .env-Konfigurationsdatei zu lesen, um die Portnummer für die Ausführung des Servers zu erhalten.

Wir importieren auch userRouter.

Danach haben wir eine Middleware, die 404-Fehler behandelt → wenn jemand nach einem Endpunkt sucht, der nicht existiert, erhält er diesen Fehler: ‘Endpoint Not Found’ mit dem Statuscode 404. Danach verwenden wir die Fehler-Middleware, die Fehlerdaten von den vorherigen Routen erhält. Wenn next(err) aufgerufen wird, können Sie die 404-Middleware als Beispiel sehen.
Wir hören auf den Port aus der.env-Datei und geben auf der Konsole aus, dass der Server läuft.

Erstellen Sie die MySQL-Datenbank und die Benutzertabelle:

Im db-Verzeichnis erstellen wir die Datei create-user-db.sql und fügen diese Zeilen ein:

In diesem Skript löschen wir zuerst die Datenbank, wenn sie existiert, damit sie im Falle eines Fehlers schnell zurückgesetzt werden kann (Sie können diese Zeile auskommentieren, wenn Sie möchten), dann erstellen wir die Datenbank, wenn sie nicht existiert. Wir legen sie als unsere aktive Datenbank fest und erstellen eine Tabelle “user” mit allen Spalten (id, Benutzername usw.), damit wir sie bei Bedarf schnell zurücksetzen können. Sie können diese Abfrage in Ihrem Datenbank-Client ausführen, wenn Sie einen verwenden.

Wenn Sie wsl verwenden, können Sie im db-Verzeichnis Folgendes ausführen:

mysql -u -p < create-user-db.sql
Vollbildmodus aufrufen Vollbildmodus beenden

Konfigurieren und Verbinden mit der MySQL-Datenbank:

Erstellen Sie eine zusätzliche Datei im db-Verzeichnis mit dem Namen db-connection.js und fügen Sie diese ein:

In dieser Datei importieren wir zunächst das dotenv-Modul und lesen damit Datenbankkonfigurationsinformationen wie db host, db user aus der.env-Datei.

Wir überprüfen die Verbindung, falls es ein Problem mit der Datenbank gibt, und geben die Verbindung dann wieder frei.

Wir haben eine Abfragemethode, die ein Versprechen des Ergebnisses der Abfrage zurückgibt.

Wir verwenden einen try-catch-Block, um häufige MySQL-Fehler zu erfassen und entsprechende HTTP-Statuscodes und Meldungen zurückzugeben.

Am Ende der Datei erstellen wir eine Instanz der DBConnection-Klasse und verwenden die Abfragemethode, und in der model.js (die wir im nächsten Schritt sehen werden) werden wir die Abfragemethode erneut verwenden.

Erstellen Sie einen Error Handler:

Als Nächstes erstellen wir unseren Error Handler.

Zu diesem Zweck erstellen wir zunächst die Datei HttpException.utils.js im Verzeichnis utils und fügen Folgendes per Copy-Paste ein:

Die Klasse HttpException erbt die Klasse Error.
Der Konstruktor erhält den Status, die Nachricht und die Daten. Wir übergeben die Meldungsvariable mit super(message) an den übergeordneten Konstruktor und initialisieren dann die Instanzvariablen status, message und data.

Danach erstellen wir einen Middleware-Fehlerhandler im Middleware-Verzeichnis.
Wir erstellen eine error. middleware.js-Datei und fügen Folgendes ein:

Unten in der Datei sehen wir, wie das Objekt aussehen wird.

Die Middleware erhält req, res und next callback, aber sie erhält auch ein zusätzliches Argument, error (indem wir next(error) verwenden, bevor wir zu dieser Middleware kommen).

Wir verwenden Destrukturierung, um die Variablen aus dem Fehlerobjekt zu erhalten und den Status auf 500 zu setzen, wenn er nicht vorher konfiguriert wurde.

Danach, ob der Status 500 ist, stellen wir sicher, dass wir die Nachricht ändern, so dass der Benutzer eine generische interne Server-Fehlermeldung erhält, ohne die genaue Art des Fehlers zu enthüllen.

Danach erstellen wir ein Fehlerobjekt mit den Eigenschaften type, status und message (data ist optional).

Erstellen Sie utils (helpers) Dateien:

Im Verzeichnis utils erstellen wir zwei weitere Dateien, common.utils.js und userRoles.utils.js.

common.utils.js:

Diese Funktion hilft, mehrere Felder für vorbereitete Abfragen mit Schlüssel-Wert-Paaren zu setzen.
ColumnSet das Array von Schlüssel =? Paaren,
Die Werte sollten daher in der gleichen Reihenfolge wie das columnSet Array sein.

userRoles.utils.js:

module.exports = { Admin: 'Admin', SuperUser: 'SuperUser'}
Vollbildmodus betreten Vollbildmodus verlassen

Async Funktion erstellen:

Erstelle eine weitere Datei mit dem Namen awaitHandlerFactory.middleware.js im Middleware-Verzeichnis und füge Folgendes per Copy-Paste ein:

Im Allgemeinen wissen wir, dass Middleware nur eine asynchrone Methode ist, die die Argumente req, res und next erhält, wenn wir also wollen, dass diese Middleware ein zusätzliches Argument erhält, machen wir es so (wir werden dies auch in der Auth-Middleware im nächsten Schritt verwenden).

Diese Funktion erhält einen Callback, führt das Middleware-Skript aus und versucht, diesen Callback im Try-Block auszulösen.
Wenn hier etwas schief geht, fängt sie den Fehler ab und wir verwenden next(err) (was ihn an die nächste Middleware => error.middleware.js weiterleitet).

Authentifizierungs-Middleware erstellen:

Eine weitere Middleware, die wir benötigen, ist die auth-Middleware, die wir verwenden werden, um die Benutzerberechtigungen über das JWT-Modul zu überprüfen.

Ähnlich der awaitHandlerFactory.middleware.js-Middleware haben wir hier eine Middleware, die ein zusätzliches Argument benötigt (das optional ist) => Rollen.

Ich habe try-catch verwendet, um den Fehlerstatus im catch-Bereich auf 401 einzustellen (wenn z.B. das Token abgelaufen ist).

Zunächst suchen wir nach req.headers.authorization – wenn es nicht im Header definiert ist oder wenn der Header nicht mit “Bearer ” beginnt, erhält der Benutzer eine 401-Antwort. Wenn er mit “Bearer” beginnt, erhalten wir das Token und verwenden den geheimen Schlüssel aus der Datei.env, um es zu entschlüsseln.

Wir überprüfen das Token mit der synchronen Funktion jwt.verify, die das Token und den geheimen Schlüssel als Argumente erhält und die entschlüsselte Nutzlast zurückgibt, ob die Signatur gültig ist und die optionalen Felder für Ablauf, Publikum oder Aussteller gültig sind. Andernfalls wird ein Fehler ausgegeben.

Jetzt können wir den Benutzer mit diesem Token finden, indem wir die Benutzerkennung durchsuchen.
Wenn der Benutzer nicht mehr existiert, erhält er eine Ausnahme 401 ohne jegliche Information.
Wenn der Benutzer existiert, prüfen wir, ob der aktuelle Benutzer der Besitzer ist, der nach seinen Routen sucht, oder ob der Benutzer die Rolle hat, auf diese Route zuzugreifen.
Wir speichern den aktuellen Benutzer für den Fall, dass er seine Daten auf der nächsten Middleware (wie die “whoami”-Route) abrufen möchte.

Datenvalidierung mit dem Express Validator-Modul:

Im Middleware-Verzeichnis werden wir eine zusätzliche Datei erstellen, die wir zur Überprüfung der req.body-Eigenschaften verwenden werden.

Erstellen Sie einen Unterordner im Middleware-Verzeichnis mit dem Namen validators und erstellen Sie in diesem Verzeichnis eine Datei, userValidator.middleware.js. Kopieren Sie diese Datei:

In dieser Datei habe ich das Modul express-validator verwendet, das sehr einfach zu verwenden ist, wenn wir einige Eigenschaften prüfen müssen, prüfen, ob die Eigenschaft vorhanden ist, oder benutzerdefinierte Prüfungen mit einer benutzerdefinierten Nachricht an den Benutzer erstellen, wenn ein Eigenschaftswert nicht gültig ist.

Jetzt können wir mit der Erstellung unserer Routen-, Controller- und Modelldateien beginnen.

Definieren Sie Routen:

Erstellen Sie die Datei user.route.js im Verzeichnis routes und fügen Sie Folgendes ein:

Das obige Beispiel zeigt, wie man Routen definiert. Lassen Sie uns versuchen, es in Stücke zu zerlegen:

  • Sie können einen Router mit express.Router() erstellen.Jede Route kann eine Middleware-Funktion laden, die die Geschäftslogik handhabt.UserController, zum Beispiel trägt alle wichtigen Middlewares.Um den Router zu verwenden, sollte der Router als Modul exportiert und in der Hauptanwendung mit app.use(router_module) verwendet werden.
  • Wir haben auth-Middleware für die Benutzerauthentifizierung und -autorisierung verwendet, um den Benutzer-Token oder die Benutzerrolle für die Route zu überprüfen.In unserem Beispiel verwenden einige der Routen die auth-Middleware zur Überprüfung der Benutzerauthentifizierung und -autorisierung.
  • Diese Middleware wird vor der Haupt-Middleware (derjenigen, die die Geschäftslogik enthält) ausgelöst.
  • Der nächste Callback muss aufgerufen werden, um die Kontrolle an die nächste Middleware-Methode zu übergeben.
  • awaitHandlerFactory (try-catch-Middleware) wird verwendet, um alle asynchronen Middlewares zu umhüllen. Sie können sehen, dass alle unsere Middleware-Funktionen mit awaitHandlerFactory-Middleware umhüllt sind, was uns hilft, unsere Fehler durch die Verwendung von try-catch an einer Stelle zu behandeln.
  • Zusätzlich haben wir die Schemata createUserSchema, updateUserSchema und validateLogin, um den Body zu validieren, bevor wir die nächste Middleware starten.

Die Syntax der HTTP-Methode lautet:

Erstellen Sie den Controller:

Erstellen Sie die Datei user.controller.js im Verzeichnis controllers und fügen Sie Folgendes ein:

Wie bereits erwähnt, enthält die Controller-Datei unsere Geschäftslogik für die Handhabung unserer Routen.
In unserem Beispiel verwenden einige Methoden die UserModel-Klasse, um die Datenbank abzufragen, um die Daten zu erhalten.
Um die Daten in jeder Middleware zurückzugeben, verwenden wir res.send(result), um eine Antwort an den Client zu senden.

Erstellen Sie das Modell:

Und erstellen Sie die Datei user.model.js im Verzeichnis models und fügen Sie Folgendes ein:

Diese Klasse stellt die Verbindung zwischen dem Controller und der Datenbank her.
Hier haben wir alle Methoden, die die Argumente vom Controller bekommen, eine Abfrage machen, Anweisungen vorbereiten, sich mit der Datenbank verbinden, indem sie die Abfrage-Methode von der db-connection Klasse verwenden, die Anfrage mit dem Array der vorbereiteten Anweisungen senden und das Ergebnis zurückbekommen.
Jede Funktion gibt das Ergebnis an den Controller zurück.

.gitIgnore:

Für den Fall, dass du dich entscheidest, dieses Projekt zu deinem GitHub hinzuzufügen, vergiss nicht, eine .gitignore-Datei zu erstellen und diese per Copy-Paste einzufügen:

node_modules.env
Enter fullscreen mode Exit fullscreen mode

Diese Datei sagt Git nur, welche Dateien es ignorieren soll.
Das Verzeichnis node_modules sollte vermieden werden, da es schwer ist und für das Repository nicht benötigt wird.
Wenn jemand dieses Repository klont, wird er den Befehl “npm I” verwenden, um alle Abhängigkeiten zu installieren.
Das Ignorieren der .env-Datei dient dazu, Ihre privaten Konfigurationen vor anderen Entwicklern zu verstecken, die Ihren Code verwenden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.