Koajs-quick-guide

提供:Dev Guides
移動先:案内検索

Koa.js-概要

Webアプリケーションフレームワークは、Webサイト、Webアプリ、およびバックエンドを構築するためのシンプルなAPIを提供します。 低レベルのプロトコル、プロセスなどを心配する必要はありません。

コアとは?

Koaは、アプリケーションを構築するための最小限のインターフェースを提供します。 これは非常に小さなフレームワーク(600 LoC)であり、アプリを構築するために必要なツールを提供し、非常に柔軟です。 Koaのnpmには多数のモジュールがあり、直接プラグインできます。 Koaは、すべての機能を備えていないexpress.jsのコアと考えることができます。

なぜコア?

Koaのフットプリントは小さく(600 LoC)、サーバーサイドアプリを作成するためのノード上の抽象化の非常に薄い層です。 完全にプラグイン可能で、巨大なコミュニティがあります。 これにより、Koaを簡単に拡張し、ニーズに応じて使用することもできます。 最先端のテクノロジー(ES6)を使用して構築されており、Expressなどの古いフレームワークよりも優れています。

Pug

Pug(以前のJade)は、HTMLテンプレートを記述するための簡潔な言語です。

  • HTMLを生成します
  • 動的コードをサポート
  • 再利用性をサポート(DRY)

これは、Koaで使用される最も人気のあるテンプレート言語の1つです。

MongoDBおよびMongoose

MongoDBは、開発とスケーリングを容易にするために設計されたオープンソースのドキュメントデータベースです。 このデータベースを使用してデータを保存します。

Mongooseは、Koaアプリケーションからデータベースに簡単にアクセスできるようにするnode.jsのクライアントAPIです。

Koa.js-環境

Koaフレームワークを使用した開発を開始するには、Nodeおよびnpm(ノードパッケージマネージャー)をインストールする必要があります。 これらがまだない場合は、link:/nodejs/nodejs_environment_setup [Node setup]にアクセスして、ローカルシステムにノードをインストールします。 ターミナルで次のコマンドを実行して、ノードとnpmがインストールされていることを確認します。

$ node --version
$ npm --version

次のような出力を受け取るはずです-

v5.0.0
3.5.2

ノードのバージョンが6.5.0以上であることを確認してください。 Nodeとnpmがセットアップされたので、npmとは何か、どのように使用するかを理解しましょう。

Node Package Manager(npm)

npmはノードのパッケージマネージャーです。 npm Registryは、Node.js、フロントエンドWebアプリ、モバイルアプリ、ロボット、ルーター、およびJavaScriptコミュニティの無数の他のニーズのためのオープンソースコードのパッケージのパブリックコレクションです。 npmを使用すると、これらすべてのパッケージにアクセスしてローカルにインストールできます。 https://www.npmjs.org [npmJS]のnpmで利用可能なパッケージのリストを参照できます。

npmの使用方法

npmを使用してパッケージをインストールするには、グローバルとローカルの2つの方法があります。

グローバル-この方法は通常、開発ツールとCLIベースのパッケージをインストールするために使用されます。 パッケージをグローバルにインストールするには、次のコマンドを使用します。

$ npm install -g <package-name>

ローカル-この方法は、通常、フレームワークとライブラリをインストールするために使用されます。 ローカルにインストールされたパッケージは、インストールされているディレクトリ内でのみ使用できます。 パッケージをローカルにインストールするには、-* g *フラグなしで上記と同じコマンドを使用します。

$ npm install <package-name>

npmを使用してプロジェクトを作成するたびに、package.jsonファイルを提供する必要があります。このファイルには、プロジェクトに関するすべての詳細が含まれています。 npmを使用すると、このファイルを簡単にセットアップできます。 開発プロジェクトをセットアップしましょう。

  • ステップ1 *-ターミナル/cmdを起動し、hello-worldという名前の新しいフォルダーを作成し、そこにcdします-

環境mkdir

  • ステップ2 *-npmを使用してpackage.jsonファイルを作成するには、次を使用します。
npm init

次の情報を求められます-

環境NPM

Enterキーを押し続け、[著者名]フィールドに名前を入力します。

  • ステップ3 *-package.jsonファイルが設定されたので、Koaをインストールします。 Koaをインストールしてpackage.jsonファイルに追加するには、次のコマンドを使用します。
$ npm install --save koa

Koaが正しくインストールされていることを確認するには、次のコマンドを実行します。

$ ls node_modules #(dir node_modules for windows)

ヒント--save *フラグは *-S フラグに置き換えることができます。 このフラグにより​​、package.jsonファイルにKoaが依存関係として追加されます。 これには利点があります。次回プロジェクトのすべての依存関係をインストールする必要があるときは、コマンドnpm installを実行するだけで、このファイルで依存関係を見つけてインストールします。

Koaフレームワークを使用して開発を開始するために必要なのはこれだけです。 開発プロセスを非常に簡単にするために、npm、nodemonからツールをインストールします。 このツールは、ファイルに変更を加えるとすぐにサーバーを再起動します。それ以外の場合は、ファイルを変更するたびにサーバーを手動で再起動する必要があります。 nodemonをインストールするには、次のコマンドを使用します。

$ npm install -g nodemon

これで、コアに飛び込む準備ができました!

Koa.js-Hello World

開発をセットアップしたら、Koaを使用して最初のアプリの開発を開始します。 app.js という新しいファイルを作成し、次のように入力します。

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')
});

ファイルを保存し、ターミナルに移動して入力します。

$ nodemon app.js

これによりサーバーが起動します。 このアプリをテストするには、ブラウザを開いて [[1]] にアクセスすると、次のメッセージが表示されます。

Hello world

このアプリの仕組み

最初の行は、ファイルにKoaをインポートします。 変数Koaを介してAPIにアクセスできます。 これを使用してアプリケーションを作成し、var appに割り当てます。

  • app.use(function)-この関数はミドルウェアであり、サーバーがリクエストを受け取るたびに呼び出されます。 ミドルウェアの詳細については、後続の章で説明します。 コールバック関数はジェネレーターです。これについては次の章で説明します。 このジェネレーターのコンテキストは、Koaではコンテキストと呼ばれます。 このコンテキストは、要求および応答オブジェクトにアクセスして変更するために使用されます。 この応答の本文を Hello world!*に設定しています。
  • app.listen(port、function)*-この関数は、指定されたポートで接続をバインドしてリッスンします。 ここでは、ポートが唯一の必須パラメーターです。 アプリが正常に実行されると、コールバック関数が実行されます。

