Välkommen till andra delen av vår serie på generatorer och Koa. Om du missade det kan du läsa läs del 1 här. Innan du börjar med utvecklingsprocessen, se till att du har installerat Node.js 0.11.9 eller högre.
I den här delen kommer vi att skapa ett ordbok API med hjälp av Koa.js, och du kommer lära dig om routning, komprimering, loggning, hastighetsbegränsning och felhantering i Koa.js. Vi kommer också att använda Mongo som vår datastore och lära oss kort om att importera data till Mongo och den lätthet som kommer med frågan i Koa. Slutligen tittar vi på felsökning av Koa-appar.
Koa har radikala förändringar byggda under sin huva som utnyttjar generatorns godhet av ES6. Förutom förändringen i kontrollflödet introducerar Koa egna egna objekt, till exempel detta
, denna förfrågan
, och this.response
, som bekvämt fungerar som ett syntaktiskt sockerlager som byggts ovanpå Node's req och resobjekt, vilket ger dig tillgång till olika bekvämlighetsmetoder och getters / setters.
Bortsett från bekvämligheten rensar Koa också middleware som, i Express, litade på fula hackar som ofta modifierade kärnobjekt. Det ger också bättre strömhantering.
En middleware är en pluggbar funktion som lägger till eller tar bort en viss funktionalitet genom att göra lite arbete i begäran / svarobjekten i Node.js.
En Koa middleware är i huvudsak en generatorfunktion som returnerar en generatorfunktion och accepterar en annan. Vanligtvis har en applikation en serie middleware som körs för varje förfrågan.
Dessutom måste en middleware leverera till nästa "downstream" middleware om den drivs av en "upstream middleware". Vi kommer att diskutera mer om detta i avsnittet om felhantering.
Bara en sista sak: För att lägga till en middleware till din Koa-applikation använder vi koa.use ()
metod och leverera middleware-funktionen som argumentet. Exempel: app.use (koa-logger)
lägger till koa-logger
till listan över middleware som vår applikation använder.
För att börja med ordbok API behöver vi en fungerande uppsättning definitioner. För att återskapa detta verkliga scenario bestämde vi oss för att gå med en riktig dataset. Vi tog definitionen dumpa från Wikipedia och laddade den i Mongo. Satsen bestod av cirka 700 000 ord då vi endast importerade den engelska dumpningen. Varje post (eller dokument) består av ett ord, dess typ och dess betydelse. Du kan läsa mer om importprocessen i import.txt
filen i förvaret.
För att gå vidare i utvecklingsprocessen klonar du förvaret och kontrollerar dina framsteg genom att växla till olika förpliktelser. För att klona repo, använd följande kommando:
$ git klon https://github.com/bhanuc/dictapi.git
Vi kan börja med att skapa en basserver Koa:
var koa = kräver ("koa"); var app = koa (); app.use (funktion * (nästa) this.type = 'json'; this.status = 200; this.body = 'Välkommen': 'Detta är en nivå 2 Hello World Application !!';); om (! module.parent) app.listen (3000); console.log ('Hello World körs på http: // localhost: 3000 /');
I första raden importerar vi Koa och sparar en instans i appvariablerna. Sedan lägger vi till en enda middleware i rad 5, vilket är en anonym generatorfunktion som tar nästa variabel som en parameter. Här ställer vi in svarstypens typ och statuskod, som också bestäms automatiskt, men vi kan också ställa in dem manuellt. Sedan satte vi slutligen svarets kropp.
Eftersom vi har satt kroppen i vår första middleware markerar detta slutet på varje förfrågningscykel och ingen annan middleware kommer att vara involverad. Slutligen börjar vi servern genom att ringa dess lyssna
metod och vidarebefordra portnumret som en parameter.
Vi kan starta servern genom att köra skriptet via:
$ npm installera koa $ node --harmony index.js
Du kan direkt nå detta stadium genom att flytta för att begå 6858ae0
:
$ git checkout 6858ae0
Routing tillåter oss att omdirigera olika förfrågningar till olika funktioner på grundval av begäran typ och URL. Vi kanske till exempel vill svara på /logga in
annorlunda än Bli Medlem
. Detta kan göras genom att lägga till en middleware, som manuellt kontrollerar webbadressen till den mottagna begäran och kör motsvarande funktioner. Eller, istället för att manuellt skriva den middleware, kan vi använda en community-made middleware, även känd som en middleware-modul.
För att lägga till routingskapacitet i vår applikation använder vi en communitymodul som heter koa-router
.
Att använda koa-router
, Vi kommer att ändra den befintliga koden till koden som visas nedan:
var koa = kräver ("koa"); var app = koa (); var router = kräver (koa-router); var mount = kräver ('koa-mount'); var handler = funktion * (nästa) this.type = 'json'; this.status = 200; this.body = 'Välkommen': 'Detta är en nivå 2 Hello World Application !!'; ; var APIv1 = ny router (); APIv1.get ('/ all', handler); app.use (mount ('/ v1', APIv1.middleware ())); om (! module.parent) app.listen (3000); console.log ('Hello World körs på http: // localhost: 3000 /');
Här har vi importerat två moduler, var router
butiker koa-router
och montera
lagrar koa-mount
modulen, så att vi kan använda routern i vår Koa-applikation.
På rad 6 har vi definierat vår hanterare
funktion, som är samma funktion som tidigare men här har vi gett det ett namn. På rad 12 lagrar vi en instans av routern i APIv1
, och på linje 13 registrerar vi vår handlare för alla SKAFFA SIG
förfrågningar på väg /Allt
.
Så alla förfrågningar utom när en få förfrågan skickas till localhost: 3000 / all
kommer att returnera "inte hittat". Slutligen på linje 15 använder vi montera
middleware, vilket ger en användbar generatorfunktion som kan matas till app.use ()
.
För att direkt nå detta steg eller jämföra din ansökan, kör följande kommando i den klonade repo:
$ git checkout 8f0d4e8
Innan vi kör vår applikation, behöver vi nu installera koa-router
och koa-mount
använder sig av npm
. Vi observerar att eftersom komplexiteten i vår applikation ökar, ökar antalet moduler / beroenden också.
För att hålla reda på all information om projektet och göra den tillgänglig för npm
, Vi lagrar all information i package.json
inklusive alla beroenden. Du kan skapa package.json manuellt eller genom att använda ett interaktivt kommandoradsgränssnitt som öppnas med hjälp av $ npm init
kommando.
"namn": "koa-api-ordbok", "version": "0.0.1", "beskrivning": "koa-api-dictionary ansökan", "main": "index" namn ":" Bhanu Pratap Chaudhary "," email ":" [email protected] "," repository ": " typ ":" git "," url ":" https://github.com/bhanuc/ dictapi.git "," licens ":" MIT "," motorer ": " nod ":"> = 0.11.13 "
En mycket minimal package.json
filen ser ut som ovanstående.
En gång package.json
är närvarande kan du spara beroendet med följande kommando:
$ npm installera--spara
Till exempel: I det här fallet installerar vi modulerna med följande kommando för att spara beroendet i package.json
.
$ npm installera koa-router koa-mount -save
Nu kan du köra programmet med $ node --harmony index.js
.
Du kan läsa mer om package.json
här.
Vi börjar med att skapa två rutter för API: n, en för att få ett enda resultat i en snabbare fråga och en sekund för att få alla matchande ord (vilket är långsammare för första gången).
För att hålla saker hanterbara kommer vi att behålla alla API-funktionerna i en separat mapp som heter api
och en fil som heter api.js
, och importera det senare i vårt huvud index.js
fil.
var munk = kräver ("munk"); var wrap = kräver ("comonk"); var db = munk ("localhost / mydb"); var words = wrap (db.get ('words')); / ** * Hämta alla resultat. * / exports.all = funktion * () if (this.request.query.word) var res = yield words.find (word: this.request.query.word); this.body = res; annars this.response.status = 404; ; / ** * FÅ ett enda resultat. * / exports.single = function * () if (this.request.query.word) var res = yield words.findOne (word: this.request.query.word); this.body = res; annars this.response.status = 404; ;
Här använder vi sam-munk
, som fungerar en omslag runt munk
, vilket gör det mycket enkelt för oss att fråga MongoDB med hjälp av generatorer i Koa. Här importerar vi munk
och sam-munk
, och anslut till MongoDB-förekomsten på rad 3. Vi ringer slå in()
på samlingar, för att göra dem generatervänliga.
Sedan lägger vi till två genererade generatormetoder Allt
och enda
som en egenskap av export
variabel så att de kan importeras i andra filer. I var och en av funktionerna kontrollerar vi först för frågeparametern "word". Om vi är närvarande frågar vi efter resultatet eller annars svarar vi med ett 404-fel.
Vi använder avkastning
sökord för att vänta på resultaten som diskuteras i den första artikeln, vilket pausar körningen tills resultatet är mottaget. På rad 12 använder vi hitta
metod som returnerar alla matchande ord, som lagras i res och därefter skickas tillbaka. På linje 23 använder vi hitta en
metod som finns tillgänglig på insamlingen, vilket returnerar det första matchande resultatet.
var koa = kräver ("koa"); var app = koa (); var router = kräver (koa-router); var mount = kräver ('koa-mount'); var api = kräver ('. / api / api.js'); var APIv1 = ny router (); APIv1.get ('/ all', api.all); APIv1.get ('/ single', api.single); app.use (mount ('/ v1', APIv1.middleware ())); om (! module.parent) app.listen (3000); console.log ('Dictapi körs på http: // localhost: 3000 /');
Här importerar vi exporterade metoder från api.js
och vi tilldelar hanterare till SKAFFA SIG
rutter /Allt
/enda
och vi har ett fullt fungerande API och program redo.
För att köra programmet behöver du bara installera munk
och sam-munk
moduler med kommandot nedan. Se också till att du har en körinstans av MongoDB där du har importerat den samling som finns i git-förvaret med de instruktioner som nämns i import.txtweird
.
$ npm installera munk comonk - spar
Nu kan du köra programmet med följande kommando:
$ node --harmony index.js
Du kan öppna webbläsaren och öppna följande webbadresser för att kontrollera hur programmet fungerar. Byt bara "nytt" med ordet du vill fråga.
http: // localhost: 3000 / V1 / all ord = new
http: // localhost: 3000 / V1 / enda ord = new
För att direkt nå detta steg eller jämföra din ansökan, kör följande kommando i den klonade repo:
$ git checkout f1076eb
Genom att använda cascading middleware kan vi fånga fel med hjälp av försök fånga
mekanism, eftersom varje middleware kan svara samtidigt som den ger både nedströms och uppströms. Så, om vi lägger till en Prova och fånga middleware i början av programmet kommer det att fånga alla de fel som uppstått av begäran i resten av middleware eftersom det blir den senaste mellanprogramvaran under uppströms. Lägger till följande kod på rad 10 eller tidigare i index.js
borde fungera.
app.use (funktion * (nästa) försök skicka nästa; // överför exekveringen till nedströms middlewares fånga (err) // exekveras endast när ett fel inträffar och ingen annan middleware svarar på begäran this.type = 'json'; // valfritt här thisstatus = err.status || 500; this.body = 'error': 'Programmet gick bara bonkers, förhoppningsvis har NSA alla loggar;)'; // delegera felet tillbaka till ansökan this.app.emit ('error', err, this); );
Lagring av loggar är en väsentlig del av en modern applikation, eftersom loggar är till stor hjälp vid felsökning och att hitta problem i en ansökan. De lagrar också alla aktiviteter och kan därmed användas för att ta reda på användaraktivitetsmönster och intressanta andra mönster.
Räntebegränsning har också blivit en viktig del av moderna applikationer där det är viktigt att stoppa spammare och bots från att slösa bort dina dyrbara serverresurser och för att hindra dem från att skrapa ditt API.
Det är ganska enkelt att lägga till loggning och betygsbegränsning för vår Koa-ansökan. Vi använder två gemenskapsmoduler: koa-logger
och koa-bättre-hastighetsbegränsande
. Vi måste lägga till följande kod i vår ansökan:
var logger = kräver (koa-logger); vargräns = kräver ("koa-better-ratelimit"); // Lägg till raderna nedan precis under fel middleware. app.use (limit (duration: 1000 * 60 * 3, // 3 min max: 10, blacklist: [])); app.use (logger ());
Här har vi importerat två moduler och lagt dem till som middleware. Loggen loggar varje förfrågan och skriver ut i stdout
av processen som lätt kan sparas i en fil. Och begränsa middleware begränsar antalet begäranden som en viss användare kan begära inom en viss tidsram (här är det maximalt tio förfrågningar om tre minuter). Du kan också lägga till en rad IP-adresser som kommer att vara svartlistade och deras förfrågan kommer inte att behandlas.
Kom ihåg att installera modulerna innan du använder koden med:
$ npm installera koa-logger koa-better-ratelimit -save
Ett sätt att säkerställa snabbare leverans är att gzip ditt svar, vilket är ganska enkelt i Koa. För att komprimera din trafik i Koa kan du använda koa-compress
modul.
Här kan alternativ vara ett tomt objekt eller kan konfigureras enligt kravet.
var compress = kräver ('koa-compress'); var opts = filter: funktion (content_type) return /text/i.test(content_type), // filterförfrågningar som ska komprimeras med regex tröskel: 2048, // minsta storlek för att komprimera flush: require ('zlib') .Z_SYNC_FLUSH; // använd koden nedan för att lägga till middleware till applikationen app.use (komprimera (ops));
Du kan även stänga av komprimering i en förfrågan genom att lägga till följande kod till en middleware:
this.compress = true;
Glöm inte att installera komprimera med npm
.
$ npm installera komprimera - spara
För att direkt nå detta steg eller jämföra din ansökan, kör följande kommando i den klonade repo:
git checkout 8f5b5a6
Testet bör vara en väsentlig del av all kod, och man bör rikta in sig för maximal testdäckning. I den här artikeln ska vi skriva tester för de rutter som är tillgängliga från vår ansökan. Vi ska använda supertest och mocka för att skapa våra test.
Vi lagrar vårt test i test.js
i api
mapp. I båda testen beskriver vi först vårt test och ger det ett mer mänskligt läsbart namn. Därefter kommer vi att skicka en anonym funktion som beskriver testets korrekta beteende och tar en återuppringning som innehåller själva testet. I varje test importerar vi vår ansökan, initierar servern, beskriver begäran, webbadress och fråga och ställer sedan in kodning till gzip. Slutligen söker vi efter svaret om det är korrekt.
var request = kräver ("supertest"); var api = kräver ('... / index.js'); beskriv ("GET all", funktion () it ("ska svara med alla ord", funktion (gjort) var app = api; request (app.listen ()) .get ('/ v1 / all') .query (word: 'new') .set ('Accept-Encoding', 'gzip') .expect ('Content-Type', / json /) .expect (200) .end (gjort);) ) (), (funktion) (var) var app = api; förfrågan (app.listen ()) .get (' v1 / singel ") .query (word: 'new') .set ('Acceptera-Encoding', 'gzip') .expect (200) .expect ('Content-Type', / json /) .end funktion (fel, res) om (err) kasta err, annars om (! ('_ id' i res.body)) returnera "missing id" Fel ("missande ord"); färdigt (););))
För att köra vårt test ska vi göra en Makefile
:
test: @ NODE_ENV = test ./node_modules/.bin/mocha \ --require should \ --reporter nyan \ --harmony \ --bail \ api / test.js .PHONY: test
Här har vi konfigurerat reportern (nyan katt) och testramen (mocka). Observera att importen ska läggas till --harmoni
för att aktivera ES6-läget. Slutligen anger vi också platsen för alla tester. en Makefile
kan konfigureras för oändlig testning av din ansökan.
För att testa din app, använd bara följande kommando i programmets huvudkatalog.
$ göra test
Kom bara ihåg att installera testmoduler (mocha, should, supertest) innan du testar, med kommandot nedan:
$ npm installera mocha ska mocha - save-dev
För att driva våra applikationer i produktion använder vi PM2, vilket är en användbar nodprocessskärm. Vi bör inaktivera loggerappen under produktionen. Det kan automatiseras med hjälp av miljövariabler.
För att installera PM2, skriv följande kommando i terminal
$ npm installera pm2 -g
Och vår app kan startas med följande kommando:
$ pm2 start index.js --node-args = "- harmoni"
Nu, även om vår ansökan kraschar, kommer den att starta om automatiskt och du kan sova ordentligt.
Koa är en lätt och uttrycksfull middleware för Node.js som gör processen att skriva webbprogram och API mer roligare.
Det gör det möjligt för dig att utnyttja en mängd community moduler för att utöka funktionaliteten i din ansökan och förenkla alla vardagliga uppgifter, vilket gör webbutveckling till en rolig aktivitet.
Tveka inte att lämna några kommentarer, frågor eller annan information i fältet nedan.