Rest API:n rakentaminen NodeJS:llä, Expressillä ja MySQL:llä

Javaskriptin ja MySQL:n tuntemuksella voimme rakentaa NodeJS-API:n Expressin avulla.

Työskentelin jonkin verran tutkimustyössä ja yritin kehittää API:n tyhjästä.
Tykkään yksinkertaistaa asioita ja yritän välttää koodin päällekkäisyyksiä.

Tässä oppaassa näytetään, miten API rakennetaan tyhjästä:
Oppiessasi opit luomaan reittejä,
käyttämään mysql2:ta, konfiguroimaan tietokannan ja muodostamaan yhteyden tietokantaan sekä suorittamaan kyselyjä prepared statementeillä.
Miten luodaan väliohjelmisto, joka voi saada lisäargumentin req:n, res:n ja seuraavan callbackin lisäksi.
Oppiessasi opit tarkistamaan pyynnön objektin tiedot Express Validator -moduulin avulla.
Opit, miten JWT-moduulin avulla luodaan käyttäjälle token, tarkistetaan token ja haetaan tokeniin tallennettu objekti.
Lisäksi opit, miten käyttäjille voidaan antaa oikeus käyttää tiettyä reittiä heidän käyttäjäroolinsa perusteella.

Teknologiat ja paketit:

  • NodeJS
  • Express
  • mysql2
  • bcryptjs
  • jsonwebtoken
  • express-validator
  • dotenv
  • cors
  • MySQL:n asentaminen:

    Käytän WSL:ää, ja voit käyttää tätä ohjetta nähdäksesi, miten MySQL asennetaan WSL:ään.
    Varmista, että MySQL on käynnissä tällä komennolla:

    sudo service mysql status
    Enter fullscreen mode Exit fullscreen mode

    Jos se ei ole käynnissä, käytä:

    sudo service mysql start
    Enter fullscreen mode Exit fullscreen mode

    Application overview:

    Rakennetaan rest API CRUD-operaatioita varten: luodaan, luetaan, päivitetään ja poistetaan käyttäjiä.

    Luodaan projektikansio ja asennetaan kaikki riippuvuudet:

    mkdir mysql-node-express && cd mysql-node-expressnpm init -ynpm i express express-validator mysql2 cors dotenv jsonwebtoken -Snpm i nodemon -D
    Siirry kokoruututilaan Poistu kokoruututilasta

    Mene package.json-tiedostoon ja vaihda “main”-arvoksi “src/server.js” ja lisää nämä skriptit scripts-objektiin:

    "start": "node src/server.js","dev": "nodemon"
    Enter fullscreen mode Exit fullscreen mode

    package.json-tiedoston pitäisi näyttää tältä:

    Luo .env-tiedosto:

    Käytämme .env-tiedostoa kaikkien ympäristömuuttujiemme hallintaan.
    .env-tiedosto on piilotettu tiedosto, jonka avulla voimme muokata ympäristömuuttujiamme käyttämällä ENV VARIABLE = VALUE -syntaksia.
    Nämä muuttujat ladataan jo asentamamme dotenv-moduulin avulla.
    .env-tiedosto voidaan määritellä ympäristön eri vaiheissa (develop / stage / tuotantoympäristöt).

    Luo .env-tiedosto, kopioi seuraavat rivit ja päivitä tiedostoon MySQL:n db_nimi, db_käyttäjätunnus ja salasana:

    # DB ConfigurationsHOST=localhostDB_USER=db_usernameDB_PASS=db_passwordDB_DATABASE=db_name# local runtime configsPORT=3000SECRET_JWT=supersecret
    Siirry täytenäyttötilaan Poistu täytenäyttötilasta

    Luo tiedoston nodemon.json:

    Nodemon on työkalu, joka auttaa node.js:ään perustuvien sovellusten kehittämisessä käynnistämällä node-sovelluksen automaattisesti uudelleen, kun kohdehakemistossa havaitaan tiedostomuutoksia.
    Nodemon on korvaava kääre nodelle. Sen sijaan, että käyttäisimme node-komentoa, meidän tulisi käyttää komentorivillä nodemon-komentoa komentorivillä skriptimme suorittamiseen.
    Voitamme helposti lisätä konfiguraatiokytkimiä ajaessamme nodemon-komentoa komentorivillä, kuten:

    nodemon --watch src
    Enter fullscreen mode Exit fullscreen mode

    Voimmekin käyttää tiedostoa (nodemon.json) määrittääksemme kaikki kytkimet.
    Jos haluamme katsella useita tiedostoja hakemistossa, voimme lisätä hakemiston “watch”-matriisiin.
    Jos haluamme etsiä tiettyä laajennusta (kuten ts-tiedostoa), voimme käyttää “ext”-ominaisuutta.
    Jos haluamme jättää huomioimatta joitain tiedostoja, voimme määritellä ne “ignore”‘ -matriisiin, ja niin edelleen…
    Käytän tätä tiedostoa enimmäkseen luodessani palvelinta NodeJS:llä, joka perustuu typescriptiin, mutta mielestäni on helpompaa, että on olemassa useampia paikkoja, joihin voimme sisällyttää sovelluksemme konfiguraatiot.
    Tämä tiedosto ei ole pakollinen.

    Luo nodemon.json-tiedosto ja lisää tiedostoon tämä:

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

    Luo src-kansio:

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

    Luo src-kansioon alikansiot: controllers, models, routes, middleware, db ja utils:

    mkdir controllers models routes middleware db utils
    Enter fullscreen mode Exit fullscreen mode

    Setup Express server:

    Luo src-hakemistoon tiedosto server.js ja kopioi nämä rivit:

    Tässä tiedostossa tuomme expressin rakentaaksemme loput API:t ja käytämme express.json():ia jäsentämään saapuvat pyynnöt JSON-hyötykuormilla.

    Tuomme myös dotenv-moduulin lukemaan .env config-tiedostoa saadaksemme porttinumeron palvelimen suorittamista varten.

    Tuomme myös userRouterin.

    Sen jälkeen meillä on väliohjelmisto, joka käsittelee 404-virheitä → jos joku etsii päätepistettä, jota ei ole olemassa, hän saa tämän virheilmoituksen: “Päätepistettä ei löydy” tilakoodilla 404. Tämän jälkeen käytämme error-väliohjelmistoa, joka saa virhetiedot edellisistä reiteistä. jos next(err) kutsutaan, näet 404-väliohjelmiston esimerkkinä.
    Kuuntelemme porttia.env-tiedostosta ja tulostamme konsoliin, että palvelin on käynnissä.

    Luodaan MySQL-tietokanta ja käyttäjätaulu:

    Luotaan db-hakemistoon create-user-db.sql-tiedosto ja copy-pastetaan nämä rivit:

    Tässä skriptissä pudotetaan ensin tietokanta, jos se on olemassa, jotta se voidaan palauttaa nopeasti virheen sattuessa (voit halutessasi kommentoida tuon rivin), sitten luodaan tietokanta, jos sitä ei ole olemassa. Asetamme sen aktiiviseksi tietokannaksi ja luomme “user”-taulukon, jossa on kaikki sarakkeet (id, käyttäjätunnus ja niin edelleen), mikä taas mahdollistaa kätevän palauttamisen tarvittaessa. Voit suorittaa tämän kyselyn tietokanta-asiakasohjelmassasi, jos käytät sellaista.

    Jos käytät wsl:ää, db-hakemistossa voit suorittaa:

    mysql -u -p < create-user-db.sql
    Siirry kokoruututilaan Poistu kokoruututilasta

    MySQL-tietokannan konfigurointi ja yhteys siihen:

    Luo db-hakemistoon ylimääräinen tiedosto nimeltään db-connection.js ja copy-paste tämä:

    Tässä tiedostossa tuomme ensin dotenv-moduulin ja käytämme sitä lukemaan tietokannan konfigurointitietoja, kuten db-isäntä, db-käyttäjä.env-tiedostosta.

    Tarkistamme yhteyden siltä varalta, että tietokannassa on ongelmia ja vapautamme yhteyden sitten.

    Meillä on query-metodi, joka palauttaa lupauksen kyselyn tuloksesta.

    Käytämme try-catch-lohkoa tavallisten MySQL-virheiden kaappaamiseen ja sopivien HTTP-tilakoodien ja -viestien palauttamiseen.

    Tiedoston lopussa luomme instanssin DBConnection-luokasta ja käytämme query-metodia, ja model.js:ssä (jonka näemme seuraavassa vaiheessa) käytämme taas query-metodia.

    Luo virheenkäsittelijän:

    Seuraavaksi luomme virheenkäsittelijän.

    Tehdäksemme niin, luomme ensin tiedoston HttpException.utils.js utils-hakemiston alle ja copy-paste-menetelmällä seuraavat:

    HttpException-luokka perii Error-luokan.
    Konstruktori saa statuksen, viestin ja datan. Välitämme viestimuuttujan vanhemmalle konstruktorille super(message):lla, minkä jälkeen alustamme status, message ja data -instanssimuuttujat.

    Sen jälkeen luomme middleware-hakemistoon middleware-virheenkäsittelijän.
    Luomme error. middleware.js-tiedoston ja copy-pastetaan seuraava:

    Tiedoston alareunasta näemme, millainen objekti tulee olemaan.

    Väliohjelmisto saa req:n, res:n ja next:n takaisinkutsun, mutta se saa myös ylimääräisen argumentin, error:n (käyttämällä next(error)-ohjelmaa ennen kuin pääsemme tähän väliohjelmistoon).

    Käytämme destrukturointia saadaksemme muuttujat error-oliosta ja asetamme tilaksi 500, jos sitä ei ole määritetty aiemmin.

    Tämän jälkeen, olipa tila 500, varmistamme, että muutamme viestin niin, että käyttäjä saa yleisen sisäisen palvelimen virheilmoituksen paljastamatta vian tarkkaa luonnetta.

    Sen jälkeen luomme virheobjektin, jolla on type-, status ja message-ominaisuudet (data on valinnainen).

    Luodaan utils- eli aputiedostot:

    Hakemistossa utils luomme vielä kaksi tiedostoa, common.utils.js ja userRoles.utils.js.

    common.utils.js:

    Tämä toiminto auttaa asettamaan useita kenttiä valmistelluille kyselyille avain-arvopareilla.
    ColumnSet avain =? parien array,
    arvojen tulee siis olla samassa järjestyksessä kuin columnSet array.

    userRoles.utils.js:

    module.exports = { Admin: 'Admin', SuperUser: 'SuperUser'}
    Siirry koko ruudun tilaan Poistu koko ruudun tilasta

    Luo asynkronisen funktion:

    Luo middleware-hakemistoon toinen tiedosto nimeltä awaitHandlerFactory.middleware.js ja copy-pastea tämä:

    Yleisesti tiedämme, että middleware on vain asynkroninen metodi, joka saa req-, res- ja next-argumentit, joten jos haluamme tämän middlewaren saavan ylimääräisen argumentin, teemme sen näin (käytämme tätä myös auth-väliohjelmassa seuraavassa vaiheessa).

    Tämä funktio saa callbackin, ajaa middleware-skriptin ja yrittää laukaista tämän callbackin try-lohkossa.
    Jos jokin menee tässä pieleen, se nappaa virheen ja käytämme next(err) (joka siirtää sen seuraavaan middlewareen => error.middleware.js).

    Luo autentikointi Middleware:

    Toinen middleware, jota tarvitsemme, on auth-väliohjelmisto, jota käytämme käyttäjän oikeuksien tarkistamiseen JWT-moduulin kautta.

    Samankaltainen kuin awaitHandlerFactory.middleware.js-väliohjelmisto, meillä on tässä väliohjelmisto, joka vaatii lisäargumentin (joka on valinnainen) => roles.

    Käytin try-catchia säätääkseni catch-alueen virhetilaa 401:ksi (jos esimerkiksi token on vanhentunut).

    Aluksi etsimme req.headers.authorization – jos sitä ei ole määritelty otsikossa tai jos otsikko ei ala “Bearer ” -merkillä, käyttäjä saa 401-vastauksen. Jos se alkaa “Bearer “, saamme tunnuksen ja käytämme.env-tiedoston salaista avainta sen purkamiseen.

    Varmennamme tunnuksen käyttämällä synkronista funktiota jwt.verify, joka saa tunnuksen ja secretKey:n argumentteina ja palauttaa puretun hyötykuorman, onko allekirjoitus kelvollinen ja ovatko valinnaiset expiration-, audience- tai issuer-kentät voimassa. Muussa tapauksessa se heittää virheen.

    Nyt voimme löytää käyttäjän, jolla on tämä token, etsimällä käyttäjätunnuksen.
    Jos käyttäjää ei ole enää olemassa, hän saa poikkeuksen 401 ilman mitään tietoa.
    Jos käyttäjä on olemassa, tarkistamme, onko nykyinen käyttäjä omistaja, joka hakee hänen reittejään tai onko käyttäjällä rooli, jolla on oikeus käyttää tätä reittiä.
    Tallennamme nykyisen käyttäjän siltä varalta, että hän haluaa saada tietonsa seuraavalla väliohjelmistolla (kuten “whoami”-reitillä).

    Tietojen validointi Express Validator -moduulilla:

    Luomme middleware-hakemistoon ylimääräisen tiedoston, jota käytämme req.body-ominaisuuksien tarkistamiseen.

    Luo middleware-hakemistoon alikansio nimeltä validators ja luo tähän hakemistoon tiedosto userValidator.middleware.js. Kopioi-pasteta tämä:

    Tässä tiedostossa käytin express-validator-moduulia, jota on erittäin helppo käyttää aina, kun meidän on tarkistettava joitain ominaisuuksia, tarkistettava, onko ominaisuus olemassa, tai luotava mukautettuja tarkistuksia, joissa käyttäjälle annetaan mukautettu viesti, jos jokin ominaisuuden arvo ei ole kelvollinen.

    Nyt voimme aloittaa reitti-, ohjain- ja mallitiedostojemme luomisen.

    Määritä reitit:

    Luo user.route.js-tiedosto routes-hakemistoon ja copy-pastea tämä:

    Yllä oleva esimerkki näyttää, miten reitit määritellään. Yritetään pilkkoa se osiin:

    • Voit luoda reitittimen käyttämällä express.Router().Jokainen reitti voi ladata välitystoiminnon, joka käsittelee liiketoimintalogiikkaa.UserController esimerkiksi kantaa kaikki tärkeimmät välitystoiminnot.Reitittimen käyttäminen edellyttää, että reititin viedään moduulina ja sitä käytetään pääsovelluksessa käyttämällä app.use(router_module).
    • Käytimme auth-väliohjelmistoa käyttäjän todennukseen ja valtuuttamiseen, käyttäjän tokenin tai käyttäjän roolin tarkistamiseen reitille.Esimerkissämme osa reiteistä käyttää auth-väliohjelmistoa käyttäjän todennuksen ja auktorisoinnin tarkistamiseen.Tämä väliohjelmisto käynnistyy ennen pääväliohjelmistoa (se, joka pitää sisällään liiketoimintalogiikan).seuraavaa takaisinkutsua on kutsuttava, jotta kontrolli siirtyy seuraavalle väliohjelmiston metodille.muuten pyyntö jää roikkumaan.
    • awaitHandlerFactorya (try-catch-väliohjelmisto) käytetään käärimään kaikki asynkroniset väliohjelmistot. Tällä tavoin, jos jokin väliohjelmisto heittää virheen, awaitHandlerFactory nappaa kyseisen virheen. näet, että kaikki väliohjelmistofunktiomme on kääritty awaitHandlerFactory-väliohjelmistolla, mikä auttaa meitä käsittelemään virheemme käyttämällä try-catchia yhdessä paikassa.
    • Lisäksi meillä on createUserSchema-, updateUserSchema- ja validateLogin-skeemat, joilla validoimme rungon ennen kuin aloitamme seuraavan väliohjelmiston.

    HTTP-metodin syntaksi on:

    Luo Controller:

    Luo user.controller.js-tiedosto controllers-hakemistoon ja copy-pastea tämä:

    Kuten edellä mainittiin, controller-tiedostossa on liiketoimintalogiikkamme reittien käsittelyä varten.
    Esimerkissämme jotkin metodit käyttävät UserModel-luokkaa tietokantakyselyyn tietojen saamiseksi.
    Palauttaaksemme tiedot kussakin välitiedostossa käytämme res.send(result) -toimintoa vastauksen lähettämiseen asiakkaalle.

    Luo Model:

    Luo user.model.js-tiedosto models-hakemistoon ja copy-pastea tämä:

    Tämä luokka muodostaa yhteyden ohjaimen ja tietokannan välille.
    Tässä on kaikki metodit, jotka saavat argumentit ohjaimesta, tekevät kyselyn, valmistelevat lausekkeet, ottavat yhteyden tietokantaan käyttämällä db-connection-luokan query-metodia, lähettävät pyynnön valmisteltujen lausekkeiden joukon kanssa ja saavat tuloksen takaisin.
    Jokainen funktio palauttaa tuloksen ohjaimeen.

    .gitIgnore:

    Jos päätät lisätä tämän projektin GitHubiin, älä unohda luoda .gitignore-tiedostoa ja copy-paste tätä:

    node_modules.env
    Enter fullscreen mode Exit fullscreen mode

    Tämä tiedosto vain kertoo gitille, mitkä tiedostot sen tulisi sivuuttaa.
    Tulee välttää node_modules-hakemistoa, koska se on raskas eikä se ole tarpeellinen arkistolle.
    Kun joku kloonaa tämän arkiston, hän käyttää komentoa “npm I” asentaakseen kaikki riippuvuudet.
    Env-tiedoston avulla voit piilottaa yksityiset määrityksesi muilta koodia käyttäviltä kehittäjiltä.

Vastaa

Sähköpostiosoitettasi ei julkaista.