Koa.js-ジェネレーター

JavaScript ES6の最もエキサイティングな新機能の1つは、ジェネレーターと呼ばれる新しい種類の機能です。 ジェネレーターの前は、通常、スクリプト全体を使用して上から下の順序で実行していましたが、コードの実行を停止して後で同じスタックで再開する簡単な方法はありませんでした。 ジェネレータは、終了して後で再入力できる関数です。 それらのコンテキスト(変数バインディング)は、再入可能に保存されます。

ジェネレーターを使用すると、その間にコードの実行を停止できます。 したがって、単純なジェネレーターを見てみましょう。

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

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

上記のコードを実行すると、結果は次のようになります。

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

上記のコードの内部を見てみましょう。 まず、* generator_func()というジェネレーターを作成します。 この奇妙な関数のインスタンスを作成し、それを *itr に割り当てました。 次に、このitr変数で* next()*の呼び出しを開始しました。

next()を呼び出すと、ジェネレーターが起動し、yieldに達するまで実行されます。 次に、値と完了のオブジェクトを返します。値には式の値があります。 この式は何でも構いません。 この時点で、実行を一時停止します。 再びこの関数(next)を呼び出すと、ジェネレーターは、一時停止の時点で関数の状態が同じである最後の降伏点から次の降伏点まで実行を再開します。 これは、コードに降伏点がなくなるまで行われます。

コアの発電機

それでは、なぜこのチュートリアルでジェネレーターについて説明するのでしょうか。 hello worldプログラムでおわかりのように、 function ()*表記を使用してコールバックをapp.use()に渡しました。 Koaは、ミドルウェアジェネレーター関数の配列を含むオブジェクトです。これらの関数はすべて、リクエストごとにスタックのような方法で構成および実行されます。 Koaは、制御フローのダウンストリーム化とそれに続くアップストリーム化も実装しています。

これをより良い方法で理解するには、次の例を見てください。

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);

上記のコードを実行して [[2]] に移動すると、コンソールに次の出力が表示されます。

1
3
5
6
4
2

これは、本質的にKoaがジェネレーターを使用する方法です。 このプロパティを使用してコンパクトなミドルウェアを作成し、アップストリームとダウンストリームの両方の機能のコードを記述することができるため、コールバックを回避できます。

Koa.js-ルーティング

Webフレームワークは、HTMLページ、スクリプト、画像などのリソースを提供します。 異なるルートで。 Koaは、コアモジュールのルートをサポートしていません。 Koaでルートを簡単に作成するには、Koa-routerモジュールを使用する必要があります。 次のコマンドを使用してこのモジュールをインストールします。

npm install --save koa-router

Koa-routerがインストールされたので、簡単な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);

アプリケーションを実行してlocalhost:3000/helloに移動すると、サーバーはルート "/hello"でget要求を受け取ります。 Koaアプリは、このルートにアタッチされたコールバック関数を実行し、「Hello World!」を送信します応答として。

こんにちはルーティング

同じルートで複数の異なるメソッドを使用することもできます。 例えば、

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);

このリクエストをテストするには、ターミナルを開き、cURLを使用して次のリクエストを実行します

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

カールルーティング

同じ関数を使用して特定のルートですべてのタイプのhttpメソッドを処理するために、特別なメソッド all がexpressによって提供されます。 この方法を使用するには、次を試してください-

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

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

Koa.js-URL構築

ルートを定義できるようになりました。それらは静的または固定です。 動的ルートを使用するには、さまざまなタイプのルートを提供する必要があります。 動的ルートを使用すると、パラメーターを渡し、それらに基づいて処理することができます。 以下は、動的ルートの例です。

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);

これをテストするには、 [[3]] に移動します。 次の応答が返されます。

URLビルID

URLの「123」を他のものに置き換えると、応答に反映されます。 以下は、上記の複雑な例です。

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);

これをテストするには、 [[4]] にアクセスします。

URL Building Complex

*_this.params_* オブジェクトを使用して、URLで渡すすべてのパラメーターにアクセスできます。 上記の2つのパスは異なることに注意してください。 重複することはありません。 また、「/things」を取得したときにコードを実行する場合は、個別に定義する必要があります。

パターン一致ルート

正規表現を使用して、URLパラメーターの一致を制限することもできます。 idが5桁の長さである必要があるとしましょう。 次のルート定義を使用できます。

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);

これは、5桁の長いIDを持つリクエストにのみ*一致*することに注意してください。 より複雑な正規表現を使用して、ルートを照合/検証できます。 リクエストに一致するルートがない場合、応答としてNot foundメッセージが表示されます。

たとえば、上記と同じルートを定義した場合、有効なURLで要求すると、次のようになります-

URLマッチングが正しい

Koa.js-HTTPメソッド

HTTPメソッドは要求で提供され、クライアントが要求した操作を指定します。 次の表は、一般的に使用されるHTTPメソッドをまとめたものです。

Sr.No. Method & Description
1

GET

GETメソッドは、指定されたリソースの表現を要求します。 GETを使用したリクエストはデータを取得するだけで、他の効果はありません。

2

POST

POSTメソッドは、URIで識別されるリソースの新しいオブジェクト/エンティティとして、リクエストに含まれるデータをサーバーが受け入れることをリクエストします。

3

PUT

PUTメソッドは、URIで識別される既存のオブジェクトへの変更として、リクエストに含まれるデータをサーバーが受け入れることをリクエストします。 存在しない場合は、PUTメソッドで作成する必要があります。

4

DELETE

DELETEメソッドは、サーバーが指定されたリソースを削除することを要求します。

これらは最も一般的なHTTPメソッドです。 それらの詳細については、link:/http/http_methods [https://www.finddevguides.com/http/http_methods]にアクセスしてください。

Koa.js-リクエストオブジェクト

Koa Requestオブジェクトは、ノードのバニラリクエストオブジェクトの上にある抽象化であり、日常のHTTPサーバー開発に役立つ追加機能を提供します。 Koaリクエストオブジェクトは、コンテキストオブジェクト this に埋め込まれています。 リクエストを取得するたびにリクエストオブジェクトをログアウトしましょう。

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);

このコードを実行して [[5]] に移動すると、次の応答が返されます。

リクエストオブジェクト

コンソールで、リクエストオブジェクトがログアウトされます。

