Koa.js - Szybki przewodnik

Struktura aplikacji internetowych zapewnia prosty interfejs API do tworzenia witryn, aplikacji internetowych i zaplecza. Nie musisz martwić się o protokoły niskiego poziomu, procesy itp.

Co to jest Koa?

Koa zapewnia minimalny interfejs do tworzenia aplikacji. Jest to bardzo mały framework (600 LoC), który zapewnia narzędzia wymagane do tworzenia aplikacji i jest dość elastyczny. Na npm dostępnych jest wiele modułów dla Koa, które można bezpośrednio do niego podłączyć. Koa można traktować jako rdzeń express.js bez wszystkich dzwonków i gwizdków.

Dlaczego Koa?

Koa ma niewielką powierzchnię (600 LoC) i jest bardzo cienką warstwą abstrakcji nad węzłem do tworzenia aplikacji po stronie serwera. Jest całkowicie podłączany i ma ogromną społeczność. Pozwala nam to również łatwo przedłużyć Koa i używać go zgodnie z naszymi potrzebami. Został zbudowany przy użyciu najnowszej technologii (ES6), która daje przewagę nad starszymi frameworkami, takimi jak express.

Mops

Mops (wcześniej znany jako Jade) to zwięzły język do pisania szablonów HTML.

  • Produkuje HTML
  • Obsługuje kod dynamiczny
  • Obsługuje wielokrotnego użytku (DRY)

Jest to jeden z najpopularniejszych języków szablonów używanych w koa.

MongoDB i Mongoose

MongoDB to baza danych dokumentów typu open source, zaprojektowana z myślą o łatwości programowania i skalowania. Będziemy używać tej bazy danych do przechowywania danych.

Mongoose to klient API dla node.js, który ułatwia dostęp do naszej bazy danych z naszej aplikacji Koa.

Aby rozpocząć programowanie w ramach platformy Koa, musisz mieć zainstalowane oprogramowanie Node i npm (menedżer pakietów węzłów). Jeśli jeszcze ich nie masz, przejdź do konfiguracji węzła, aby zainstalować węzeł w systemie lokalnym. Potwierdź, że węzeł i npm są zainstalowane, uruchamiając następujące polecenia w terminalu.

$ node --version
$ npm --version

Powinieneś otrzymać wynik podobny do -

v5.0.0
3.5.2

Upewnij się, że wersja Twojego węzła jest wyższa niż 6.5.0. Teraz, gdy mamy już skonfigurowane Node i npm, zrozummy, czym jest npm i jak go używać.

Menedżer pakietów węzłów (npm)

npm to menedżer pakietów dla node. Rejestr npm to publiczna kolekcja pakietów kodu open source dla Node.js, aplikacji internetowych typu front-end, aplikacji mobilnych, robotów, routerów i niezliczonych innych potrzeb społeczności JavaScript. npm pozwala nam uzyskać dostęp do wszystkich tych pakietów i zainstalować je lokalnie. Możesz przeglądać listę pakietów dostępnych na npm na npmJS .

Jak korzystać z npm?

Istnieją dwa sposoby zainstalowania pakietu przy użyciu npm - globalnie i lokalnie.

Globally- Ta metoda jest zwykle używana do instalowania narzędzi programistycznych i pakietów opartych na interfejsie CLI. Aby zainstalować pakiet globalnie, użyj następującego polecenia.

$ npm install -g <package-name>

Locally- Ta metoda jest zwykle używana do instalowania struktur i bibliotek. Pakiet zainstalowany lokalnie może być używany tylko w katalogu, w którym został zainstalowany. Aby zainstalować pakiet lokalnie, użyj tego samego polecenia, co powyżej, bez -g flaga.

$ npm install <package-name>

Za każdym razem, gdy tworzymy projekt za pomocą npm, musimy dostarczyć plik package.json, który zawiera wszystkie szczegóły dotyczące naszego projektu. npm ułatwia nam skonfigurowanie tego pliku. Skonfigurujmy nasz projekt rozwojowy.

Step 1 - Uruchom swój terminal / cmd, utwórz nowy folder o nazwie hello-world i włóż do niego płytę CD -

Step 2 - Teraz, aby utworzyć plik package.json przy użyciu npm, użyj następującego.

npm init

Poprosi Cię o następujące informacje -

Po prostu naciskaj Enter i wprowadź swoje imię i nazwisko w polu „nazwisko autora”.

Step 3- Teraz mamy skonfigurowany plik package.json, zainstalujemy Koa. Aby zainstalować Koa i dodać go do naszego pliku package.json, użyj następującego polecenia.

$ npm install --save koa

Aby potwierdzić poprawną instalację Koa, uruchom następujące polecenie.

$ ls node_modules #(dir node_modules for windows)

Tip - The --save flagę można zastąpić -Sflaga. Ta flaga zapewnia, że ​​Koa zostanie dodana jako zależność do naszego pliku package.json. Ma to tę zaletę, że następnym razem, gdy będziemy musieli zainstalować wszystkie zależności naszego projektu, wystarczy uruchomić polecenie npm install, a ona znajdzie zależności w tym pliku i zainstaluje je za nas.

To wszystko, czego potrzebujemy, aby rozpocząć programowanie przy użyciu frameworka Koa. Aby znacznie ułatwić nasz proces rozwoju, zainstalujemy narzędzie npm, nodemon. To narzędzie polega na tym, że ponownie uruchamia nasz serwer, gdy tylko wprowadzimy zmianę w którymkolwiek z naszych plików, w przeciwnym razie musimy ręcznie ponownie uruchomić serwer po każdej modyfikacji pliku. Aby zainstalować nodemon, użyj następującego polecenia.

$ npm install -g nodemon

Teraz wszyscy jesteśmy gotowi, aby zanurzyć się w Koa!

Po skonfigurowaniu programowania nadszedł czas, aby rozpocząć tworzenie naszej pierwszej aplikacji przy użyciu Koa. Utwórz nowy plik o nazwieapp.js i wpisz w nim następujące informacje.

var koa = require('koa');
var app = new koa();

app.use(function* (){
   this.body = 'Hello world!';
});

app.listen(3000, function(){
   console.log('Server running on https://localhost:3000')
});

Zapisz plik, przejdź do terminala i wpisz.

$ nodemon app.js

Spowoduje to uruchomienie serwera. Aby przetestować tę aplikację, otwórz przeglądarkę i przejdź dohttps://localhost:3000 i powinieneś otrzymać następującą wiadomość.

Jak działa ta aplikacja?

Pierwsza linia importuje Koa do naszego pliku. Dostęp do jego API mamy poprzez zmienną Koa. Używamy go do tworzenia aplikacji i przypisywania jej do var app.

app.use(function)- Ta funkcja jest oprogramowaniem pośredniczącym, które jest wywoływane za każdym razem, gdy nasz serwer otrzymuje żądanie. Dowiemy się więcej o oprogramowaniu pośrednim w kolejnych rozdziałach. Funkcja wywołania zwrotnego to generator, który zobaczymy w następnym rozdziale. Kontekst tego generatora jest nazywany kontekstem w Koa. Ten kontekst służy do uzyskiwania dostępu i modyfikowania obiektów żądań i odpowiedzi. Ustanawiamy treść tej odpowiedziHello world!.

app.listen(port, function)- Ta funkcja wiąże i nasłuchuje połączeń na określonym porcie. Port jest tutaj jedynym wymaganym parametrem. Funkcja wywołania zwrotnego jest wykonywana, jeśli aplikacja działa pomyślnie.

Jedną z najbardziej ekscytujących nowych funkcji JavaScript ES6 jest nowy rodzaj funkcji, zwany generatorem. Przed generatorami cały skrypt był zwykle wykonywany w kolejności od góry do dołu, bez łatwego sposobu na zatrzymanie wykonywania kodu i wznowienie później z tym samym stosem. Generatory to funkcje, które można zamknąć, a następnie ponownie wprowadzić. Ich kontekst (zmienne powiązania) zostanie zapisany przy ponownym wejściu.

Generatory pozwalają nam zatrzymać wykonywanie kodu pomiędzy. Przyjrzyjmy się zatem prostemu generatorowi.

var generator_func = function* (){
   yield 1;
   yield 2;
};

var itr = generator_func();
console.log(itr.next());
console.log(itr.next());
console.log(itr.next());

Po uruchomieniu powyższego kodu wynik będzie następujący.

{ value: 1, done: false }
{ value: 2, done: false }
{ value: undefined, done: true }

Zajrzyjmy do powyższego kodu. Najpierw tworzymy generator o nazwiegenerator_func(). Stworzyliśmy instancję tej dziwnie wyglądającej funkcji i przypisaliśmy ją doitr. Wtedy zaczęliśmy dzwonićnext() na tej zmiennej itr.

Wywołanie next () uruchamia generator i działa, aż osiągnie wydajność. Następnie zwraca obiekt z wartością i gotowe, gdzie wartość ma wartość wyrażenia. To wyrażenie może oznaczać wszystko. W tym momencie wstrzymuje wykonywanie. Ponownie, gdy wywołujemy tę funkcję (next), generator wznawia wykonywanie od ostatniej granicy plastyczności, przy czym stan funkcji jest taki sam w momencie przerwy, aż do następnej granicy plastyczności. Dzieje się tak do momentu, gdy w kodzie nie ma już punktów plastyczności.

Generatory w Koa

Dlaczego więc omawiamy generatory w tym samouczku. Jak być może pamiętasz z programu Hello world, użyliśmy plikufunction* ()notacja do przekazania wywołania zwrotnego do app.use (). Koa to obiekt, który zawiera tablicę funkcji generatora oprogramowania pośredniego, z których wszystkie są tworzone i wykonywane w sposób podobny do stosu przy każdym żądaniu. Koa realizuje również downstreaming, po którym następuje upstreaming przepływu sterowania.

