Det er unødvendig å nevne den økende populariteten til Node.js for applikasjonsutvikling. eBay har kjørt en produksjonsnode API-tjeneste siden 2011. PayPal bygger aktivt opp frontfronten i Node. Walmarts mobilside er blitt den største Node-applikasjonen, trafikkmessig. På Thanksgiving-helgen i 2014, Walmart-servere behandlet 1,5 milliarder forespørsler Hvorav 70 prosent ble levert via mobil og drevet av Node.js. På utviklingssiden er Node-pakkebehandling ( over havnivå ) fortsetter å vokse raskt og har nylig overgått 150.000 vertsmoduler.
Samtidig som Ruby har skinner og Python har Django, er det dominerende rammeverket for applikasjonsutvikling for Node ennå ikke etablert. Men det er en kraftig konkurrent som får damp: LoopBack , et åpen kildekode API-rammeverk bygget av San Mateo, California StrongLoop . StrongLoop er en viktig bidragsyter til det siste Nodeversjon , for ikke å nevne de mangeårige vedlikeholdere av Uttrykke , en av de mest populære Node-rammene som eksisterer.
La oss se nærmere på LoopBack og dets evner ved å gjøre alt om til praksis og bygge et eksempel på en applikasjon.
LoopBack er et rammeverk for opprette APIer og koble dem til backend-datakilder. Bygget på toppen av Express, kan det ta en datamodelldefinisjon og enkelt generere en fullt funksjonell REST API fra ende til ende som kan ringes av enhver klient.
LoopBack leveres med en innebygd klient, API Explorer . Vi bruker dette siden det gjør det lettere å se resultatene av arbeidet vårt, og slik at eksempelet vårt kan fokusere på å bygge selve API-et.
Du vil selvfølgelig trenge Node installert på maskinen din for å følge med. Skjønner her . npm følger med, slik at du enkelt kan installere de nødvendige pakkene. La oss komme i gang.
Søknaden vår vil administrere folk som ønsker å donere gaver, eller ting de bare ikke trenger lenger, til noen som trenger dem. Så brukerne vil være givere og mottakere. En giver kan opprette en ny gave og se listen over gaver. En mottaker kan se listen over gaver fra alle brukere, og kan kreve alle som ikke er gjort krav på. Selvfølgelig kan vi bygge givere og mottakere som separate roller på samme enhet (bruker), men la oss prøve å skille dem slik at vi kan se hvordan vi bygger relasjoner i LoopBack. Navnet på denne banebrytende applikasjonen vil være Gi noen .
Installer StrongLoop kommandolinjeverktøy gjennom npm:
$ npm install -g strongloop
Kjør deretter LoopBacks applikasjonsgenerator:
$ slc loopback _-----_ | | .--------------------------. |--(o)--| | Let's create a LoopBack | `---------´ | application! | ( _´U`_ ) '--------------------------' /___A___ | ~ | __'.___.'__ ´ ` |° ´ Y ` ? What's the name of your application? Givesomebody
La oss legge til en modell. Vår første modell vil bli kalt Gift. LoopBack vil be om datakilden og baseklassen. Siden vi ikke har satt opp datakilden ennå, kan vi sette db (memory)
. Baseklassen er en automatisk generert modellklasse, og vi vil bruke PersistedModel
i dette tilfellet, da det allerede inneholder alle de vanlige CRUD-metodene for oss. Deretter spør LoopBack om den skal eksponere modellen gjennom REST (ja), og navnet på REST-tjenesten. Trykk på enter her for å bruke standard, som ganske enkelt er flertallet av modellnavnet (i vårt tilfelle gifts
).
$ slc loopback:model ? Enter the model name: Gift ? Select the data-source to attach Gift to: (Use arrow keys) ❯ db (memory) ? Select model's base class: (Use arrow keys) Model ❯ PersistedModel ? Expose Gift via the REST API? (Y/n) Yes ? Custom plural form (used to build REST URL):
Til slutt gir vi navnene på egenskapene, deres datatyper og påkrevde / ikke-nødvendige flagg. Gave vil ha name
og description
egenskaper:
Let's add some Gift properties now. Enter an empty property name when done. ? Property name: name invoke loopback:property ? Property type: (Use arrow keys) ❯ string ? Required? (y/N)Yes
Skriv inn et tomt eiendomsnavn for å indikere at du er ferdig med å definere egenskaper.
Modellgeneratoren oppretter to filer som definerer modellen i applikasjonens common/models
: gift.json
og gift.js
. JSON-filen spesifiserer alle metadata om enheten: egenskaper, relasjoner, valideringer, roller og metodenavn. JavaScript-filen brukes til å definere ytterligere atferd, og til å spesifisere eksterne kroker som skal kalles før eller etter visse operasjoner (f.eks. Opprette, oppdatere eller slette).
De to andre modellenhetene vil være våre donor- og mottakermodeller. Vi kan lage dem ved hjelp av samme prosess, bortsett fra denne gangen, la oss sette User
som basisklasse. Det vil gi oss noen egenskaper som username
, password
, email
ut av boksen. Vi kan legge til bare navn og land, for eksempel for å ha en full enhet. For mottakeren vil vi også legge til leveringsadressen.
La oss ta en titt på den genererte prosjektstrukturen:
De tre hovedkatalogene er: - /server
- Inneholder node applikasjonsskript og konfigurasjonsfiler. - /client
- Inneholder .js, .html, .css og alle andre statiske filer. - /common
- Denne mappen er felles for både serveren og klienten. Modellfiler går her.
Her er en detaljert oversikt over innholdet i hver katalog, hentet fra LoopBack-dokumentasjon :
Fil eller katalog | Beskrivelse | Hvordan få tilgang i kode |
---|---|---|
Toppkatalog applikasjonskatalog | ||
package.json | Standard npm pakke spesifikasjon. Se pakke.json | Ikke relevant |
/ server katalog - Node applikasjonsfiler | ||
server.js | Hovedprogramprogramfil. | Ikke relevant |
config.json | Applikasjon innstillinger. Se config.json . | app.get('setting-name') |
datasources.json | Datakildekonfigurasjonsfil. Se datakilder.json .For et eksempel, se Opprett ny datakilde . | app.datasources['datasource-name'] |
model-config.json | Modellkonfigurasjonsfil. Se modell-config.json .For mer informasjon, se Koble modeller til datakilder . | Ikke relevant |
middleware.json | Middleware definisjonsfil. For mer informasjon, se Definere mellomvare . | Ikke relevant |
/boot katalog | Legg til skript for å utføre initialisering og oppsett. Se oppstartsskript . | Skript utføres automatisk i alfabetisk rekkefølge. |
/ klientkatalog - klientapplikasjonsfiler | ||
README.md | LoopBack-generatorer lager tomme README-filer i markdown-format. | Ikke relevant |
Annen | Legg til HTML, CSS, klient JavaScript-filer. | |
/ felles katalog - delte applikasjonsfiler | ||
/models katalog | Egendefinerte modellfiler:
| Node: myModel = app.models.myModelName |
I vårt eksempel har vi noen viktige forhold å modellere. En giver kan donere mange gaver, noe som gir forholdet Donor har mange gaver . En mottaker kan også motta mange gaver, så vi har også forholdet Mottaker har mange gaver . På den andre siden, Gaven tilhører Donor , og kan også tilhører mottakeren hvis mottakeren velger å godta det. La oss sette dette inn på språket til LoopBack.
$ slc loopback:relation ? Select the model to create the relationship from: Donor ? Relation type: has many ? Choose a model to create a relationship with: Gift ? Enter the property name for the relation: gifts ? Optionally enter a custom foreign key: ? Require a through model? No
Merk at det ikke er noen gjennomgående modell; vi holder bare referansen til Gaven.
Hvis vi gjentar fremgangsmåten ovenfor for mottaker, og legger til to tilhører forhold til Gift, vil vi oppnå modelldesignet på baksiden. LoopBack oppdaterer automatisk JSON-filene for modellene for å uttrykke nøyaktig hva vi nettopp gjorde gjennom disse enkle dialogene:
// common/models/donor.json ... 'relations': { 'gifts': { 'type': 'hasMany', 'model': 'Gift', 'foreignKey': '' } }, ...
La oss nå se hvordan vi legger ved en ekte datakilde for å lagre alle applikasjonsdataene våre. I forbindelse med dette eksemplet vil vi bruke MongoDB , men LoopBack har moduler for å koble til Oracle, MySQL, PostgreSQL, Redis og SQL Server.
Installer først kontakten:
$ npm install --save loopback-connector-mongodb
Deretter legger du til en datakilde i prosjektet ditt:
$ slc loopback:datasource ? Enter the data-source name: givesomebody ? Select the connector for givesomebody: MongoDB (supported by StrongLoop)
Neste trinn er å konfigurere datakilden i server/datasources.json
. Bruk denne konfigurasjonen for en lokal MongoDB-server:
... 'givesomebody': { 'name': 'givesomebody', 'connector': 'mongodb', 'host': 'localhost', 'port': 27017, 'database': 'givesomebody', 'username': '', 'password': '' } ...
Til slutt, åpne server/model-config.json
og endre datasource
for alle enheter vi vil fortsette i databasen til 'givesomebody'
.
{ ... 'User': { 'dataSource': 'givesomebody' }, 'AccessToken': { 'dataSource': 'givesomebody', 'public': false }, 'ACL': { 'dataSource': 'givesomebody', 'public': false }, 'RoleMapping': { 'dataSource': 'givesomebody', 'public': false }, 'Role': { 'dataSource': 'givesomebody', 'public': false }, 'Gift': { 'dataSource': 'givesomebody', 'public': true }, 'Donor': { 'dataSource': 'givesomebody', 'public': true }, 'Receiver': { 'dataSource': 'givesomebody', 'public': true } }
Det er på tide å se hva vi har bygget så langt! Vi bruker det fantastiske innebygde verktøyet, API Explorer , som kan brukes som klient for tjenesten vi nettopp opprettet. La oss prøve å teste REST API ringer.
I et eget vindu starter du MongoDB med:
$ mongod
Kjør applikasjonen med:
$ node .
Gå til http://localhost:3000/explorer/
i nettleseren din. Du kan se enhetene dine med listen over tilgjengelige operasjoner. Prøv å legge til en donor med POST /Donors
anrop.
API Explorer er veldig intuitiv; velg en av de eksponerte metodene, og det tilsvarende modellskjemaet vises nederst i høyre hjørne. I data
tekstområdet, er det mulig å skrive en tilpasset HTTP-forespørsel. Når forespørselen er fylt ut, klikker du på 'Prøv den ut' -knappen, og serverens svar vises nedenfor.
Som nevnt ovenfor er en av enhetene som er forhåndsbygd med LoopBack, brukerklassen. Bruker har innloggings- og utloggingsmetoder, og kan være bundet til en AccessToken-enhet som beholder token til den spesifikke brukeren. Faktisk er et komplett brukerautentiseringssystem klart til å gå ut av esken. Hvis vi prøver å ringe /Donors/login
gjennom API Explorer , her er svaret vi får:
{ 'id': '9Kvp4zc0rTrH7IMMeRGwTNc6IqNxpVfv7D17DEcHHsgcAf9Z36A3CnPpZJ1iGrMS', 'ttl': 1209600, 'created': '2015-05-26T01:24:41.561Z', 'userId': '' }
id
er faktisk verdien av AccessToken, generert og vedvaret i databasen automatisk. Som du ser her, er det mulig å angi et tilgangstoken og bruke det for hver etterfølgende forespørsel.
En ekstern metode er en statisk metode for en modell, eksponert over et tilpasset REST-endepunkt. Eksterne metoder kan brukes til å utføre operasjoner som ikke er gitt av LoopBacks standardmodell REST API.
Ved siden av CRUD-metodene som vi får ut av boksen, kan vi legge til så mange egendefinerte metoder som vi vil. Alle bør gå inn i [model].js
fil. I vårt tilfelle, la oss legge til en ekstern metode i gavemodellen for å sjekke om gaven allerede er reservert, og en for å liste opp alle gaver som ikke er reservert.
La oss først legge til en ekstra egenskap til modellen som heter reserved
. Bare legg dette til egenskapene i gift.json
:
... 'reserved': { 'type': 'boolean' } ...
Fjernmetoden i gift.js
skal se ut slik:
module.exports = function(Gift) { // method which lists all free gifts Gift.listFree = function(cb) { Gift.find({ fields: { reserved: false } }, cb); }; // expose the above method through the REST Gift.remoteMethod('listFree', { returns: { arg: 'gifts', type: 'array' }, http: { path: '/list-free', verb: 'get' } }); // method to return if the gift is free Gift.isFree = function(id, cb) { var response; Gift.find({ fields: { id: id } }, function(err, gift) { if (err) return cb(err); if (gift.reserved) response = 'Sorry, the gift is reserved'; else response = 'Great, this gift can be yours'; }); cb(null, response); }; // expose the method through REST Gift.remoteMethod('isFree', { accepts: { arg: 'id', type: 'number' }, returns: { arg: 'response', type: 'string' }, http: { path: '/free', verb: 'post' } }); };
Så for å finne ut om en bestemt gave er tilgjengelig, kan klienten nå sende en POST-forespørsel til /api/Gifts/free
, og sende inn id
av den aktuelle gaven.
Noen ganger er det behov for kjøring av en eller annen metode før eller etter fjernmetoden. Du kan definere to typer eksterne kroker:
beforeRemote()
kjører før fjernmetoden.afterRemote()
kjører etter fjernmetoden.I begge tilfeller gir du to argumenter: en streng som samsvarer med den eksterne metoden du vil 'koble' til funksjonen din, og tilbakeringingsfunksjonen. Mye av kraften til eksterne kroker er at strengen kan inkludere jokertegn, så den utløses av en hvilken som helst matchingmetode.
I vårt tilfelle, la oss sette en krok for å skrive ut informasjon til konsollen når en ny giver blir opprettet. For å oppnå dette, la oss legge til en 'før opprett' -krok i donor.js
:
module.exports = function(Donor) { Donor.beforeRemote('create', function(context, donor, next) { console.log('Saving new donor with name: ', context.req.body.name); next(); }); };
Forespørselen kalles med oppgitt context
, og next()
tilbakeringing i mellomvare (diskutert nedenfor) kalles etter at kroken går.
LoopBack-applikasjoner får tilgang til data gjennom modeller, så å kontrollere tilgangen til data betyr å definere begrensninger på modeller; det vil si å spesifisere hvem eller hva som kan lese og skrive dataene eller utføre metoder på modellene. LoopBack-tilgangskontroller bestemmes av tilgangskontrollister, eller ACL-er.
La oss la innloggede givere og mottakere se gaver, men bare påloggede givere kan opprette og slette dem.
$ slc loopback:acl
For å begynne med, nekt alle tilgang til alle sluttpunkter.
? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: All (match all types) ? Select the role: All users ? Select the permission to apply: Explicitly deny access
La deretter alle lese fra gavemodeller:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: Read ? Select the role: All users ? Select the permission to apply: Explicitly grant access
Deretter vil vi tillate autentiserte brukere å lage gaver:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: A single method ? Enter the method name: create ? Select the role: Any authenticated user ? Select the permission to apply: Explicitly grant access
Og til slutt, la oss tillate eieren av gaven å gjøre endringer:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: Write ? Select the role: The user owning the object ? Select the permission to apply: Explicitly grant access
Nå når vi vurderer gift.json
, bør alt være på plass:
'acls': [ { 'accessType': '*', 'principalType': 'ROLE', 'principalId': '$everyone', 'permission': 'DENY' }, { 'accessType': 'READ', 'principalType': 'ROLE', 'principalId': '$everyone', 'permission': 'ALLOW' }, { 'accessType': 'EXECUTE', 'principalType': 'ROLE', 'principalId': '$authenticated', 'permission': 'ALLOW', 'property': 'create' } ],
En viktig merknad her: $authenticated
er en forhåndsdefinert rolle som tilsvarer alle brukere i systemet (både givere og mottakere), men vi vil bare la givere lage nye gaver. Derfor trenger vi en tilpasset rolle. Ettersom rollen er en enhet til vi kommer ut av boksen, kan vi utnytte API-anropet for å opprette $authenticatedDonor
rolle i oppstartsfunksjonen, og så er det bare å endre pricipalId
i gift.json
.
Det vil være nødvendig å opprette en ny fil, server/boot/script.js
, og legge til følgende kode:
Role.create({ name: 'authenticatedDonor' }, function(err, role) { if (err) return debug(err); })
RoleMapping-enheten tilordner roller til brukere. Sørg for at både Role og RoleMapping blir eksponert gjennom REST. I server/model-config.json
, sjekk at 'public'
er satt til true
for rolleenheten. Så i donor.js
kan vi skrive en 'før opprett' krok som vil kartlegge userID
og roleID
i RoleMapping POST API-samtalen.
Middleware inneholder funksjoner som kjøres når en forespørsel til REST-endepunktet. Siden LoopBack er basert på Express, bruker den Express middleware med ett ekstra konsept, kalt 'middleware phases.' Faser brukes til å tydelig definere rekkefølgen funksjoner i mellomvare kalles.
Her er listen over forhåndsdefinerte faser, som gitt i LoopBack-dokumentene:
Hver fase har tre underfaser. For eksempel er underfasene i den innledende fasen:
La oss se raskt på vår standard middleware.json:
{ 'initial:before': { 'loopback#favicon': {} }, 'initial': { 'compression': {}, 'cors': { 'params': { 'origin': true, 'credentials': true, 'maxAge': 86400 } } }, 'session': { }, 'auth': { }, 'parse': { }, 'routes': { }, 'files': { }, 'final': { 'loopback#urlNotFound': {} }, 'final:after': { 'errorhandler': {} } }
I den innledende fasen kaller vi loopback.favicon()
(loopback#favicon
er mellomvare-ID for samtalen). Deretter tredjeparts NPM-moduler compression
og cors
kalles (med eller uten parametere). I sluttfasen har vi to anrop til. urlNotFound
er en LoopBack-samtale, og errorhandler
er tredjepartsmodul. Dette eksemplet skal demonstrere at mange innebygde samtaler kan brukes akkurat som de eksterne npm-modulene. Og selvfølgelig kan vi alltid lage vår egen mellomvare og ringe dem gjennom denne JSON-filen.
loopback-boot
For å avslutte, la oss nevne en modul som eksporterer boot()
funksjon som initialiserer applikasjonen. I server/server.js
du finner følgende kode som støtter applikasjonen:
boot(app, __dirname, function(err) { if (err) throw err; // start the server if `$ node server.js` if (require.main === module) app.start(); });
Dette skriptet vil søke i server/boot
mappen, og last inn alle skriptene den finner der i alfabetisk rekkefølge. Dermed kan vi i server/boot
spesifisere hvilket som helst skript som skal kjøres ved start. Et eksempel er explorer.js
, som kjører API Explorer , klienten vi brukte for å teste API-en vår.
Før jeg forlater deg, vil jeg nevne det StrongLoop Arc , et grafisk brukergrensesnitt som kan brukes som et alternativ til slc
kommandolinjeverktøy. Det inkluderer også verktøy for å bygge, profilere og overvåke Node-applikasjoner. For de som ikke er fans av kommandolinjen, er dette absolutt verdt å prøve. Imidlertid er StrongLoop Arc i ferd med å bli avviklet, og funksjonaliteten blir integrert i IBM API Connect Developer Toolkit .
Generelt kan LoopBack spare deg for mye manuelt arbeid siden du får mange ting ut av esken. Det lar deg fokusere på applikasjonsspesifikke problemer og forretningslogikk. Hvis søknaden din er det basert på CRUD-operasjoner og manipulere forhåndsdefinerte enheter, hvis du er lei av å omskrive brukerens autentiserings- og autorisasjonsinfrastruktur når mange utviklere har skrevet det før deg, eller hvis du vil utnytte alle fordelene med et flott nettrammeverk som Express, og deretter bygge din REST API med LoopBack kan gjøre dine drømmer til virkelighet. Det er enkelt!