{
   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'
   }
}

このオブジェクトを使用して、リクエストの多くの有用なプロパティにアクセスできます。 いくつかの例を見てみましょう。

request.header

すべての要求ヘッダーを提供します。

request.method

要求メソッドを提供します(GET、POSTなど)

request.href

完全なリクエストURLを提供します。

request.path

要求のパスを提供します。 クエリ文字列とベースURLなし。

request.query

解析されたクエリ文字列を提供します。 たとえば、 [[6]] = Ayush&age = 20&country = India などのリクエストでこれを記録すると、次のオブジェクトが取得されます。

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

request.accepts(type)

この関数は、要求されたリソースが指定された要求タイプを受け入れるかどうかに基づいて、trueまたはfalseを返します。

リクエストオブジェクトの詳細については、http://koajs.com/#request [Request]のドキュメントをご覧ください。

Koa.js-応答オブジェクト

Koa Responseオブジェクトは、ノードのバニラ応答オブジェクトの上にある抽象化であり、日常のHTTPサーバー開発に役立つ追加機能を提供します。 Koa応答オブジェクトは、コンテキストオブジェクト this に埋め込まれています。 リクエストを取得するたびにレスポンスオブジェクトをログアウトしましょう。

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);

このコードを実行して [[7]] に移動すると、次の応答が返されます。

リクエストオブジェクト

コンソールで、リクエストオブジェクトがログアウトされます。

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

ステータスとメッセージはKoaによって自動的に設定されますが、当社が変更できます。 応答本文を設定しない場合、ステータスコードは404に設定されます。 応答本文を設定すると、ステータスはデフォルトで200に設定されます。 この動作を明示的にオーバーライドできます。

このオブジェクトを使用して、応答の多くの有用なプロパティにアクセスできます。 私たちはいくつかの例を見てみましょう-

response.header

すべての応答ヘッダーを提供します。

response.status

応答ステータス(200、404、500など)を提供します。 このプロパティは、応答ステータスの設定にも使用されます。

response.message

応答メッセージを提供します。 このプロパティは、応答付きのカスタムメッセージを設定するためにも使用されます。 response.statusに関連付けられています。

response.body

応答本文を取得または設定します。 通常、コンテキストオブジェクトを使用してアクセスします。 これは、アクセスするための別の方法です。 本体のタイプは、String、Buffer、Stream、Object、またはNullです。

response.type

現在の応答のコンテンツタイプを取得または設定します。

response.get(field)

この関数は、大文字と小文字を区別しない値フィールドを持つヘッダーの値を取得するために使用されます。

response.set(フィールド、値)

この関数は、フィールドと値のペアを使用して応答にヘッダーを設定するために使用されます。

response.remove(field)

この関数は、フィールド名を使用して応答のヘッダーを設定解除するために使用されます。

応答オブジェクトの詳細については、http://koajs.com/#response [Response]のドキュメントをご覧ください。

Koa.js-リダイレクト

Webサイトを作成する場合、リダイレクトは非常に重要です。 不正な形式のURLが要求された場合、またはサーバーにエラーがある場合は、それらをそれぞれのエラーページにリダイレクトする必要があります。 リダイレクトを使用して、Webサイトの制限された領域から人々を遠ざけることもできます。

エラーページを作成し、誰かが不正な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);

このコードを実行して/hello以外のルートに移動すると、/not_foundにリダイレクトされます。 ミドルウェアを最後に配置しました(このミドルウェアのapp.use関数呼び出し)。 これにより、最終的にミドルウェアに到達し、対応する応答を送信します。 上記のコードを実行すると、次の結果が表示されます。

*https://localhost:3000/hello* に移動すると、次のようになります-

Redirect Hello

私たちが他のルートにナビゲートすると、私たちは得る-

リダイレクトエラー

Koa.js-エラー処理

エラー処理は、Webアプリケーションの構築において重要な役割を果たします。 Koaはこの目的にもミドルウェアを使用します。

Koaでは、最初のミドルウェアの1つとして\ try yield next **を行うミドルウェアを追加します。 ダウンストリームでエラーが発生した場合は、関連するcatch句に戻り、ここでエラーを処理します。 たとえば-

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);

上記のコードで意図的にエラーを作成し、最初のミドルウェアのcatchブロックでエラーを処理しています。 これは、コンソールに送信されるとともに、クライアントへの応答として送信されます。 以下は、このエラーをトリガーしたときに表示されるエラーメッセージです。

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

現在、サーバーに送信されたリクエストはすべてこのエラーになります。

Koa.js-カスケード

ミドルウェア関数は、コンテキストオブジェクト*およびアプリケーションの要求/応答サイクルの次のミドルウェア関数にアクセスできる関数です。 これらの関数は、リクエストボディの解析、レスポンスヘッダーの追加などのタスクのリクエストおよびレスポンスオブジェクトを変更するために使用されます。 Koaはさらに一歩進んで *'downstream' を生成し、コントロールを 'upstream' に戻します。 この効果は「カスケード」と呼ばれます。

以下は、実行中のミドルウェア関数の簡単な例です。

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);

上記のミドルウェアは、サーバー上のすべての要求に対して呼び出されます。 したがって、すべてのリクエストの後に、コンソールに次のメッセージが表示されます。

A new request received at 1467267512545

特定のルート(およびそのすべてのサブルート)に制限するには、ルーティングで行ったようにルートを作成するだけです。 実際、これらのミドルウェアはリクエストを処理するだけです。

例えば、

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);

これで、 '/request’のサブルートを要求するたびに、時間を記録します。

ミドルウェア呼び出しの順序

Koaのミドルウェアに関する最も重要なことの1つは、ミドルウェアがファイルに書き込まれる/ファイルに含まれる順序が、ダウンストリームで実行される順序であることです。 ミドルウェアでyieldステートメントに到達するとすぐに、最後に到達するまで、次のミドルウェアに順番に切り替わります。 それから再び、yieldステートメントから関数の再開と再開を開始します。

たとえば、次のコードスニペットでは、最初の関数が最初にyieldまで実行され、次に2番目のミドルウェアがyieldまで実行され、次に3番目が実行されます。 ここにミドルウェアはもうないので、逆に、つまり3番目、2番目、1番目の順序で実行を開始します。 この例では、ミアウェアを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);

このコードを実行した後に「/」にアクセスすると、コンソールで次のようになります-

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.