Spójrz na poniższy przykład, aby lepiej to zrozumieć.

var koa = require('koa');
var app = koa();
 
app.use(function* (next) {
   //do something before yielding to next generator function 
   
   //in line which will be 1st event in downstream
   console.log("1");
   yield next;
 
   //do something when the execution returns upstream, 
   //this will be last event in upstream
   console.log("2");
});
app.use(function* (next) {
   // This shall be 2nd event downstream
   console.log("3");
   yield next;
 
   // This would be 2nd event upstream
   console.log("4");
});
app.use(function* () { 
   // Here it would be last function downstream
   console.log("5");
   
   // Set response body
   this.body = "Hello Generators";

   // First event of upstream (from the last to first)
   console.log("6");
});

app.listen(3000);

Podczas uruchamiania powyższego kodu i przechodzenia do https://localhost:3000/ otrzymujemy następujące dane wyjściowe na naszej konsoli.

1
3
5
6
4
2

Zasadniczo w ten sposób Koa używa generatorów. Pozwala nam tworzyć kompaktowe oprogramowanie pośredniczące przy użyciu tej właściwości i pisać kod zarówno dla funkcji nadrzędnych, jak i podrzędnych, chroniąc nas w ten sposób przed wywołaniami zwrotnymi.

Struktury internetowe udostępniają zasoby, takie jak strony HTML, skrypty, obrazy itp. Na różnych trasach. Koa nie obsługuje tras w module podstawowym. Musimy użyć modułu routera Koa, aby łatwo tworzyć trasy w Koa. Zainstaluj ten moduł za pomocą następującego polecenia.

npm install --save koa-router

Teraz, gdy mamy zainstalowany router Koa, spójrzmy na prosty przykład trasy GET.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();              //Instantiate the router
_.get('/hello', getMessage);   // Define routes

function *getMessage() {
   this.body = "Hello world!";
};

app.use(_.routes());           //Use the routes defined using the router
app.listen(3000);

Jeśli uruchomimy naszą aplikację i przejdziemy do localhost: 3000 / hello, serwer otrzyma żądanie pobierania na trasie „/ hello”. Nasza aplikacja Koa wykonuje funkcję zwrotną dołączoną do tej trasy i wysyła „Hello World!” jako odpowiedź.

Na tej samej trasie możemy też mieć wiele różnych metod. Na przykład,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router(); //Instantiate the router

_.get('/hello', getMessage);
_.post('/hello', postMessage);

function *getMessage() {
	this.body = "Hello world!";
};
function *postMessage() {
   this.body = "You just called the post method at '/hello'!\n";
};
app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Aby przetestować to żądanie, otwórz terminal i użyj cURL do wykonania następującego żądania

curl -X POST "https://localhost:3000/hello"

Specjalna metoda, all, jest dostarczany przez express do obsługi wszystkich typów metod http na określonej trasie przy użyciu tej samej funkcji. Aby skorzystać z tej metody, wypróbuj następujące rozwiązania -

_.all('/test', allMessage);

function *allMessage(){
   this.body = "All HTTP calls regardless of the verb will get this response";
};

Możemy teraz zdefiniować trasy; są statyczne lub nieruchome. Aby korzystać z tras dynamicznych, musimy zapewnić różne typy tras. Korzystanie z tras dynamicznych pozwala nam przekazywać parametry i przetwarzać na ich podstawie. Poniżej przedstawiono przykład trasy dynamicznej.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/:id', sendID);