次の図は、上記の例で実際に起こっていることを要約しています。

ミドルウェアの説明

独自のミドルウェアの作成方法がわかったので、最も一般的に使用されるコミュニティ作成ミドルウェアのいくつかについて説明しましょう。

サードパーティのミドルウェア

Express用のサードパーティミドルウェアのリストはhttps://github.com/koajs/koa/wiki[here。]で入手できます。以下は、最も一般的に使用されるミドルウェアの一部です-

  • コアボディパーサー
  • コアルーター
  • コアスタティック
  • コア圧縮

後続の章で複数のミドルウェアについて説明します。

Koa.js-テンプレート

パグはテンプレートエンジンです。 テンプレートエンジンは、サーバーコードがHTMLで乱雑になるのを防ぎ、文字列を既存のHTMLテンプレートに乱暴に連結するために使用されます。 Pugは非常に強力なテンプレートエンジンで、 filters、includes、inheritance、interpolation などのさまざまな機能を備えています。 これには多くの根拠があります。

KoaでPugを使用するには、次のコマンドを使用してインストールする必要があります。

$ npm install --save pug koa-pug

パグをインストールしたら、アプリのテンプレートエンジンとして設定します。 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);

次に、viewsという名前の新しいディレクトリを作成します。 ディレクトリ内で、first_view.pugという名前のファイルを作成し、次のデータを入力します。

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

このページを実行するには、アプリに次のルートを追加します。

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

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

あなたはとして出力を受け取るでしょう-

こんにちはビュー

Pugが行うことは、この非常にシンプルなマークアップをHTMLに変換することです。 タグを閉じるのを追跡する必要はありません。クラスやidキーワードを使用する必要はなく、「。」を使用しますそして、それらを定義する「#」。 上記のコードは最初に変換されます

<!DOCTYPE html>
<html>
   <head>
      <title>Hello Pug</title>
   </head>

   <body>
      <p class = "greetings" id = "people">Hello Views!</p>
   </body>
</html>

Pugは、HTMLマークアップを単純化するだけではありません。 Pugのこれらの機能のいくつかを見てみましょう。

シンプルなタグ

タグは、インデントに従ってネストされます。 上記の例のように、 <title><head> タグ内でインデントされているため、その中にありました。 ただし、 <body> タグは同じインデントにあるため、 <head> タグの兄弟でした。

タグを閉じる必要はありません。 Pugは、同じまたは外側のインデントレベルで次のタグに遭遇するとすぐに、タグを閉じます。

タグ内にテキストを配置する3つの方法があります-

  • スペース区切り-
h1 Welcome to Pug
  • パイプテキスト-
div
   | To insert multiline text,
   | You can use the pipe operator.
*テキストのブロック-
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.

コメント

PugはJavaScript(//)と同じ構文を使用してコメントを作成します。 これらのコメントはhtmlコメントに変換されます(<!-comment→)。 例えば、

//This is a Pug comment

このコメントは次のように変換されます-

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

属性

属性を定義するには、属性のカンマ区切りリストを括弧で囲んで使用します。 クラスおよびID属性には特別な表現があります。 次のコード行は、特定のhtmlタグの属性、クラス、およびIDの定義をカバーしています。

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

このコード行は、に変換されます-

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

テンプレートに値を渡す

Pugテンプレートをレンダリングするとき、実際にルートハンドラーから値を渡すことができ、テンプレートで使用できます。 次のコードで新しいルートハンドラーを作成します。

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: "finddevguides",
      url:"https://www.finddevguides.com"
   });
};

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

次に、次のコードを使用して、viewsディレクトリにdynamic.pugという名前の新しいビューファイルを作成します。

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

ブラウザで localhost:3000/dynamic を開くと、以下が出力されます。 −

テンプレート変数

これらの渡された変数をテキスト内で使用することもできます。 渡された変数をタグのテキスト間に挿入するには、#\ {variableName}構文を使用します。 たとえば、上記の例でfinddevguidesからの挨拶を挿入する場合は、次のコードを使用する必要があります。

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

値を使用するこの方法は、補間と呼ばれます。

条件付き

条件ステートメントとループ構造も使用できます。 ユーザーがログインしている場合は「Hi、User」を表示し、そうでない場合は「ログイン/サインアップ」リンクを表示したいという実用的な例を考えてみましょう。 これを達成するために、次のような単純なテンプレートを定義できます-

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

ルートを使用してこれをレンダリングし、次のようなオブジェクトを渡す場合-

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

Hi、Ayushを表示するメッセージが表示されます。 ただし、オブジェクトを渡さない場合、またはユーザーキーを持たないオブジェクトを渡さない場合は、サインアップリンクを取得します。

含めるとコンポーネント

Pugは、Webページのコンポーネントを作成する非常に直感的な方法を提供します。 たとえば、ニュースWebサイトが表示された場合、ロゴとカテゴリのヘッダーは常に修正されます。 それをすべてのビューにコピーする代わりに、インクルードを使用できます。 次の例は、インクルードの使用方法を示しています-

次のコードで3つのビューを作成します-

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.

このためのルートを次のように作成します。

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);
*localhost:3000/components* に移動すると、次の出力が表示されます。

テンプレートのコンポーネント

*_include_* は、プレーンテキスト、CSS、およびJavaScriptを含めるためにも使用できます。

Pugには他にも多くの機能があります。 ただし、これらはこのチュートリアルの範囲外です。 パグについては、http://jade-lang.com [Pug]でさらに詳しく調べることができます。

Koa.js-フォームデータ

フォームはWebの不可欠な部分です。 私たちが訪問するほとんどすべてのウェブサイトは、私たちのために情報を送信または取得するフォームを提供します。 フォームを開始するには、まずkoa-bodyをインストールします。 これをインストールするには、ターミナルに移動して使用します-

$ npm install --save koa-body

app.jsファイルの内容を次のコードに置き換えます。

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);

ここで行っている新しいことは、ボディパーサーとmulterのインポートです。 jsonおよびx-www-form-urlencodedヘッダーリクエストの解析にはbodyパーサーを使用し、multipart/form-dataの解析にはmulterを使用しています。

これをテストするためにhtmlフォームを作成しましょう! 次のコードを使用して、form.pugという名前の新しいビューを作成します。

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

を使用してサーバーを実行します-

nodemon index.js

ここでlocalhost:3000/に移動し、必要に応じてフォームに入力して送信します。 あなたは応答を受け取ります-