function *sendID() {
   this.body = 'The id you specified is ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

Aby to przetestować, przejdź do https://localhost:3000/123. Otrzymasz następującą odpowiedź.

Możesz zastąpić „123” w adresie URL czymkolwiek innym, a zostanie to odzwierciedlone w odpowiedzi. Poniżej znajduje się złożony przykład powyższego.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:name/:id', sendIdAndName);

function *sendIdAndName(){
   this.body = 'id: ' + this.params.id + ' and name: ' + this.params.name;
};

app.use(_.routes());

app.listen(3000);

Aby to przetestować, przejdź do https://localhost:3000/things/tutorialspoint/12345.

Możesz użyć this.paramsobiekt, aby uzyskać dostęp do wszystkich parametrów, które przekazujesz w adresie URL. Zauważ, że powyższe dwie mają różne ścieżki. Nigdy się nie pokryją. Również jeśli chcesz wykonać kod, gdy otrzymasz „/ things”, musisz zdefiniować go osobno.

Trasy dopasowane do wzorca

Możesz również użyć wyrażenia regularnego, aby ograniczyć dopasowanie parametrów adresu URL. Powiedzmy, że potrzebujesz, aby identyfikator składał się z pięciu cyfr. Możesz użyć następującej definicji trasy.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:id([0-9]{5})', sendID);

function *sendID(){
   this.body = 'id: ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

Zauważ, że to będzie onlydopasuj żądania, które mają 5-cyfrowy identyfikator. Możesz użyć bardziej złożonych wyrażeń regularnych, aby dopasować / zweryfikować swoje trasy. Jeśli żadna z twoich tras nie pasuje do żądania, w odpowiedzi otrzymasz komunikat Nie znaleziono.

Na przykład, jeśli zdefiniujemy te same trasy, co powyżej, na żądanie z poprawnym adresem URL otrzymamy -

W żądaniu podano metodę HTTP, która określa operację, której zażądał klient. W poniższej tabeli podsumowano powszechnie używane metody HTTP.

Sr.No. Metoda i opis
1

GET

Metoda GET żąda reprezentacji określonego zasobu. Żądania używające GET powinny tylko pobierać dane i nie powinny mieć żadnego innego skutku.

2

POST

Metoda POST żąda od serwera akceptacji danych zawartych w żądaniu jako nowego obiektu / jednostki zasobu identyfikowanego przez URI.

3

PUT

Metoda PUT żąda, aby serwer zaakceptował dane zawarte w żądaniu jako modyfikację istniejącego obiektu identyfikowanego przez URI. Jeśli go nie ma, to metoda PUT powinna go utworzyć.

4

DELETE

Metoda DELETE żąda od serwera usunięcia określonego zasobu.

Oto najpopularniejsze metody HTTP. Aby dowiedzieć się więcej o nich, przejdź dohttps://www.tutorialspoint.com/http/http_methods.htm.

Obiekt żądania Koa to abstrakcja znajdująca się na szczycie podstawowego obiektu żądania węzła, zapewniająca dodatkową funkcjonalność, która jest przydatna przy codziennym programowaniu serwera HTTP. Obiekt żądania Koa jest osadzony w obiekcie kontekstu,this. Wylogujmy się z obiektu żądania za każdym razem, gdy otrzymamy żądanie.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   console.log(this.request);
   this.body = 'Your request has been logged.';
}
app.use(_.routes());
app.listen(3000);

Po uruchomieniu tego kodu i przejściu do https://localhost:3000/hello, otrzymasz następującą odpowiedź.

Na konsoli wylogujesz obiekt żądania.

{ 
   method: 'GET',
   url: '/hello/',
   header: 
   { 
      host: 'localhost:3000',
      connection: 'keep-alive',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) 
         AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
      accept: 'text/html,application/xhtml+xml,
         application/xml;q = 0.9,image/webp,*/*;q = 0.8',
      dnt: '1',
      'accept-encoding': 'gzip, deflate, sdch',
      'accept-language': 'en-US,en;q = 0.8' 
   }
}

Mamy dostęp do wielu przydatnych właściwości żądania wykorzystującego ten obiekt. Spójrzmy na kilka przykładów.

request.header

Zawiera wszystkie nagłówki żądań.

request.method

Zapewnia metodę żądania (GET, POST itp.)

request.href

Zawiera pełny adres URL żądania.

request.path

Zawiera ścieżkę żądania. Bez ciągu zapytania i podstawowego adresu URL.

request.query

Podaje przeanalizowany ciąg zapytania. Na przykład, jeśli zarejestrujemy to w żądaniu takim jakhttps://localhost:3000/hello/?name=Ayush&age=20&country=India, wtedy otrzymamy następujący obiekt.

{
   name: 'Ayush',
   age: '20',
   country: 'India'
}

request.accepts (typ)

Ta funkcja zwraca prawdę lub fałsz w zależności od tego, czy żądane zasoby akceptują dany typ żądania.

Więcej informacji na temat obiektu żądania można znaleźć w dokumentach pod adresem Request .

Obiekt odpowiedzi Koa jest abstrakcją znajdującą się na szczycie podstawowego obiektu odpowiedzi węzła, zapewniając dodatkową funkcjonalność, która jest przydatna przy codziennym programowaniu serwera HTTP. Obiekt odpowiedzi Koa jest osadzony w obiekcie kontekstu,this. Wylogujmy się z obiektu odpowiedzi za każdym razem, gdy otrzymamy żądanie.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   this.body = 'Your request has been logged.';
   console.log(this.response);
}

app.use(_.routes());
app.listen(3000);

Po uruchomieniu tego kodu i przejściu do https://localhost:3000/hello wtedy otrzymasz następującą odpowiedź.

Na konsoli wylogujesz obiekt żądania.

{ 
   status: 200,
   message: 'OK',
   header: 
   {
      'content-type': 'text/plain; charset=utf-8',
      'content-length': '12' 
   },
   body: 'Your request has been logged.' 
}

Status i wiadomość są ustawiane automatycznie przez Koa, ale mogą być przez nas modyfikowane. Jeśli nie ustawimy treści odpowiedzi, kod stanu zostanie ustawiony na 404. Po ustawieniu treści odpowiedzi domyślnie ustawiany jest stan 200. Możemy jawnie zmienić to zachowanie.

Mamy dostęp do wielu przydatnych właściwości odpowiedzi wykorzystującej ten obiekt. Spójrzmy na kilka przykładów -

response.header

Zawiera wszystkie nagłówki odpowiedzi.

response.status

Zawiera stan odpowiedzi (200, 404, 500 itd.). Ta właściwość jest również używana do ustawiania stanu odpowiedzi.

odpowiedź. wiadomość

Zawiera komunikat odpowiedzi. Ta właściwość służy również do ustawiania niestandardowych wiadomości z odpowiedziami. Jest to związane ze statusem response.status.

response.body

Pobierz lub ustaw treść odpowiedzi. Zwykle uzyskujemy do niego dostęp za pomocą obiektu kontekstu. To tylko inny sposób na uzyskanie do niego dostępu. Treść może być typu: String, Buffer, Stream, Object lub Null.

response.type

Pobierz lub ustaw typ zawartości bieżącej odpowiedzi.

response.get (pole)

Ta funkcja jest używana do pobierania wartości nagłówków z polem wartości bez rozróżniania wielkości liter.

response.set (pole, wartość)

Ta funkcja służy do ustawiania nagłówka odpowiedzi przy użyciu pary pola i wartości.

response.remove (pole)

Ta funkcja służy do usuwania nagłówka odpowiedzi przy użyciu nazwy pola.

Możesz przeczytać więcej o obiekcie odpowiedzi w dokumentacji w Response .

Przekierowanie jest bardzo ważne przy tworzeniu stron internetowych. Jeśli zażądano zniekształconego adresu URL lub na serwerze są błędy, należy przekierować je do odpowiednich stron błędów. Przekierowania mogą być również używane do utrzymywania ludzi z dala od zastrzeżonych obszarów witryny.

Utwórzmy stronę błędu i przekierowujmy na tę stronę za każdym razem, gdy ktoś zażąda nieprawidłowego adresu URL.

var koa = require('koa');
var router = require('koa-router');
var app = koa();
var _ = router();

_.get('/not_found', printErrorMessage);
_.get('/hello', printHelloMessage);

app.use(_.routes());
app.use(handle404Errors);

function *printErrorMessage() {
   this.status = 404;
   this.body = "Sorry we do not have this resource.";
}
function *printHelloMessage() {
   this.status = 200;
   this.body = "Hey there!";
}
function *handle404Errors(next) {
   if (404 != this.status) return;
   this.redirect('/not_found');
}
app.listen(3000);

Kiedy uruchomimy ten kod i przejdziemy do dowolnej trasy innej niż / hello, zostaniemy przekierowani do / not_found. Oprogramowanie pośredniczące umieściliśmy na końcu (wywołanie funkcji app.use do tego oprogramowania pośredniego). Gwarantuje to, że w końcu dotrzemy do oprogramowania pośredniczącego i wyślemy odpowiednią odpowiedź. Poniżej przedstawiono wyniki, które widzimy po uruchomieniu powyższego kodu.

Kiedy nawigujemy do https://localhost:3000/hellootrzymujemy -

Jeśli nawigujemy inną trasą, otrzymujemy -

Obsługa błędów odgrywa ważną rolę w tworzeniu aplikacji internetowych. Koa również używa do tego celu oprogramowania pośredniczącego.

W Koa dodajesz oprogramowanie pośredniczące, które to robi try { yield next }jako jedno z pierwszych programów pośredniczących. Jeśli napotkamy jakikolwiek błąd poniżej, wracamy do powiązanej klauzuli catch i obsługujemy tutaj błąd. Na przykład -

var koa = require('koa');
var app = koa();

//Error handling middleware
app.use(function *(next) {
   try {
      yield next;
   } catch (err) {
      this.status = err.status || 500;
      this.body = err.message;
      this.app.emit('error', err, this);
   }
});

//Create an error in the next middleware
//Set the error message and status code and throw it using context object

app.use(function *(next) {
   //This will set status and message
   this.throw('Error Message', 500);
});

app.listen(3000);

Celowo utworzyliśmy błąd w powyższym kodzie i obsługujemy błąd w bloku catch naszego pierwszego oprogramowania pośredniego. To jest następnie wysyłane do naszej konsoli, a także wysyłane jako odpowiedź do naszego klienta. Poniżej znajduje się komunikat o błędzie, który otrzymujemy po wyzwoleniu tego błędu.

InternalServerError: Error Message
   at Object.module.exports.throw 
      (/home/ayushgp/learning/koa.js/node_modules/koa/lib/context.js:91:23)
   at Object.<anonymous> (/home/ayushgp/learning/koa.js/error.js:18:13)
   at next (native)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:65:19)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5
   at Object.co (/home/ayushgp/learning/koa.js/node_modules/co/index.js:50:10)
   at Object.toPromise (/home/ayushgp/learning/koa.js/node_modules/co/index.js:118:63)
   at next (/home/ayushgp/learning/koa.js/node_modules/co/index.js:99:29)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:69:7)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5

W tej chwili każde żądanie wysłane do serwera spowoduje ten błąd.

Funkcje oprogramowania pośredniczącego to funkcje, które mają dostęp do context objectoraz kolejna funkcja oprogramowania pośredniego w cyklu żądanie-odpowiedź aplikacji. Funkcje te służą do modyfikowania obiektów żądań i odpowiedzi dla zadań, takich jak analizowanie treści żądań, dodawanie nagłówków odpowiedzi itp. Koa idzie o krok dalej, dając'downstream', a następnie przekazanie sterowania z powrotem 'upstream'. Ten efekt nazywa sięcascading.

Poniżej znajduje się prosty przykład działania funkcji oprogramowania pośredniego.

var koa = require('koa');
var app = koa();
var _ = router();

//Simple request time logger
app.use(function* (next) {
   console.log("A new request received at " + Date.now());
   
   //This function call is very important. It tells that more processing is 
   //required for the current request and is in the next middleware function/route handler.
   yield next;
});

app.listen(3000);

Powyższe oprogramowanie pośredniczące jest wywoływane dla każdego żądania na serwerze. Dlatego po każdym żądaniu w konsoli otrzymamy następujący komunikat.

A new request received at 1467267512545

Aby ograniczyć to do określonej trasy (i wszystkich jej podtrasów), musimy po prostu utworzyć trasy, tak jak zrobiliśmy to w przypadku routingu. Właściwie to tylko te oprogramowanie pośredniczące obsługuje nasze żądanie.

Na przykład,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

//Simple request time logger
_.get('/request/*', function* (next) {
   console.log("A new request received at " + Date.now());
   yield next;
});

app.use(_.routes());
app.listen(3000);

Teraz za każdym razem, gdy zażądasz jakiejś podtrasy „/ request”, tylko wtedy zapisze czas.

Kolejność wywołań oprogramowania pośredniego

Jedną z najważniejszych rzeczy związanych z oprogramowaniem pośredniczącym w Koa jest to, że kolejność, w jakiej są zapisywane / umieszczane w pliku, to kolejność, w jakiej są wykonywane w dół. Gdy tylko trafimy na deklarację zysku w oprogramowaniu pośrednim, przełącza się ono na następne oprogramowanie pośrednie w linii, aż dotrzemy do ostatniego. Potem znowu zaczynamy cofać się i wznawiać funkcje z instrukcji yield.

Na przykład w poniższym fragmencie kodu pierwsza funkcja jest wykonywana najpierw do uzyskania zysku, następnie do drugiego oprogramowania pośredniczącego do uzyskania, a następnie do trzeciej. Ponieważ nie mamy już tutaj oprogramowania pośredniego, zaczynamy cofać się, wykonując w odwrotnej kolejności, tj. Trzeci, drugi, pierwszy. W tym przykładzie podsumowano, jak używać oprogramowania pośredniczącego na sposób Koa.

var koa = require('koa');
var app = koa();

//Order of middlewares
app.use(first);
app.use(second);
app.use(third);

function *first(next) {
   console.log("I'll be logged first. ");
   
   //Now we yield to the next middleware
   yield next;
   
   //We'll come back here at the end after all other middlewares have ended
   console.log("I'll be logged last. ");
};

function *second(next) {
   console.log("I'll be logged second. ");
   yield next;
   console.log("I'll be logged fifth. ");
};

function *third(next) {
   console.log("I'll be logged third. ");
   yield next;
   console.log("I'll be logged fourth. ");
};

app.listen(3000);

Kiedy odwiedzimy '/' po uruchomieniu tego kodu, na naszej konsoli otrzymamy -

I'll be logged first. 
I'll be logged second. 
I'll be logged third. 
I'll be logged fourth. 
I'll be logged fifth. 
I'll be logged last.

Poniższy diagram podsumowuje, co faktycznie dzieje się w powyższym przykładzie.

Teraz, gdy wiemy, jak stworzyć własne oprogramowanie pośredniczące, omówmy niektóre z najczęściej używanych programów pośredniczących tworzonych przez społeczność.

Oprogramowanie pośredniczące innych firm

Lista oprogramowania pośredniego innych firm do obsługi ekspresowej jest dostępna tutaj. Poniżej przedstawiono niektóre z najczęściej używanych programów pośredniczących -

  • koa-bodyparser
  • koa-router
  • koa-static
  • koa-compress

W kolejnych rozdziałach omówimy wiele programów pośredniczących.

Mops to szablonowy silnik. Silniki szablonów są używane do usuwania zaśmiecania naszego kodu serwera za pomocą HTML, łącząc ciągi znaków z istniejącymi szablonami HTML. Mops to bardzo potężny silnik szablonów, który ma wiele funkcji, takich jakfilters, includes, inheritance, interpolationitp. Jest wiele powodów do omówienia w tej sprawie.

Aby używać Mopsa z Koa, musimy go zainstalować za pomocą następującego polecenia.

$ npm install --save pug koa-pug

Po zainstalowaniu mopsa ustaw go jako silnik szablonów dla swojej aplikacji. Dodaj następujący kod do pliku app.js.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Teraz utwórz nowy katalog o nazwie views. W katalogu utwórz plik o nazwie first_view.pug i wprowadź w nim następujące dane.

doctype html
html
   head
      title = "Hello Pug"
   body
      p.greetings#people Hello Views!

Aby uruchomić tę stronę, dodaj następującą trasę do swojej aplikacji.

_.get('/hello', getMessage); // Define routes

function *getMessage(){
   this.render('first_view');
};

Otrzymasz wynik jako -

To, co robi Pug, to konwertuje ten bardzo prosty wyglądający znacznik do html. Nie musimy śledzić zamykania naszych tagów, nie musimy używać słów kluczowych class i id, a raczej używać '.' i „#”, aby je zdefiniować. Powyższy kod jest najpierw konwertowany do

<!DOCTYPE html>
<html>
   <head>
      <title>Hello Pug</title>
   </head>
    
   <body>
      <p class = "greetings" id = "people">Hello Views!</p>
   </body>
</html>

Mops jest w stanie zrobić znacznie więcej niż upraszczanie znaczników HTML. Przyjrzyjmy się niektórym z tych funkcji Mopsa.

Proste tagi

Tagi są zagnieżdżane zgodnie z ich wcięciem. Podobnie jak w powyższym przykładzie,<title> został wcięty w <head>tag, więc był w środku. Jednakże<body> tag był na tym samym wcięciu, więc był rodzeństwem <head> etykietka.

Nie musimy zamykać tagów. Gdy tylko Mops napotka następny tag na tym samym lub zewnętrznym poziomie wcięcia, zamyka tag za nas.

Istnieją trzy metody umieszczania tekstu w tagu:

  • Przestrzeń oddzielona -
h1 Welcome to Pug
  • Tekst potokowy -
div
   | To insert multiline text, 
   | You can use the pipe operator.
  • Blok tekstu -
div.
   But that gets tedious if you have a lot of text. 
   You can use "." at the end of tag to denote block of text. 
   To put tags inside this block, simply enter tag in a new line and 
   indent it accordingly.

Komentarze

Pug używa tej samej składni co JavaScript (//) do tworzenia komentarzy. Te komentarze są konwertowane na komentarze html (<! - comment ->). Na przykład,

//This is a Pug comment

Ten komentarz zostanie przekonwertowany na -

<!--This is a Pug comment-->

Atrybuty

Aby zdefiniować atrybuty, używamy listy atrybutów oddzielonych przecinkami, w nawiasach. Atrybuty klasy i ID mają specjalne reprezentacje. Poniższy wiersz kodu obejmuje definiowanie atrybutów, klas i identyfikatora dla danego tagu html.

div.container.column.main#division(width = "100",height = "100")

Ta linia kodu jest konwertowana na -

<div class = "container column main" id = "division" width = "100" height = "100"></div>

Przekazywanie wartości do szablonów

Kiedy renderujemy szablon Pug, możemy przekazać mu wartość z naszego programu obsługi trasy, której możemy następnie użyć w naszym szablonie. Utwórz nową procedurę obsługi trasy z następującym kodem.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app // equals to pug.use(app) and app.use(pug.middleware)
});

var _ = router(); //Instantiate the router

_.get('//dynamic_view', dynamicMessage); // Define routes

function *dynamicMessage(){
   this.render('dynamic', {
      name: "TutorialsPoint", 
      url:"https://www.tutorialspoint.com"
   });
};

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Następnie utwórz nowy plik widoku w katalogu views o nazwie dynamic.pug, używając poniższego kodu.

html
   head
      title = name
   body
      h1 = name
      a(href = url) URL

otwarty localhost:3000/dynamicw przeglądarce i po nim powinno być wyjście. -

Możemy również użyć tych przekazanych zmiennych w tekście. Aby wstawić przekazane zmienne między tekstem tagu, używamy składni # {nazwa_zmiennej}. Na przykład w powyższym przykładzie, jeśli chcemy wstawić Pozdrowienia z TutorialsPoint, musimy użyć poniższego kodu.

html
   head
      title = name
   body
      h1 Greetings from #{name}
      a(href = url) URL

Ta metoda używania wartości nosi nazwę interpolacji.

Warunki

Możemy również używać instrukcji warunkowych i konstrukcji pętli. Rozważmy ten praktyczny przykład, jeśli użytkownik jest zalogowany, chcielibyśmy wyświetlić „Cześć, Użytkownik”, a jeśli nie, to chcielibyśmy pokazać mu link „Zaloguj / Zarejestruj się”. Aby to osiągnąć, możemy zdefiniować prosty szablon, taki jak -

html
   head
      title Simple template
   body
      if(user)
         h1 Hi, #{user.name}
      else
         a(href = "/sign_up") Sign Up

Kiedy renderujemy to za pomocą naszych tras i przekazujemy obiekt taki jak -

this.render('/dynamic',{user: 
   {name: "Ayush", age: "20"}
});

Zostanie wyświetlony komunikat Hi, Ayush. Jeśli jednak nie przekażemy żadnego obiektu lub przekażemy go bez klucza użytkownika, otrzymamy link Zarejestruj się.

Uwzględnij i składniki

Mops zapewnia bardzo intuicyjny sposób tworzenia komponentów dla strony internetowej. Na przykład, jeśli widzisz witrynę z wiadomościami, nagłówek z logo i kategoriami jest zawsze stały. Zamiast kopiować to do każdego widoku, możemy użyć dołączania. Poniższy przykład pokazuje, jak możemy użyć funkcji include -

Utwórz trzy widoki za pomocą następującego kodu -

header.pug

div.header.
   I'm the header for this website.

content.pug

html
   head
      title Simple template
   body
      include ./header.pug
      h3 I'm the main content
      include ./footer.pug

footer.pug

div.footer.
   I'm the footer for this website.

Utwórz do tego trasę w następujący sposób.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

_.get('/components', getComponents);

function *getComponents(){
   this.render('content.pug');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Iść do localhost:3000/components, powinieneś otrzymać następujące dane wyjściowe.

include może być również używany do dołączania zwykłego tekstu, CSS i JavaScript.

Mopsa ma wiele innych funkcji. Jednak są one poza zakresem tego samouczka. Możesz dalej odkrywać Pug w Pug .

Formularze są integralną częścią sieci. Prawie każda odwiedzana przez nas witryna internetowa oferuje nam formularze, które przesyłają lub pobierają dla nas pewne informacje. Aby rozpocząć korzystanie z formularzy, najpierw zainstalujemy ciało koa. Aby to zainstalować, przejdź do terminala i użyj -

$ npm install --save koa-body

Zastąp zawartość pliku app.js następującym kodem.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

_.get('/', renderForm);
_.post('/', handleForm);

function * renderForm(){
   this.render('form');
}
function *handleForm(){
   console.log(this.request.body);
   console.log(this.req.body);
   this.body = this.request.body; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

Nowe rzeczy, które tutaj robimy, to importowanie parsera treści i multera. Używamy parsera treści do analizowania żądań nagłówków json i x-www-form-urlencoded, podczas gdy używamy multer do analizowania danych wieloczęściowych / formularzy.

Stwórzmy formularz html, aby to przetestować! Utwórz nowy widok o nazwie form.pug z następującym kodem.

html
   head
      title Form Tester
   body
      form(action = "/", method = "POST")
         div
            label(for = "say") Say: 
            input(name = "say" value = "Hi")
         br
         div
            label(for = "to") To: 
            input(name = "to" value = "Koa form")
         br
         button(type = "submit") Send my greetings

Uruchom swój serwer za pomocą -

nodemon index.js

Teraz przejdź do localhost: 3000 / i wypełnij formularz, jak chcesz, i prześlij go. Otrzymasz odpowiedź jako -

Spójrz na swoją konsolę, pokaże ci ona treść twojego żądania jako obiekt JavaScript. Na przykład -

Plik this.request.bodyobiekt zawiera przeanalizowane treści żądania. Aby użyć pól z tego obiektu, po prostu użyj ich jak zwykłych obiektów JS.

To tylko jeden ze sposobów wysłania prośby. Istnieje wiele innych sposobów, ale te nie mają tutaj znaczenia, ponieważ nasza aplikacja Koa będzie obsługiwać wszystkie te żądania w ten sam sposób. Aby dowiedzieć się więcej o różnych sposobach składania wniosków, zajrzyj na tę stronę.

Aplikacje internetowe muszą zapewniać funkcjonalność umożliwiającą przesyłanie plików. Zobaczmy, jak możemy odbierać pliki od klientów i przechowywać je na naszym serwerze.

Użyliśmy już oprogramowania pośredniczącego koa-body do analizowania żądań. To oprogramowanie pośrednie jest również używane do obsługi przekazywania plików. Stwórzmy formularz, który pozwoli nam przesłać pliki, a następnie zapisać te pliki za pomocą Koa. Najpierw utwórz szablon o nazwiefile_upload.pug z następującą treścią.

html
   head
      title File uploads
   body
      form(action = "/upload" method = "POST" enctype = "multipart/form-data")
         div
            input(type = "text" name = "name" placeholder = "Name")
         
         div
            input(type = "file" name = "image")
         
         div
            input(type = "submit")

Pamiętaj, że w formularzu musisz podać ten sam typ kodowania, co powyżej. Teraz zajmijmy się tymi danymi na naszym serwerze.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app 
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},    //This is where the files would come
   multipart: true,
   urlencoded: true
}));

var _ = router(); //Instantiate the router

_.get('/files', renderForm);
_.post('/upload', handleForm);

function * renderForm(){
   this.render('file_upload');
}

function *handleForm(){
   console.log("Files: ", this.request.body.files);
   console.log("Fields: ", this.request.body.fields);
   this.body = "Received your data!"; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

Po uruchomieniu tego otrzymasz następujący formularz.

Po przesłaniu tego konsola wygeneruje następujące dane wyjściowe.

Przesłane pliki są przechowywane w ścieżce w powyższym wyniku. Możesz uzyskać dostęp do plików we wniosku za pomocąthis.request.body.files a pola w tym wniosku złożone przez this.request.body.fields.

Pliki statyczne to pliki, które klienci pobierają w postaci, w jakiej są z serwera. Utwórz nowy katalog,public. Express, domyślnie nie pozwala na obsługę plików statycznych.

Do tego celu potrzebujemy oprogramowania pośredniczącego. Śmiało i zainstalujkoa-serve -

$ npm install --save koa-static

Teraz musimy useto oprogramowanie pośredniczące. Wcześniej utwórz katalog o nazwie public. Tutaj będziemy przechowywać wszystkie nasze pliki statyczne. To pozwala nam zabezpieczyć nasz kod serwera, ponieważ nic powyżej tego publicznego folderu nie byłoby dostępne dla klientów. Po utworzeniu katalogu publicznego utwórz plik o nazwiehello.txtw nim z dowolną zawartością. Teraz dodaj do pliku app.js.

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));

app.listen(3000);

Note- Koa wyszukuje pliki względem katalogu statycznego, więc nazwa katalogu statycznego nie jest częścią adresu URL. Trasa główna jest teraz ustawiona na katalog publiczny, więc wszystkie ładowane pliki statyczne będą traktowane jako publiczne jako katalog główny. Aby sprawdzić, czy to działa poprawnie, uruchom aplikację i wejdź nahttps://localhost:3000/hello.txt

Powinieneś otrzymać następujące dane wyjściowe. Zwróć uwagę, że nie jest to dokument HTML ani widok Pug, a raczej prosty plik txt.

Wiele reżyserów statycznych

Możemy również ustawić wiele katalogów zasobów statycznych za pomocą -

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));
app.use(serve('./images'));

app.listen(3000);

Teraz, kiedy poprosimy o plik, Koa przeszuka te katalogi i wyśle ​​nam pasujący plik.

Pliki cookie to proste, małe pliki / dane, które są wysyłane do klienta na żądanie serwera i przechowywane po stronie klienta. Za każdym razem, gdy użytkownik ponownie ładuje witrynę, ten plik cookie jest wysyłany z żądaniem. Pomaga to śledzić działania użytkowników. Istnieje wiele zastosowań plików cookie HTTP.

  • Zarządzanie sesjami
  • Personalizacja (systemy rekomendacji)
  • Śledzenie użytkowników

Aby używać plików cookie w Koa, mamy następujące funkcje: ctx.cookies.set() i ctx.cookies.get(). Aby ustawić nowy plik cookie, zdefiniujmy nową trasę w naszej aplikacji Koa.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie() {
   this.cookies.set('foo', 'bar', {httpOnly: false});
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Aby sprawdzić, czy plik cookie jest ustawiony, czy nie, po prostu przejdź do przeglądarki, uruchom konsolę i wprowadź -

console.log(document.cookie);

Spowoduje to wyświetlenie następującego wyniku (może być ustawione więcej plików cookie, być może z powodu rozszerzeń przeglądarki).

"foo = bar"

Oto przykład powyższego.

Przeglądarka odsyła również pliki cookie za każdym razem, gdy wysyła zapytanie do serwera. Aby wyświetlić plik cookie na serwerze, na konsoli serwera w trasie dodaj następujący kod do tej trasy.

console.log('Cookies: foo = ', this.cookies.get('foo'));

Następnym razem, gdy wyślesz żądanie do tej trasy, otrzymasz następujące dane wyjściowe.

Cookies: foo = bar

Dodawanie plików cookie z czasem wygaśnięcia

Możesz dodać pliki cookie, które wygasają. Aby dodać plik cookie, który wygasa, po prostu przekaż obiekt z właściwością „expires” ustawioną na czas, w którym ma wygasnąć. Na przykład,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
	this.cookies.set('name', 'value', { 
      httpOnly: false, expires: 360000 + Date.now() });
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Usuwanie istniejących plików cookie

Aby usunąć plik cookie, po prostu ustaw plik cookie na pusty ciąg. Na przykład, jeśli chcesz usunąć plik cookie o nazwiefooużyj poniższego kodu.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
   this.cookies.set('name', '');
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Spowoduje to usunięcie wspomnianego pliku cookie. Pamiętaj, że powinieneś zostawićHttpOnly opcja ma być prawdziwa, gdy nie używa pliku cookie w kodzie po stronie klienta.

Protokół HTTP jest bezstanowy, dlatego aby powiązać żądanie z jakimkolwiek innym żądaniem, potrzebujesz sposobu na przechowywanie danych użytkownika między żądaniami HTTP. Pliki cookie i parametry adresu URL są odpowiednimi sposobami przesyłania danych między klientem a serwerem. Jednak oba są czytelne po stronie klienta. Sesje rozwiązują dokładnie ten problem. Przypisujesz klientowi identyfikator, a wszystkie dalsze żądania wysyła przy użyciu tego identyfikatora. Informacje powiązane z klientem są przechowywane na serwerze połączonym z tym identyfikatorem.

Będziemy potrzebować sesji koa, więc zainstaluj ją za pomocą -

npm install --save koa-session

Umieścimy plik koa-sessionoprogramowanie pośredniczące na miejscu. W tym przykładzie użyjemy pamięci RAM do przechowywania sesji. Nigdy nie używaj tego w środowiskach produkcyjnych. Oprogramowanie pośredniczące sesji obsługuje wszystko, tj. Tworzenie sesji, ustawianie plików cookie sesji i tworzenie obiektu sesji w obiekcie kontekstu.

Za każdym razem, gdy ponownie wysyłamy żądanie od tego samego klienta, będziemy przechowywać u nas informacje o jego sesji (zakładając, że serwer nie został ponownie uruchomiony). Możemy dodać więcej właściwości do tego obiektu sesji. W poniższym przykładzie utworzymy licznik wyświetleń dla klienta.

var session = require('koa-session');
var koa = require('koa');
var app = koa();

app.keys = ['Shh, its a secret!'];
app.use(session(app));  // Include the session middleware

app.use(function *(){
   var n = this.session.views || 0;
   this.session.views = ++n;
   
   if(n === 1)
      this.body = 'Welcome here for the first time!';
   else
      this.body = "You've visited this page " + n + " times!";
})

app.listen(3000);

To, co robi powyższy kod, to kiedy użytkownik odwiedza witrynę, tworzy nową sesję dla użytkownika i przypisuje plik cookie. Następnym razem, gdy użytkownik odwiedzi, plik cookie jest sprawdzany, a zmienna sesji page_view jest odpowiednio aktualizowana.

Teraz, jeśli uruchomisz aplikację i przejdziesz do localhost:3000, otrzymasz następującą odpowiedź.

Jeśli ponownie odwiedzisz stronę, licznik stron wzrośnie. W tym przypadku strona była odświeżana 12 razy.

Uwierzytelnianie to proces, w którym podane poświadczenia są porównywane z danymi zapisanymi w bazie danych autoryzowanych użytkowników w lokalnym systemie operacyjnym lub na serwerze uwierzytelniania. Jeśli poświadczenia są zgodne, proces jest zakończony, a użytkownik uzyskuje uprawnienia dostępu.

Stworzymy bardzo podstawowy system uwierzytelniania, który będzie używany Basic HTTP Authentication. Jest to najprostszy możliwy sposób wymuszenia kontroli dostępu, ponieważ nie wymaga plików cookie, sesji ani niczego innego. Aby z tego skorzystać, klient musi wysłać nagłówek Authorization wraz z każdym zgłoszonym żądaniem. Nazwa użytkownika i hasło nie są szyfrowane, ale są łączone w jeden ciąg, taki jak poniżej.

username:password

Ten ciąg jest kodowany za pomocą Base64, a słowo Basic jest umieszczane przed tą wartością. Na przykład, jeśli twoja nazwa użytkownika to Ayush, a hasło India, to ciąg"Ayush:India" zostanie wysłany w postaci zakodowanej w nagłówku autoryzacji.

Authorization: Basic QXl1c2g6SW5kaWE=

Aby zaimplementować to w swojej aplikacji koa, będziesz potrzebować oprogramowania pośredniczącego koa-basic-auth. Zainstaluj go za pomocą -

$ npm install --save koa-basic-auth

Teraz otwórz plik app.js i wprowadź w nim następujący kod.

//This is what the authentication would be checked against
var credentials = { name: 'Ayush', pass: 'India' }

var koa = require('koa');
var auth = require('koa-basic-auth');
var _ = require('koa-router')();

var app = koa();

//Error handling middleware
app.use(function *(next){
   try {
      yield next;
   } catch (err) {
      if (401 == err.status) {
         this.status = 401;
         this.set('WWW-Authenticate', 'Basic');
         this.body = 'You have no access here';
      } else {
         throw err;
      }
   }
});

// Set up authentication here as first middleware. 
// This returns an error if user is not authenticated.
_.get('/protected', auth(credentials), function *(){
   this.body = 'You have access to the protected area.';
   yield next;
});

// No authentication middleware present here.
_.get('/unprotected', function*(next){
   this.body = "Anyone can access this area";
   yield next;
});

app.use(_.routes());
app.listen(3000);

Stworzyliśmy oprogramowanie pośredniczące do obsługi błędów, które obsługuje wszystkie błędy związane z uwierzytelnianiem. Następnie stworzyliśmy 2 trasy -

  • /protected- Dostęp do tej trasy jest możliwy tylko wtedy, gdy użytkownik prześle poprawny nagłówek uwierzytelniania. Dla wszystkich innych spowoduje to błąd.

  • /unprotected - Dostęp do tej trasy może uzyskać każdy, z uwierzytelnieniem lub bez.

Teraz, jeśli wyślesz żądanie do / protected bez nagłówka uwierzytelniania lub z niewłaściwymi poświadczeniami, otrzymasz błąd. Na przykład,

$ curl https://localhost:3000/protected

Otrzymasz odpowiedź jako -

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic
Content-Type: text/plain; charset=utf-8
Content-Length: 28
Date: Sat, 17 Sep 2016 19:05:56 GMT
Connection: keep-alive

Please authenticate yourself

Jednak dzięki odpowiednim poświadczeniom otrzymasz oczekiwaną odpowiedź. Na przykład,

$ curl -H "Authorization: basic QXl1c2g6SW5kaWE=" https://localhost:3000/protected -i

Otrzymasz odpowiedź jako -

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Sat, 17 Sep 2016 19:07:33 GMT
Connection: keep-alive

You have access to the protected area.

Trasa / niezabezpieczona jest nadal dostępna dla wszystkich.

Kompresja to prosty i skuteczny sposób na zaoszczędzenie przepustowości i przyspieszenie witryny. Jest kompatybilny tylko z nowoczesnymi przeglądarkami i powinien być używany ostrożnie, jeśli Twoi użytkownicy również korzystają ze starszych przeglądarek.

Podczas wysyłania odpowiedzi z serwera, jeśli używana jest kompresja, może to znacznie poprawić czas ładowania. Będziemy używać oprogramowania pośredniczącego o nazwiekoa-compress zadbać o kompresję plików, a także ustawienie odpowiednich nagłówków.

Śmiało i zainstaluj oprogramowanie pośredniczące za pomocą -

$ npm install --save koa-compress

Teraz w pliku app.js dodaj następujący kod -

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

app.use(compress({
   filter: function (content_type) {
      return /text/i.test(content_type)
   },
   threshold: 2048,
   flush: require('zlib').Z_SYNC_FLUSH
}));

var _ = router(); //Instantiate the router

_.get('/', getRoot);

function *getRoot(next){
   this.render('index');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Dzięki temu nasze oprogramowanie pośredniczące do kompresji jest gotowe. Opcja filtru to funkcja sprawdzająca typ zawartości odpowiedzi w celu podjęcia decyzji o kompresji. Opcja progu to minimalny rozmiar odpowiedzi w bajtach do skompresowania. Gwarantuje to, że nie kompresujemy każdej małej odpowiedzi.

Poniżej znajduje się odpowiedź bez kompresji.

Poniżej przedstawiono podobną odpowiedź z kompresją.

Jeśli spojrzysz na zakładkę rozmiaru na dole, możesz bardzo dobrze zobaczyć różnicę między nimi. Po kompresji plików następuje poprawa o ponad 150%.

Buforowanie to termin przechowywania odpowiedzi wielokrotnego użytku w celu szybszego wykonywania kolejnych żądań. Każda przeglądarka jest dostarczana z implementacją pamięci podręcznej HTTP. Wszystko, co musimy zrobić, to upewnić się, że każda odpowiedź serwera zawiera poprawne dyrektywy nagłówka HTTP, aby poinstruować przeglądarkę, kiedy i jak długo odpowiedź może być przechowywana w pamięci podręcznej przez przeglądarkę.

Oto niektóre korzyści z włączenia buforowania do aplikacji internetowych -

  • Twoje koszty sieciowe spadną. Jeśli zawartość jest przechowywana w pamięci podręcznej, będziesz musiał wysyłać jej mniej przy każdym kolejnym żądaniu.

  • Szybkość i wydajność Twojej strony internetowej wzrasta.

  • Twoje treści mogą być udostępniane nawet wtedy, gdy klient jest offline.

Będziemy używać oprogramowania pośredniczącego koa-static-cache do implementacji buforowania w naszej aplikacji. Zainstaluj te oprogramowanie pośrednie za pomocą -

$ npm install --save koa-static-cache

Przejdź do pliku app.js i dodaj do niego następujący kod.

var koa = require('koa');
var app = koa();

var path = require('path');
var staticCache = require('koa-static-cache');

app.use(staticCache(path.join(__dirname, 'public'), {
   maxAge: 365 * 24 * 60 * 60  //Add these files to caches for a year
}))

app.listen(3000);

Plik koa-static-cacheOprogramowanie pośredniczące służy do buforowania odpowiedzi serwera po stronie klienta. Plikcache-controlnagłówek jest ustawiany zgodnie z opcjami, które podajemy podczas inicjalizacji obiektu pamięci podręcznej. Ustawiliśmy czas wygaśnięcia tej buforowanej odpowiedzi na 1 rok. Poniżej znajdują się porównania żądań, które wysłaliśmy przed i po buforowaniu pliku.

Przed zapisaniem tego pliku w pamięci podręcznej zwrócony kod stanu wynosił 200, co jest prawidłowe. Nagłówki odpowiedzi zawierały wiele informacji dotyczących zawartości, która miała być zapisana w pamięci podręcznej, a także otrzymały rozszerzenieETag za treść.

Następnym razem, gdy żądanie zostało wysłane, zostało wysłane wraz z ETtag. Ponieważ nasza zawartość nie uległa zmianie na serwerze, odpowiadający jej ETag również pozostał taki sam, a klientowi powiedziano, że kopia, którą ma lokalnie, jest aktualna z tym, co serwer zapewni i powinien używać lokalnego zamiast żądać jeszcze raz.

Note- Aby unieważnić dowolny plik w pamięci podręcznej, wystarczy zmienić jego nazwę pliku i zaktualizować jego odniesienie. Zapewni to, że masz nowy plik do wysłania do klienta, a klient nie może załadować go z powrotem z pamięci podręcznej.

Otrzymujemy prośby, ale nigdzie ich nie przechowujemy. Potrzebujemy bazy danych do przechowywania danych. Użyjemy słynnej bazy danych NoSQL o nazwieMongoDB. Aby zainstalować i przeczytać o Mongo, przejdź do tego linku.

Aby używać Mongo z Koa, potrzebujemy klienta API dla węzła. Jest dla nas wiele opcji, jednak w tym samouczku będziemy trzymać się mangusty . Mongoose jest używany dodocument modelingw Node dla MongoDB. Modelowanie dokumentów oznacza, że ​​utworzymy plikModel (podobnie jak class w programowaniu zorientowanym na dokumenty), a następnie będziemy produkować documents używając tego modelu (tak jak tworzymy documents of a classw OOP). Całe nasze przetwarzanie zostanie wykonane na tych „dokumentach”, a na końcu zapiszemy te dokumenty w naszej bazie danych.

Konfigurowanie Mongoose

Teraz, gdy mamy zainstalowane Mongo, zainstalujmy Mongoose, w ten sam sposób, w jaki instalowaliśmy nasze inne pakiety węzłów.

$ npm install --save mongoose

Zanim zaczniemy używać mangusty, musimy stworzyć bazę danych za pomocą powłoki Mongo. Aby utworzyć nową bazę danych, otwórz terminal i wpisz „mongo”. Uruchomi się powłoka Mongo, wprowadź następujące informacje.

use my_db

Zostanie utworzona nowa baza danych. Za każdym razem, gdy otworzysz powłokę Mongo, będzie ona domyślnie „testować” bazę danych i będziesz musiał przejść do swojej bazy danych za pomocą tego samego polecenia, co powyżej.

Aby użyć mongoose, będziemy wymagać tego w naszym pliku app.js, a następnie połączyć się z usługą mongod działającą na mongodb: // localhost

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

app.use(_.routes());
app.listen(3000);

Teraz nasza aplikacja jest połączona z naszą bazą danych, stwórzmy nowy Model. Ten model będzie działał jako zbiór w naszej bazie danych. Aby utworzyć nowy model, użyj poniższego kodu przed zdefiniowaniem jakichkolwiek tras.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

app.use(_.routes());
app.listen(3000);

Powyższy kod definiuje schemat osoby i służy do tworzenia modelu mangusty Person.

Zapisywanie dokumentów

Teraz utworzymy nowy formularz html, który pobierze dane osoby i zapisze ją w naszej bazie danych. Aby utworzyć formularz, utwórz nowy plik widoku o nazwie person.pug w katalogu views z następującą zawartością.

html
   head
      title Person
   body
      form(action = "/person", method = "POST")
         div
            label(for = "name") Name: 
            input(name = "name")
         br
         div
            label(for = "age") Age: 
            input(name = "age")
         br
         div
            label(for = "nationality") Nationality: 
            input(name = "nationality")
         br
         button(type = "submit") Create new person

Dodaj także nową trasę pobierania w index.js, aby renderować ten dokument.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.get('/person', getPerson);

function *getPerson(next){
   this.render('person');
   yield next;
}

app.use(_.routes());
app.listen(3000);

Idź do localhost: 3000 / osoba, aby sprawdzić, czy nasz formularz wyświetla się poprawnie. Zwróć uwagę, że to tylko interfejs użytkownika, jeszcze nie działa. Tak wygląda nasza forma.

Teraz zdefiniujemy procedurę obsługi trasy pocztowej w „/ person”, która będzie obsługiwać to żądanie.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.post('/person', createPerson);

function *createPerson(next){
   var self = this;
   var personInfo = self.request.body; //Get the parsed information
   
   if(!personInfo.name || !personInfo.age || !personInfo.nationality){
      self.render(
         'show_message', {message: "Sorry, you provided wrong info", type: "error"});
   } else {
      var newPerson = new Person({
         name: personInfo.name,
         age: personInfo.age,
         nationality: personInfo.nationality
      });
      yield newPerson.save(function(err, res) {
         if(err)
            self.render('show_message', 
               {message: "Database error", type: "error"});
         else
            self.render('show_message', 
               {message: "New person added", type: "success", person: personInfo});
      });
   }
}

app.use(_.routes());
app.listen(3000);

W powyższym kodzie, jeśli otrzymamy puste pole lub nie otrzymamy żadnego pola, wyślemy odpowiedź o błędzie. Jeśli jednak otrzymamy dobrze uformowany dokument, to tworzymy dokument newPerson z modelu Person i zapisujemy go do naszej bazy danych za pomocąnewPerson.save()funkcjonować. Jest to zdefiniowane w mongoose i akceptuje wywołanie zwrotne jako argument. To wywołanie zwrotne ma dwa argumenty,error i response. Spowoduje to wyświetlenie widoku show_message, więc musimy go również utworzyć.

Aby wyświetlić odpowiedź z tej trasy, będziemy również musieli utworzyć plik show_messagewidok. Utwórz nowy widok za pomocą następującego kodu.

html
   head
      title Person
   body
      if(type = "error")
         h3(style = "color:red") #{message}
      else
         h3 New person, name: 
            #{person.name}, age: 
            #{person.age} and nationality: 
            #{person.nationality} added!

Poniżej znajduje się odpowiedź, którą otrzymujemy po pomyślnym przesłaniu formularza (show_message.pug).

Mamy teraz interfejs do tworzenia osób!

Pobieranie dokumentów

Mongoose zapewnia wiele funkcji do pobierania dokumentów, skupimy się na trzech z nich. Wszystkie te funkcje również przyjmują wywołanie zwrotne jako ostatni parametr i podobnie jak funkcja save, ich argumentami są błąd i odpowiedź.

Te trzy funkcje to -

Model.find (warunki, wywołanie zwrotne)

Ta funkcja znajduje wszystkie dokumenty pasujące do pól w obiekcie warunków. Te same operatory używane w Mongo działają również w przypadku mangusty. Na przykład spowoduje to pobranie wszystkich dokumentów z kolekcji osób.

Person.find(function(err, response){
   console.log(response);
});

Spowoduje to pobranie wszystkich dokumentów, w których nazwa pola to „Ayush” i wiek to 20 lat.

Person.find({name: "Ayush", age: 20}, 
   function(err, response){
      console.log(response);
   });

Możemy również dostarczyć potrzebną nam projekcję, czyli potrzebne nam pola. Na przykład, jeśli chcemy tylkonames ludzi, których nationalityjest „indyjski” , używamy -

Person.find({nationality: "Indian"}, 
   "name", function(err, response) {
      console.log(response);
   });

Model.findOne (warunki, wywołanie zwrotne)

Ta funkcja zawsze pobiera pojedynczy, najbardziej odpowiedni dokument. Ma te same dokładne argumenty, co Model.find ().

Model.findById (id, wywołanie zwrotne)

Ta funkcja przyjmuje rozszerzenie _id(zdefiniowane przez mongo) jako pierwszy argument, opcjonalny łańcuch projekcji i wywołanie zwrotne do obsługi odpowiedzi. Na przykład,

Person.findById("507f1f77bcf86cd799439011", 
   function(err, response){
      console.log(response);
   });

Utwórzmy trasę, aby wyświetlić wszystkie rekordy osób.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.get('/people', getPeople);
function *getPeople(next){
   var self = this;
   
   yield Person.find(function(err, response){
      self.body = response;
   });
}
app.use(_.routes());
app.listen(3000);

Aktualizacja dokumentów

Mongoose zapewnia trzy funkcje aktualizacji dokumentów.

Model.update (stan, aktualizacje, oddzwonienie)

Ta funkcja przyjmuje warunek i aktualizuje obiekt jako dane wejściowe i stosuje zmiany do wszystkich dokumentów spełniających warunki w kolekcji. Na przykład poniższy kod zaktualizuje wszystkie dokumenty Person tak, aby miały obywatelstwo „amerykańskie”.

Person.update({age: 25},
   {nationality: "American"}, 
   function(err, response){
      console.log(response);
   });

Model.findOneAndUpdate (stan, aktualizacje, wywołanie zwrotne)

Robi dokładnie to, co mówi. Znajduje jeden dokument na podstawie zapytania i aktualizuje go zgodnie z drugim argumentem. Jako ostatni argument przyjmuje również callback. Na przykład,

Person.findOneAndUpdate({name: "Ayush"}, 
   {age: 40}, 
   function(err, response){
      console.log(response);
   });

Model.findByIdAndUpdate (identyfikator, aktualizacje, wywołanie zwrotne)

Ta funkcja aktualizuje pojedynczy dokument identyfikowany przez jego identyfikator. Na przykład,

Person.findByIdAndUpdate("507f1f77bcf86cd799439011", 
   {name: "James"}, 
   function(err, response){
      console.log(response);
   });

Stwórzmy trasę, aby zaktualizować ludzi. Będzie to trasa PUT z identyfikatorem jako parametrem i szczegółami w ładunku.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.put('/people/:id', updatePerson);

function *updatePerson() {
   var self = this;
   yield Person.findByIdAndUpdate(self.params.id, 
      {$set: {self.request.body}}, function(err, response){
      
      if(err) {
         self.body = {
            message: "Error in updating person with id " + self.params.id};
      } else {
         self.body = response;
      }
   });
}

app.use(_.routes());
app.listen(3000);

Aby przetestować tę trasę, wprowadź następujące informacje w swoim terminalu (zamień identyfikator na identyfikator utworzony przez Ciebie).

curl -X PUT --data "name = James&age = 20&nationality = American" https://localhost:3000/people/507f1f77bcf86cd799439011

Spowoduje to zaktualizowanie dokumentu związanego z identyfikatorem podanym w trasie o powyższe szczegóły.

Usuwanie dokumentów

Omówiliśmy CReate, Read i Update, teraz zobaczymy, jak mangusta może być używana do usuwania dokumentów. Są tutaj trzy funkcje, dokładnie takie jak aktualizacja.

Model.remove (warunek, [wywołanie zwrotne])

Ta funkcja przyjmuje obiekt warunku jako dane wejściowe i usuwa wszystkie dokumenty spełniające warunki. Na przykład, jeśli musimy usunąć wszystkie osoby w wieku 20 lat,

Person.remove({age:20});

Model.findOneAndRemove (warunek, [wywołanie zwrotne])

Ta funkcja usuwa plik single, najbardziej odpowiedni dokument według warunków obiektu. Na przykład,

Person.findOneAndRemove({name: "Ayush"});

Model.findByIdAndRemove (id, [wywołanie zwrotne])

Ta funkcja usuwa pojedynczy dokument określony przez jego identyfikator. Na przykład,

Person.findByIdAndRemove("507f1f77bcf86cd799439011");

Teraz stwórzmy trasę do usuwania osób z naszej bazy danych.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.delete('/people/:id', deletePerson);
function *deletePerson(next){
   var self = this;
   yield Person.findByIdAndRemove(self.params.id, function(err, response){
      if(err) {
         self.body = {message: "Error in deleting record id " + self.params.id};
      } else {
         self.body = {message: "Person with id " + self.params.id + " removed."};
      }
   });
}

app.use(_.routes());
app.listen(3000);

Aby to sprawdzić, użyj następującego polecenia curl -

curl -X DELETE https://localhost:3000/people/507f1f77bcf86cd799439011

Spowoduje to usunięcie osoby o podanym identyfikatorze i wygenerowanie następującego komunikatu. -

{message: "Person with id 507f1f77bcf86cd799439011 removed."}

To podsumowuje, jak możemy tworzyć proste aplikacje CRUD przy użyciu MongoDB, Mongoose i Koa. Aby dokładniej zbadać mangustę, przeczytaj dokumentację API.

Aby tworzyć aplikacje mobilne, aplikacje jednostronicowe, używać wywołań AJAX i dostarczać dane klientom, potrzebujesz interfejsu API. Popularny styl architektoniczny określający strukturę i nazywanie tych interfejsów API i punktów końcowych jest nazywanyREST(Representational Transfer State). Protokół HTTP 1.1 został zaprojektowany z myślą o zasadach REST. REST został wprowadzony przezRoy Fielding w 2000 roku w swojej pracy Fielding Dissertations.

RESTful URI i metody dostarczają nam prawie wszystkich informacji potrzebnych do przetworzenia żądania. Poniższa tabela zawiera podsumowanie, w jaki sposób należy używać różnych czasowników i jak nazywać identyfikatory URI. Pod koniec będziemy tworzyć API filmów, więc omówmy, jak będzie ono zbudowane.

metoda URI Detale Funkcjonować
DOSTAĆ /kino Bezpieczny, podłączany Pobiera listę wszystkich filmów i ich szczegóły
DOSTAĆ / filmy / 1234 Bezpieczny, podłączany Pobiera szczegóły identyfikatora filmu 1234
POCZTA /kino Nie dotyczy Tworzy nowy film z podanymi szczegółami. Odpowiedź zawiera identyfikator URI dla tego nowo utworzonego zasobu.
POŁOŻYĆ / filmy / 1234 Idempotent Modyfikuje identyfikator filmu 1234 (tworzy go, jeśli jeszcze nie istnieje). Odpowiedź zawiera identyfikator URI dla tego nowo utworzonego zasobu.
USUNĄĆ / filmy / 1234 Idempotent Identyfikator filmu 1234 powinien zostać usunięty, jeśli istnieje. Odpowiedź powinna zawierać status zapytania.
DELETE lub PUT /kino Nieważny Powinien być nieważny. DELETE i PUT powinny określać, nad którym zasobem pracują.

Teraz stwórzmy to API w Koa. Będziemy używać JSON jako formatu danych transportowych, ponieważ jest łatwy w obsłudze w JavaScript i ma wiele innych zalet. Zastąp plik index.js następującym -

INDEX.JS

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');

var app = koa();

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

//Require the Router we defined in movies.js
var movies = require('./movies.js');

//Use the Router on the sub route /movies
app.use(movies.routes());

app.listen(3000);

Teraz, gdy mamy już skonfigurowaną aplikację, skoncentrujmy się na tworzeniu API. Najpierw skonfiguruj plik movies.js. Nie używamy bazy danych do przechowywania filmów, ale przechowujemy je w pamięci, więc za każdym razem, gdy serwer uruchamia się ponownie, dodane przez nas filmy znikają. Można to łatwo naśladować za pomocą bazy danych lub pliku (przy użyciu modułu node fs).

Importuj router koa, utwórz router i wyeksportuj go za pomocą module.exports.

var Router = require('koa-router');
var router = Router({
  prefix: '/movies'
});  //Prefixed all routes with /movies

var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];

//Routes will go here

module.exports = router;

POBIERZ trasy

Zdefiniuj trasę GET, aby pobrać wszystkie filmy.

router.get('/', sendMovies);
function *sendMovies(next){
   this.body = movies;
   yield next;
}

Otóż ​​to. Aby sprawdzić, czy to działa dobrze, uruchom aplikację, a następnie otwórz terminal i wpisz -

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies

Otrzymasz następującą odpowiedź -

[{"id":101,"name":"Fight 
Club","year":1999,"rating":8.1},{"id":102,"name":"Inception","year":2010,"rating":8.7},
{"id":103,"name":"The Dark Knight","year":2008,"rating":9},{"id":104,"name":"12 Angry 
Men","year":1957,"rating":8.9}]

Mamy trasę, aby zdobyć wszystkie filmy. Teraz stwórzmy trasę, aby uzyskać określony film według jego identyfikatora.

router.get('/:id([0-9]{3,})', sendMovieWithId);

function *sendMovieWithId(next){
   var ctx = this;
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}

W ten sposób otrzymamy filmy zgodnie z podanym przez nas identyfikatorem. Aby to przetestować, użyj następującego polecenia w swoim terminalu.

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies/101

Otrzymasz odpowiedź jako -

{"id":101,"name":"Fight Club","year":1999,"rating":8.1}

Jeśli odwiedzisz nieprawidłową trasę, wygeneruje błąd nie można GET, a jeśli odwiedzisz prawidłową trasę z nieistniejącym identyfikatorem, spowoduje to błąd 404.

Skończyliśmy z trasami GET. Teraz przejdźmy do trasy POST.

POST Route

Użyj następującej trasy, aby obsłużyć przesłane dane.

router.post('/', addNewMovie);

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}

Spowoduje to utworzenie nowego filmu i zapisanie go w zmiennej movies. Aby przetestować tę trasę, wprowadź w terminalu:

curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://localhost:3000/movies

Otrzymasz następującą odpowiedź -

{"message":"New movie created.","location":"/movies/105"}

Aby sprawdzić, czy został on dodany do obiektu movies, uruchom ponownie żądanie pobierania dla / movies / 105. Otrzymasz następującą odpowiedź -

{"id":105,"name":"Toy story","year":"1995","rating":"8.5"}

Przejdźmy dalej, aby utworzyć trasy PUT i DELETE.

PUT Route

Trasa PUT jest prawie dokładnie taka sama jak trasa POST. Będziemy określać identyfikator obiektu, który zostanie zaktualizowany / utworzony. Utwórz trasę w następujący sposób -

router.put('/:id', updateMovieWithId);

function *updateMovieWithId(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};    
      } else {
         //Update existing movie
         movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", location: "/movies/" + this.params.id};
      }
   }
}

Ta trasa będzie spełniać funkcję, którą określiliśmy w powyższej tabeli. Zaktualizuje obiekt o nowe szczegóły, jeśli istnieje. Jeśli nie istnieje, utworzy nowy obiekt. Aby przetestować tę trasę, użyj następującego polecenia curl. Spowoduje to zaktualizowanie istniejącego filmu. Aby utworzyć nowy film, po prostu zmień identyfikator na nieistniejący.

curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://localhost:3000/movies/101

Odpowiedź

{"message":"Movie id 101 updated.","location":"/movies/101"}

USUŃ trasę

Użyj poniższego kodu, aby utworzyć trasę usuwania.

router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

Przetestuj trasę w taki sam sposób, jak dla pozostałych. Po pomyślnym usunięciu (na przykład id 105) otrzymasz -

{message: "Movie id 105 removed."}

Wreszcie nasz plik movies.js wygląda następująco -

var Router = require('koa-router');
var router = Router({
   prefix: '/movies'
});  //Prefixed all routes with /movies
var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];

//Routes will go here
router.get('/', sendMovies);
router.get('/:id([0-9]{3,})', sendMovieWithId);
router.post('/', addNewMovie);
router.put('/:id', updateMovieWithId);
router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

function *updateMovieWithId(next) {
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new
         movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};
      } else {
         //Update existing movie
            movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", 
            location: "/movies/" + this.params.id};
      }
   }
}

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}
function *sendMovies(next){
   this.body = movies;
   yield next;
}
function *sendMovieWithId(next){
   var ctx = this
   
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}
module.exports = router;

To kończy nasze REST API. Teraz możesz tworzyć znacznie bardziej złożone aplikacje, korzystając z tego prostego stylu architektonicznego i Koa.

Rejestrowanie jest bardzo przydatne podczas tworzenia aplikacji internetowych, ponieważ informuje nas, gdzie dokładnie coś poszło nie tak. Dostajemy również kontekst dla rzeczy, które poszły nie tak i możemy wymyślić możliwe rozwiązania tego samego.

Aby umożliwić logowanie w Koa, potrzebujemy oprogramowania pośredniego, koa-logger. Zainstaluj go za pomocą następującego polecenia.

$ npm install --save-dev koa-logger

Teraz w aplikacji dodaj następujący kod, aby włączyć rejestrowanie.

var logger = require('koa-logger')
var koa = require('koa')

var app = koa()
app.use(logger())

app.use(function*(){
   this.body = "Hello Logger";
})

app.listen(3000)

Uruchom ten serwer i odwiedź dowolną trasę na serwerze. Powinieneś zobaczyć dzienniki takie jak -

Teraz, jeśli pojawi się błąd dotyczący określonej trasy lub żądania, te dzienniki powinny pomóc Ci dowiedzieć się, co poszło nie tak w każdym z nich.

Rusztowanie pozwala nam w łatwy sposób stworzyć plik skeleton for a web application. Ręcznie utworzyliśmy nasz katalog publiczny, dodaliśmy oprogramowanie pośrednie, utworzyliśmy oddzielne pliki tras itp. Narzędzie do tworzenia szkieletów konfiguruje za nas wszystkie te elementy, abyśmy mogli bezpośrednio rozpocząć tworzenie naszej aplikacji.

Rusztowanie, którego będziemy używać, nazywa się Yeoman. Jest to narzędzie do tworzenia szkieletów zbudowane dla Node.js, ale ma również generatory dla kilku innych frameworków (takich jak flask, rails, django itp.). Aby zainstalować yeoman, wprowadź następujące polecenie w swoim terminalu.

$ npm install -g yeoman

Yeoman używa generatorów do tworzenia szkieletów aplikacji. Aby sprawdzić generatory dostępne na npm do użytku z yeoman, udaj się tutaj . Na potrzeby tego samouczka użyjemy 'generator-koa'. Aby zainstalować ten generator, wprowadź następujące polecenie w swoim terminalu.

$ npm install -g generator-koa

Aby użyć tego generatora, wprowadź -

yo koa

Następnie utworzy strukturę katalogów i utworzy dla Ciebie następujące pliki. Zainstaluje również niezbędne moduły npm i komponenty altany.

create package.json
create test/routeSpec.js
create views/layout.html
create views/list.html
create public/styles/main.css
create public/scripts/.gitkeep
create controllers/messages.js
create app.js
create .editorconfig
create .jshintrc

I'm all done. Running npm install & bower install for you to install 
the required dependencies. 
If this fails, try running the command yourself.

Ten generator tworzy dla nas bardzo prostą strukturę.

.
├── controllers
│   └── messages.js
├── public
|   ├── scripts
|   └── styles
|       └── main.css    
├── test
|   └── routeSpec.js
├── views
|   ├── layout.html
|   └── list.html
├── .editorconfig
├── .jshintrc
├── app.js
└── package.json

Poznaj wiele generatorów dostępnych dla Koa i wybierz ten, który pasuje do Ciebie. Kroki do pracy ze wszystkimi generatorami są takie same. Musisz zainstalować generator, uruchomić go za pomocą programu yeoman, zada Ci kilka pytań, a następnie utworzy szkielet aplikacji na podstawie Twoich odpowiedzi.

Poniżej znajduje się lista zasobów, z których korzystaliśmy podczas opracowywania tego samouczka -

  • Koajs.com

  • Koajs - Przykłady Lista przykładów stworzonych przez społeczność

  • Lista oficjalnych i 3 rd middleware producentów.

  • CRUD API przy użyciu koa.js - krótki screencast, który przechodzi przez tworzenie CRUD API w Koa.js

  • Prezentacja ekranowa Szybki start Koa.js

  • Wprowadzenie do Koa.js i generatorów