受信したフォーム

コンソールを見てください。リクエストの本文がJavaScriptオブジェクトとして表示されます。 たとえば-

フォームコンソール

*this.request.body* オブジェクトには、解析されたリクエスト本文が含まれます。 そのオブジェクトのフィールドを使用するには、それらを通常のJSオブジェクトとして使用します。

これは、リクエストを送信する1つの方法にすぎません。 他にも多くの方法がありますが、Koaアプリはこれらのすべてのリクエストを同じ方法で処理するため、ここでは説明しません。 リクエストを行うさまざまな方法の詳細については、https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Sending_forms_through_JavaScript [this]ページをご覧ください。

Koa.js-ファイルのアップロード

Webアプリケーションは、ファイルのアップロードを許可する機能を提供する必要があります。 クライアントからファイルを受信して​​サーバーに保存する方法を見てみましょう。

リクエストの解析には、すでにkoa-bodyミドルウェアを使用しています。 このミドルウェアは、ファイルのアップロードの処理にも使用されます。 ファイルをアップロードし、Koaを使用してこれらのファイルを保存できるフォームを作成しましょう。 最初に、次の内容で file_upload.pug という名前のテンプレートを作成します。

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")

フォームで上記と同じエンコードタイプを指定する必要があることに注意してください。 サーバーでこのデータを処理しましょう。

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);

これを実行すると、次のフォームが表示されます。

ファイルアップロードフォーム

これを送信すると、コンソールは次の出力を生成します。

ファイルコンソール画面

アップロードされたファイルは、上記の出力のパスに保存されます。 this.request.body.files を使用してリクエスト内のファイルにアクセスし、 this.request.body.fields によってリクエスト内のフィールドにアクセスできます。

Koa.js-静的ファイル

静的ファイルは、クライアントがサーバーからそのままダウンロードするファイルです。 新しいディレクトリ public を作成します。 Expressでは、デフォルトで静的ファイルを提供できません。

この目的に役立つミドルウェアが必要です。 先に進み、 koa-serve をインストールします-

$ npm install --save koa-static

次に、このミドルウェアを*使用*する必要があります。 その前に、publicというディレクトリを作成します。 ここにすべての静的ファイルを保存します。 これにより、このパブリックフォルダーの上にクライアントがアクセスできないため、サーバーコードを安全に保つことができます。 パブリックディレクトリを作成したら、その中に好きなコンテンツを含む hello.txt という名前のファイルを作成します。 次に、app.jsに次を追加します。

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

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

app.listen(3000);

注意-Koaは静的ディレクトリに関連するファイルを検索するため、静的ディレクトリの名前はURLの一部ではありません。 これでルートルートがパブリックディレクトリに設定されるため、ロードするすべての静的ファイルはルートとしてパブリックと見なされます。 これが正常に機能していることをテストするには、アプリを実行して [[8]] にアクセスします

次の出力が得られます。 これはHTMLドキュメントまたはPugビューではなく、単純なtxtファイルであることに注意してください。

静的ファイル

複数の静的Dirs

また、次を使用して複数の静的アセットディレクトリを設定することもできます-

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

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

app.listen(3000);

ファイルを要求すると、Koaはこれらのディレクトリを検索し、一致するファイルを送信します。

Koa.js-クッキー

Cookieは、サーバー要求でクライアントに送信され、クライアント側に保存される単純な小さなファイル/データです。 ユーザーがWebサイトをロードするたびに、このCookieがリクエストとともに送信されます。 これにより、ユーザーのアクションを追跡できます。 HTTP Cookieには多くの用途があります。

  • セッション管理
  • パーソナライゼーション(推奨システム)
  • ユーザー追跡

KoaでCookieを使用するには、* ctx.cookies.set()および ctx.cookies.get()*という関数があります。 新しいCookieを設定するには、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);

Cookieが設定されているかどうかを確認するには、ブラウザに移動してコンソールを起動し、入力します-

console.log(document.cookie);

これにより、次の出力が生成されます(ブラウザの拡張機能により、さらに多くのCookieが設定されている場合があります)。

"foo = bar"

上記の例を次に示します。

Cookie

また、ブラウザーはサーバーに照会するたびにCookieを送り返します。 サーバーのCookieを表示するには、ルートのサーバーコンソールで、そのルートに次のコードを追加します。

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

次回このルートにリクエストを送信すると、次の出力が表示されます。

Cookies: foo = bar

有効期限付きのCookieの追加

期限切れのCookieを追加できます。 有効期限が切れるCookieを追加するには、プロパティ「expires」が設定されたオブジェクトを有効期限が切れる時刻に渡すだけです。 例えば、

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);

既存のCookieを削除する

Cookieを設定解除するには、Cookieを空の文字列に設定するだけです。 たとえば、 foo という名前のCookieをクリアする必要がある場合は、次のコードを使用します。

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);

これにより、上記のCookieが設定解除されます。 クライアント側のコードでCookieを使用しない場合は、 HttpOnly オプションをtrueのままにしておく必要があることに注意してください。

Koa.js-セッション

HTTPはステートレスなので、リクエストを他のリクエストに関連付けるには、HTTPリクエスト間でユーザーデータを保存する方法が必要です。 CookieとURLパラメータはどちらも、クライアントとサーバー間でデータを転送するのに適した方法です。 ただし、両方ともクライアント側で読み取り可能です。 セッションはまさにこの問題を解決します。 クライアントにIDを割り当て、そのIDを使用してそれ以降のすべての要求を行います。 クライアントに関連付けられた情報は、このIDにリンクされたサーバーに保存されます。

私たちはkoa-sessionが必要になるので、それを使用してインストールします-

npm install --save koa-session
*koa-session* ミドルウェアを配置します。 この例では、RAMを使用してセッションを保存します。 これを実稼働環境で使用しないでください。 セッションミドルウェアはすべてを処理します。 セッションの作成、セッションCookieの設定、およびコンテキストオブジェクトでのセッションオブジェクトの作成。

同じクライアントから再度リクエストを行うたびに、セッション情報が保存されます(サーバーが再起動されなかった場合)。 このセッションオブジェクトにさらにプロパティを追加できます。 次の例では、クライアントのビューカウンターを作成します。

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);

上記のコードは、ユーザーがサイトにアクセスすると、ユーザーの新しいセッションを作成し、Cookieを割り当てます。 次回ユーザーがアクセスすると、Cookieがチェックされ、それに応じてpage_viewセッション変数が更新されます。

アプリを実行して localhost:3000 にアクセスすると、次の応答が返されます。

セッションファースト

ページに再度アクセスすると、ページカウンターが増加します。 この場合、ページは12回更新されました。

セッション12

Koa.js-認証

認証は、提供された資格情報が、ローカルオペレーティングシステムまたは認証サーバー内の承認されたユーザーの情報のデータベースにあるファイルの資格情報と比較されるプロセスです。 資格情報が一致する場合、プロセスは完了し、ユーザーにはアクセスの許可が付与されます。

*Basic HTTP Authentication* を使用する非常に基本的な認証システムを作成します。 これは、Cookie、セッションなどを必要としないため、アクセス制御を実施する最も簡単な方法です。 これを使用するには、クライアントが行うすべての要求とと​​もにAuthorizationヘッダーを送信する必要があります。 ユーザー名とパスワードは暗号化されませんが、次のような単一の文字列に連結されます。
username:password

この文字列はBase64でエンコードされ、Basicという単語がこの値の前に置かれます。 たとえば、ユーザー名がAyushでパスワードがIndiaの場合、文字列 "Ayush:India" が認証ヘッダーでエンコードされて送信されます。

Authorization: Basic QXl1c2g6SW5kaWE=

これをkoaアプリに実装するには、koa-basic-authミドルウェアが必要です。 を使用してインストールします-

$ npm install --save koa-basic-auth

app.jsファイルを開き、次のコードを入力します。

//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);

すべての認証関連エラーを処理するエラー処理ミドルウェアを作成しました。 次に、2つのルートを作成しました-

  • /protected -このルートは、ユーザーが正しい認証ヘッダーを送信した場合にのみアクセスできます。 他のすべての場合、エラーが発生します。
  • /unprotected -このルートには、認証の有無にかかわらず、誰でもアクセスできます。

認証ヘッダーなしで、または間違った資格情報で/protectedにリクエストを送信すると、エラーが表示されます。 例えば、

$ curl https://localhost:3000/protected

あなたは応答を受け取ります-

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

ただし、適切な資格情報を使用すると、期待される応答が得られます。 例えば、

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

あなたはとして応答を取得します-

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.

/unprotectedルートは誰でも引き続きアクセスできます。

Koa.js-圧縮

圧縮は、帯域幅を節約してサイトを高速化するためのシンプルで効果的な方法です。 最新のブラウザとのみ互換性があり、ユーザーがレガシーブラウザも使用する場合は注意して使用する必要があります。

サーバーから応答を送信するときに、圧縮を使用すると、ロード時間を大幅に改善できます。 koa-compress というミドルウェアを使用して、ファイルの圧縮と適切なヘッダーの設定を行います。

先に進み、ミドルウェアをインストールします-

$ npm install --save koa-compress

今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)
});

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);

これにより、圧縮ミドルウェアが配置されます。 フィルターオプションは、応答のコンテンツタイプをチェックして圧縮するかどうかを決定する機能です。 しきい値オプションは、圧縮するバイト単位の最小応答サイズです。 これにより、小さな応答がすべて圧縮されることはありません。

以下は、圧縮なしの応答です。

非圧縮

以下は、圧縮を使用した同様の応答です。

圧縮

下部のサイズタブを見ると、2つの違いがよくわかります。 ファイルを圧縮すると、150%以上の改善があります。

Koa.js-キャッシュ

キャッシングは、後続のリクエストを高速化するために再利用可能な応答を保存するための用語です。 すべてのブラウザには、HTTPキャッシュの実装が付属しています。 必要なことは、各サーバー応答が正しいHTTPヘッダーディレクティブを提供して、ブラウザーが応答をキャッシュするタイミングと時間をブラウザーに指示することです。

以下は、Webアプリにキャッシュを含める利点です。

  • ネットワークコストが減少します。 コンテンツがキャッシュされている場合、以降のリクエストごとに送信する必要のあるコンテンツは少なくなります。
  • Webサイトの速度とパフォーマンスが向上します。 *クライアントがオフラインであっても、コンテンツを利用可能にすることができます。

koa-static-cacheミドルウェアを使用して、アプリにキャッシュを実装します。 を使用してこれらのミドルウェアをインストールします-

$ npm install --save koa-static-cache

app.jsファイルに移動し、次のコードを追加します。

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);
*koa-static-cache* ミドルウェアは、クライアント側でサーバー応答をキャッシュするために使用されます。 *cache-control* ヘッダーは、キャッシュオブジェクトの初期化中に指定したオプションに従って設定されます。 このキャッシュされた応答の有効期限を1年に設定しました。 以下は、ファイルがキャッシュされる前後に送信したリクエストの比較です。

このファイルがキャッシュされる前は、返されたステータスコードは200でしたが、これで問題ありません。 応答ヘッダーには、キャッシュされるコンテンツに関する複数の情報があり、コンテンツの ETag も指定されていました。

キャッシュ前

次にリクエストが送信されたときに、ETtagとともに送信されました。 サーバー上のコンテンツは変更されていないため、対応するETagも同じままで、クライアントはローカルにあるコピーがサーバーが提供するもので最新のものであり、リクエストする代わりにローカルのものを使用する必要があると通知されました再び。

キャッシュ後

注意-キャッシュされたファイルを無効にするには、ファイル名を変更して参照を更新するだけです。 これにより、クライアントに送信する新しいファイルが確保され、クライアントはそのファイルをキャッシュから読み込むことができなくなります。

Koa.js-データベース

リクエストを受信して​​いますが、どこにも保存していません。 データを保存するデータベースが必要です。 MongoDB と呼ばれる有名なNoSQLデータベースを使用します。 Mongoをインストールして読むには、link:/mongodb/mongodb_environment [this link。]にアクセスしてください。

KoaでMongoを使用するには、ノードのクライアントAPIが必要です。 複数のオプションがありますが、このチュートリアルではhttp://mongoosejs.com/[mongoose]に固執します。 Mongooseは、Node for MongoDBの*ドキュメントモデリング*に使用されます。 ドキュメントモデリングとは、 Model (ドキュメント指向プログラミングの class とほぼ同じ)を作成し、このモデルを使用して documents を生成することです(OOPで classs of document を作成するように) 。 すべての処理はこれらの「ドキュメント」で行われ、最後にこれらのドキュメントをデータベースに書き込みます。

Mongooseのセットアップ

Mongoをインストールしたので、他のノードパッケージをインストールしたのと同じ方法でmongooseをインストールします。

$ npm install --save mongoose

mongooseの使用を開始する前に、Mongoシェルを使用してデータベースを作成する必要があります。 新しいデータベースを作成するには、ターミナルを開いて「mongo」と入力します。 Mongoシェルが起動します。次を入力します。

use my_db

新しいデータベースが作成されます。 Mongoシェルを開くたびに、デフォルトで「test」dbになり、上記と同じコマンドを使用してデータベースに変更する必要があります。

mongooseを使用するには、app.jsファイルでそれを要求し、mongodb://localhostで実行されているmongodサービスに接続します

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);

これでアプリがデータベースに接続されました。新しいモデルを作成しましょう。 このモデルは、データベース内のコレクションとして機能します。 新しいモデルを作成するには、ルートを定義する前に次のコードを使用します。

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);

上記のコードは、人のスキーマを定義し、mongoose Model Person を作成するために使用されます。

ドキュメントを保存する

次に、人の詳細を取得してデータベースに保存する新しいhtmlフォームを作成します。 フォームを作成するには、viewsディレクトリに次の内容のperson.pugという新しいビューファイルを作成します。

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

また、index.jsに新しいgetルートを追加して、このドキュメントをレンダリングします。

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);

localhost:3000/personに移動して、フォームが正しく表示されているかどうかを確認します。 これは単なるUIであり、まだ機能していないことに注意してください。 これがフォームの外観です。

Mongoose Create

ここで、このリクエストを処理するポストルートハンドラーを '/person’で定義します。

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);

上記のコードで、空のフィールドを受信した場合、またはフィールドを受信しなかった場合、エラー応答を送信します。 ただし、整形式のドキュメントを受け取った場合は、PersonモデルからnewPersonドキュメントを作成し、* newPerson.save()関数を使用してDBに保存します。 これはmongooseで定義され、引数としてコールバックを受け入れます。 このコールバックには、 *error および response の2つの引数があります。 これにより、show_messageビューがレンダリングされるため、これも作成する必要があります。

このルートからの応答を表示するには、 show_message ビューも作成する必要があります。 次のコードで新しいビューを作成します。

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!

以下は、フォーム(show_message.pug)の送信に成功したときに受け取る応答です。

Mongoose Response

これで、人を作成するためのインターフェースができました!

ドキュメントを取得する

Mongooseはドキュメントを取得するための多くの機能を提供しますが、そのうちの3つに焦点を当てます。 これらの関数はすべて、最後のパラメーターとしてコールバックを使用し、save関数と同様に、それらの引数はエラーと応答です。

3つの機能は-

Model.find(条件、コールバック)

この関数は、条件オブジェクトのフィールドに一致するすべてのドキュメントを検索します。 Mongoで使用されているのと同じ演算子は、mongooseでも機能します。 たとえば、これにより、個人のコレクションからすべてのドキュメントが取得されます。

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

これにより、フィールド名が「Ayush」で年齢が20のすべてのドキュメントが取得されます。

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

必要な投影、つまり必要なフィールドも提供できます。 たとえば、*国籍*が_ "Indian" _である人々の*名前*のみが必要な場合、次を使用します-

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

Model.findOne(条件、コールバック)

この関数は、常に最も関連性の高い単一のドキュメントを取得します。 Model.find()とまったく同じ引数を持ちます。

Model.findById(id、コールバック)

この関数は、最初の引数として _id (mongoで定義)、オプションの投影文字列、および応答を処理するためのコールバックを受け取ります。 例えば、

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

すべての人のレコードを表示するルートを作成しましょう。

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);

ドキュメントの更新

Mongooseは、ドキュメントを更新するための3つの機能を提供します。

Model.update(条件、更新、コールバック)

この関数は条件を取得し、入力としてオブジェクトを更新し、コレクション内の条件に一致するすべてのドキュメントに変更を適用します。 たとえば、次のコードはすべてのユーザー文書を更新して、国籍が「アメリカ人」になるようにします。

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

Model.findOneAndUpdate(条件、更新、コールバック)

まさにそのとおりです。 クエリに基づいて1つのドキュメントを検索し、2番目の引数に従ってドキュメントを更新します。 また、最後の引数としてコールバックを取ります。 例えば、

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

Model.findByIdAndUpdate(id、更新、コールバック)

この関数は、IDで識別される単一のドキュメントを更新します。 例えば、

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

人を更新するルートを作成しましょう。 これは、パラメーターとしてidを持ち、ペイロードに詳細を持つPUTルートになります。

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);

このルートをテストするには、ターミナルで次のように入力します(IDを作成した人のIDに置き換えます)。

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

これにより、ルートで提供されたIDに関連付けられたドキュメントが上記の詳細で更新されます。

ドキュメントを削除する

  • C * reate、* R * ead、* U *pdateについて説明しましたが、今度はmongooseを使用してドキュメントを削除する方法を確認します。 ここには、更新とまったく同じ3つの関数があります。

Model.remove(条件、[コールバック])

この関数は、条件オブジェクトを入力として受け取り、条件に一致するすべてのドキュメントを削除します。 たとえば、20歳のすべての人を削除する必要がある場合

Person.remove({age:20});

Model.findOneAndRemove(条件、[コールバック])

この関数は、条件オブジェクトに応じて、最も関連性の高いドキュメントを削除します。 例えば、

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

Model.findByIdAndRemove(id、[callback])

この関数は、IDで識別される単一のドキュメントを削除します。 例えば、

Person.findByIdAndRemove("507f1f77bcf86cd799439011");

それでは、データベースから人を削除するルートを作成しましょう。

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);

これをテストするには、次のcurlコマンドを使用します-

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

これにより、指定されたIDを持つ人が削除され、次のメッセージが生成されます。 −

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

これで、MongoDB、mongoose、およびKoaを使用して簡単なCRUDアプリケーションを作成する方法をまとめました。 mongooseをさらに詳しく調べるには、http://mongoosejs.com [APIドキュメント]をお読みください。

Koa.js-RESTful API

モバイルアプリケーション、シングルページアプリケーションを作成し、AJAX呼び出しを使用してクライアントにデータを提供するには、APIが必要です。 これらのAPIとエンドポイントを構造化して名前を付ける方法の一般的なアーキテクチャスタイルは、* REST(Representational Transfer State)と呼ばれます。 HTTP 1.1は、RESTの原則を念頭に置いて設計されました。 RESTは、2000年に彼の論文Fielding Dissertationsで *Roy Fielding によって紹介されました。

RESTful URIとメソッドは、リクエストの処理に必要なほぼすべての情報を提供します。 次の表は、さまざまな動詞の使用方法とURIの命名方法をまとめたものです。 最後に向けて映画APIを作成するので、どのように構成するかについて説明しましょう。

Method URI Details Function
GET /movies Safe, cachable Gets the list of all movies and their details
GET /movies/1234 Safe, cachable Gets the details of Movie id 1234
POST /movies N/A Creates a new movie with details provided. Response contains the URI for this newly created resource.
PUT /movies/1234 Idempotent Modifies movie id 1234 (creates one if it doesn’t already exist). Response contains the URI for this newly created resource.
DELETE /movies/1234 Idempotent Movie id 1234 should be deleted, if it exists. Response should contain the status of request.
DELETE or PUT /movies Invalid Should be invalid. DELETE and PUT should specify which resource they are working on.

次に、このAPIをKoaで作成しましょう。 JavaScriptでの操作が簡単で、他にも多くの利点があるため、トランスポートデータ形式としてJSONを使用します。 index.jsファイルを次のように置き換えます-

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);

アプリケーションのセットアップが完了したので、APIの作成に集中しましょう。 最初にmovies.jsファイルをセットアップします。 データベースを使用して映画を保存するのではなく、メモリに保存しているため、サーバーが再起動するたびに、追加された映画は消えます。 これは、データベースまたはファイルを使用して(node fsモジュールを使用して)簡単に模倣できます。

koa-routerをインポートし、ルーターを作成し、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;

ルートを取得

すべての映画を取得するためのGETルートを定義します。

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

それでおしまい。 これが正常に機能しているかどうかをテストするには、アプリを実行し、ターミナルを開いて入力します-

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/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}]

すべての映画を入手するルートがあります。 次に、IDで特定の映画を取得するためのルートを作成します。

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;
}

これにより、指定したIDに従って映画が取得されます。 これをテストするには、ターミナルで次のコマンドを使用します。

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

あなたはとして応答を取得します-

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

無効なルートにアクセスすると、GETエラーは発生しませんが、存在しないIDで有効なルートにアクセスすると、404エラーが発生します。

GETルートはこれで完了です。 それでは、POSTルートに進みましょう。

POSTルート

次のルートを使用して、POSTされたデータを処理します。

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;
}

これにより、新しいムービーが作成され、movies変数に保存されます。 このルートをテストするには、ターミナルに次のように入力します-

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

あなたは次の応答を取得します-

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

これがムービーオブジェクトに追加されたかどうかをテストするには、/movies/105のget要求を再度実行します。 あなたは次の応答を取得します-

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

次に、PUTおよびDELETEルートを作成します。

PUTルート

PUTルートは、POSTルートとほぼ同じです。 更新/作成されるオブジェクトのIDを指定します。 次の方法でルートを作成します-

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};
      }
   }
}

このルートは、上の表で指定した機能を実行します。 オブジェクトが存在する場合、新しい詳細でオブジェクトを更新します。 存在しない場合は、新しいオブジェクトを作成します。 このルートをテストするには、次のcurlコマンドを使用します。 これにより、既存のムービーが更新されます。 新しいムービーを作成するには、IDを存在しないIDに変更するだけです。

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

応答

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

ルートを削除

次のコードを使用して、削除ルートを作成します。

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."};
   }
}

他のルートと同じ方法でルートをテストします。 削除が成功すると(たとえば、id 105)、次のようになります-

{message: "Movie id 105 removed."}

最後に、movies.jsファイルは次のようになります-

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;

これでREST APIが完成しました。 この単純なアーキテクチャスタイルとKoaを使用して、はるかに複雑なアプリケーションを作成できるようになりました。

Koa.js-ロギング

ロギングは、Webアプリケーションを作成するときに非常に役立ちます。これは、正確にどこで問題が発生したかを教えてくれるからです。 また、問題が発生した場合のコンテキストを取得し、同じ解決策を考え出すことができます。

Koaでログを有効にするには、ミドルウェア koa-logger が必要です。 次のコマンドを使用してインストールします。

$ npm install --save-dev koa-logger

アプリケーションで、次のコードを追加してロギングを有効にします。

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)

このサーバーを実行し、サーバー上の任意のルートにアクセスします。 次のようなログが表示されるはずです-

ロギング

これで、特定のルートまたはリクエストでエラーが発生した場合、これらのログは、それぞれのエラーを把握するのに役立ちます。

Koa.js-足場

足場を使用すると、Webアプリケーションのスケルトンを簡単に作成できます。 パブリックディレクトリを手動で作成し、ミドルウェアを追加し、個別のルートファイルを作成しました。 足場ツールがこれらすべてをセットアップするため、アプリケーションの構築を直接開始できます。

使用する足場は Yeoman と呼ばれます。 Node.js用に構築された足場ツールですが、他のいくつかのフレームワーク(フラスコ、レール、djangoなど)用のジェネレーターもあります。 yeomanをインストールするには、ターミナルで次のコマンドを入力します。

$ npm install -g yeoman

Yeomanは、ジェネレーターを使用してアプリケーションの足場を作ります。 npmでyeomanで使用できるジェネレーターを確認するには、http://yeoman.io/generators/[こちら]にアクセスしてください。 このチュートリアルでは、「generator-koa」を使用します。 このジェネレーターをインストールするには、ターミナルで次のコマンドを入力します。

$ npm install -g generator-koa

このジェネレータを使用するには、次を入力します-

yo koa

次に、ディレクトリ構造を作成し、次のファイルを作成します。 また、必要なnpmモジュールとbowerコンポーネントもインストールします。

create package.json
create test/routeSpec.js
create views/layoutl
create views/listl
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.

このジェネレーターは、非常に単純な構造を作成します。

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

Koaで使用可能な多くのジェネレーターを調べて、適切なジェネレーターを選択してください。 すべてのジェネレーターを使用する手順は同じです。 ジェネレーターをインストールし、yeomanを使用して実行し、いくつかの質問をしてから、回答に基づいてアプリケーションのスケルトンを作成する必要があります。

Koa.js-リソース

以下は、このチュートリアルの開発中に使用したリソースのリストです-