Expressjs-quick-guide

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

ExpressJS-概要

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

Expressとは何ですか?

Expressは、アプリケーションをビルドするための最小限のインターフェースを提供します。 アプリをビルドするために必要なツールを提供します。 npm には多数のモジュールがあり、Expressに直接プラグインできるため、柔軟性があります。

Expressは TJ Holowaychuk によって開発され、https://nodejs.org/en/[Node.js]財団と多数のオープンソース貢献者によって維持されています。

エクスプレスする理由

RailsやDjangoのような競合他社とは異なり、Expressにはアプリケーションを構築する方法がありますが、Expressには何かを行うための「最良の方法」はありません。 非常に柔軟でプラグイン可能です。

Pug

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

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

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

MongoDBおよびMongoose

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

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

ExpressJS-環境

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

node --version
npm --version

次のような出力が表示されます。

v5.0.0
3.5.2

Nodeと npm がセットアップされたので、 npm とは何か、その使用方法を理解しましょう。

Node Package Manager(npm)

npmはノードのパッケージマネージャーです。 npm Registryは、Node.js、フロントエンドWebアプリ、モバイルアプリ、ロボット、ルーター、およびJavaScriptコミュニティの無数の他のニーズのためのオープンソースコードのパッケージのパブリックコレクションです。 npmを使用すると、これらすべてのパッケージにアクセスしてローカルにインストールできます。 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(ディレクトリを作成)します-

npm init info

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

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

npm init info

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

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

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

ls node_modules #(dir node_modules for windows)

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

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

npm install -g nodemon

これで、Expressの作業を開始できます。

ExpressJS-Hello World

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

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

app.get('/', function(req, res){
   res.send("Hello world!");
});

app.listen(3000);

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

nodemon index.js

これによりサーバーが起動します。 このアプリをテストするには、ブラウザを開いて http://localhost:3000 にアクセスすると、次のスクリーンショットのようにメッセージが表示されます。

Hello world

アプリの仕組み

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

app.get(route、callback)

この関数は、指定されたルートで get リクエストが呼び出されたときに何をするかを指示します。 コールバック関数には、 _ request(req)' および _response(res)' の2つのパラメーターがあります。 リクエスト* object(req)*はHTTPリクエストを表し、リクエストクエリ文字列、パラメーター、ボディ、HTTPヘッダーなどのプロパティがあります。 同様に、応答オブジェクトは、ExpressアプリがHTTP要求を受信したときに送信するHTTP応答を表します。

res.send()

この関数は、オブジェクトを入力として受け取り、要求元のクライアントに送信します。 ここでは、文字列_ "Hello World!" _を送信しています。

app.listen(ポート、[ホスト]、[バックログ]、[コールバック]])

この関数は、指定されたホストとポートで接続をバインドしてリッスンします。 ここでは、ポートが唯一の必須パラメーターです。

S.No. Argument & Description
1

port

サーバーが着信要求を受け入れるポート番号。

2

host

ドメインの名前。 アプリをクラウドにデプロイするときに設定する必要があります。

3

backlog

キューに入れられた保留中の接続の最大数。 デフォルトは511です。

4

callback

サーバーが要求のリッスンを開始するときに呼び出される非同期関数。

ExpressJS-ルーティング

Webフレームワークは、HTMLページ、スクリプト、画像などのリソースを提供します。 異なるルートで。

次の関数は、Expressアプリケーションでルートを定義するために使用されます-

app.method(path、handler)

このMETHODは、HTTP動詞のいずれか(get、set、put、delete)に適用できます。 リクエストタイプに関係なく実行される代替メソッドもあります。

パスは、リクエストが実行されるルートです。

ハンドラーは、関連するルートで一致する要求タイプが見つかったときに実行されるコールバック関数です。 例えば、

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

app.get('/hello', function(req, res){
   res.send("Hello World!");
});

app.listen(3000);

アプリケーションを実行して localhost:3000/hello に移動すると、サーバーはルート "/hello" でgetリクエストを受信し、Expressアプリはこのルートにアタッチされた callback 関数を実行して* "Hello World ! "*応答として。

こんにちは

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

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

app.get('/hello', function(req, res){
   res.send("Hello World!");
});

app.post('/hello', function(req, res){
   res.send("You just called the post method at '/hello'!\n");
});

app.listen(3000);

この要求をテストするには、端末を開き、cURLを使用して次の要求を実行します-

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

Curlリクエスト

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

app.all('/test', function(req, res){
   res.send("HTTP method doesn't have any effect on this route!");
});

この方法は、一般にミドルウェアの定義に使用されます。ミドルウェアの章で説明します。

ルーター

上記のようなルートの定義は、維持するのが非常に面倒です。 メインの index.js ファイルからルートを分離するには、 Express.Router を使用します。 things.js という新しいファイルを作成し、次のように入力します。

var express = require('express');
var router = express.Router();

router.get('/', function(req, res){
   res.send('GET route on things.');
});
router.post('/', function(req, res){
   res.send('POST route on things.');
});

//export this router to use in our index.js
module.exports = router;
*index.js* でこのルーターを使用するには、 *app.listen* 関数呼び出しの前に次を入力します。
var express = require('Express');
var app = express();

var things = require('./things.js');

//both index.js and things.js should be in same directory
app.use('/things', things);

app.listen(3000);

ルート '/things'app.use 関数呼び出しは、 things ルーターをこのルートにアタッチします。 これで、アプリが「/things」で取得したリクエストはすべて、things.jsルーターで処理されます。 things.jsの '/' ルートは、実際には '/things’のサブルートです。 localhost:3000/things/にアクセスすると、次の出力が表示されます。

ルーターのこと

ルーターは、懸念事項を分離し、コードの関連部分をまとめるのに非常に役立ちます。 メンテナンス可能なコードの構築に役立ちます。 エンティティに関連するルートを単一のファイルで定義し、上記のメソッドを使用して index.js ファイルに含める必要があります。

ExpressJS-HTTPメソッド

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

S.No. Method & Description
1

GET

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

2

POST

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

3

PUT

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

4

DELETE

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

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

ExpressJS-URL構築

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

これは、動的ルートの例です-

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

app.get('/:id', function(req, res){
   res.send('The id you specified is ' + req.params.id);
});
app.listen(3000);

これをテストするには、 http://localhost:3000/123 に移動します。 次の応答が表示されます。

URLビルディング1

URLの「123」を他のものに置き換えると、変更が応答に反映されます。 上記のより複雑な例は-

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

app.get('/things/:name/:id', function(req, res) {
   res.send('id: ' + req.params.id + ' and name: ' + req.params.name);
});
app.listen(3000);

上記のコードをテストするには、 http://localhost:3000/things/finddevguides/12345 にアクセスします。

URLビル2

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

パターン一致ルート

*regex* を使用して、URLパラメーターの一致を制限することもできます。 *id* が5桁の長い数字である必要があると仮定しましょう。 次のルート定義を使用できます-
var express = require('express');
var app = express();

app.get('/things/:id([0-9]{5})', function(req, res){
   res.send('id: ' + req.params.id);
});

app.listen(3000);

これは、5桁の長さの id を持つ要求にのみ*一致*することに注意してください。 より複雑な正規表現を使用して、ルートを照合/検証できます。 どのルートもリクエストに一致しない場合、応答として _ "<not-request-route>" _ メッセージを取得できません。 このメッセージは、この単純なルートを使用して、404の見つからないページに置き換えられます-

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

//Other routes here
app.get('*', function(req, res){
   res.send('Sorry, this is an invalid URL.');
});
app.listen(3000);

重要-Expressは、必要な外部ルーターを含む index.js ファイルの最初から最後までのルートと一致するため、すべてのルートの後に配置する必要があります。

たとえば、上記と同じルートを定義した場合、有効なURLでリクエストすると、次の出力が表示されます。 −

正しい正規表現

誤ったURLリクエストの場合、次の出力が表示されます。

無効な正規表現(404)

ExpressJS-ミドルウェア

ミドルウェア関数は、* requestオブジェクト(req) responseオブジェクト(res)、およびアプリケーションの要求/応答サイクルの次のミドルウェア関数にアクセスできる関数です。 これらの関数は、要求本文の解析、応答ヘッダーの追加などのタスクの *req および res オブジェクトを変更するために使用されます。

ここに動作中のミドルウェア機能の簡単な例があります-

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

//Simple request time logger
app.use(function(req, res, 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.
   next();
});

app.listen(3000);

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

A new request received at 1467267512545

特定のルート(およびそのすべてのサブルート)に制限するには、そのルートを app.use() の最初の引数として指定します。 例えば、

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

//Middleware function to log request protocol
app.use('/things', function(req, res, next){
   console.log("A request for things received at " + Date.now());
   next();
});

//Route handler that sends the response
app.get('/things', function(req, res){
   res.send('Things');
});

app.listen(3000);

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

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

Expressのミドルウェアで最も重要なことの1つは、ファイルに書き込まれる/含まれる順序です。ルートの一致も考慮する必要があるため、実行される順序。

たとえば、次のコードスニペットでは、最初の関数が最初に実行され、次にルートハンドラー、最後に関数が実行されます。 この例では、ルートハンドラの前後にミドルウェアを使用する方法をまとめています。また、ルートハンドラーをミドルウェア自体として使用する方法。

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

//First middleware before response is sent
app.use(function(req, res, next){
   console.log("Start");
   next();
});

//Route handler
app.get('/', function(req, res, next){
   res.send("Middle");
   next();
});

app.use('/', function(req, res){
   console.log('End');
});

app.listen(3000);

このコードを実行した後に「/」にアクセスすると、応答が Middle としてコンソールに表示されます-

Start
End

次の図は、ミドルウェアについて学んだことをまとめたものです-

ミドルウェア

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

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

Expressのサードパーティミドルウェアのリストは、http://expressjs.com/en/resources/middlewarel [こちら]から入手できます。 以下は、最も一般的に使用されるミドルウェアの一部です。また、これらを使用/マウントする方法を学びます-

ボディパーサー

これは、ペイロードが添付されているリクエストのボディを解析するために使用されます。 ボディパーサーをマウントするには、 npm install --save body-parserを使用してインストールし、マウントするには、index.jsに次の行を含めます。

var bodyParser = require('body-parser');

//To parse URL encoded data
app.use(bodyParser.urlencoded({ extended: false }))

//To parse json data
app.use(bodyParser.json())

body-parserで利用可能なすべてのオプションを表示するには、githubページにアクセスしてください。

cookie-parser

_Cookie_ヘッダーを解析し、req.cookiesにcookie名をキーとするオブジェクトを設定します。 Cookieパーサーをマウントするには、npm install --save cookie-parserを使用してインストールし、マウントするために、index.jsに次の行を含めます-

var cookieParser = require('cookie-parser');
app.use(cookieParser())

エクスプレスセッション

指定されたオプションでセッションミドルウェアを作成します。 セッションのセクションでその使用法について説明します。

ExpressJSには他にも多くのサードパーティミドルウェアがあります。 ただし、ここでは重要なもののみを説明しました。

ExpressJS-テンプレート

PugはExpressのテンプレートエンジンです。 テンプレートエンジンは、サーバーコードがHTMLで乱雑になるのを防ぎ、文字列を既存のHTMLテンプレートに乱暴に連結するために使用されます。 Pugは非常に強力なテンプレートエンジンで、*フィルター、インクルード、継承、補間*などのさまざまな機能を備えています。 これには多くの根拠があります。

ExpressでPugを使用するには、インストールする必要があります。

npm install --save pug

Pugがインストールされたので、アプリのテンプレートエンジンとして設定します。 あなたはそれを「要求」する必要はありません。 次のコードを index.js ファイルに追加します。

app.set('view engine', 'pug');
app.set('views','./views');

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

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

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

app.get('/first_template', function(req, res){
   res.render('first_view');
});

出力は-* Hello World!として取得されます。Pugは、この非常にシンプルなマークアップをHTMLに変換します。 タグを閉じるのを追跡する必要はありません。クラスやidキーワードを使用する必要はなく、「。」を使用しますおよび *'#' で定義します。 上記のコードは最初に変換されます-

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

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

Pugは、HTMLマークアップを単純化するだけではありません。

パグの重要な機能

Pugのいくつかの重要な機能を調べてみましょう。

シンプルなタグ

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

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

タグ内にテキストを配置するには、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 express = require('express');
var app = express();

app.get('/dynamic_view', function(req, res){
   res.render('dynamic', {
      name: "finddevguides",
      url:"http://www.finddevguides.com"
   });
});

app.listen(3000);

そして、次のコードを使用して、 dynamic.pug と呼ばれるビューディレクトリに新しいビューファイルを作成します-

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

ブラウザでlocalhost:3000/dynamic_viewを開きます。あなたは次の出力を取得する必要があります-

テンプレート内の変数

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

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

値を使用するこの方法は*補間*と呼ばれます。 上記のコードは、次の出力を表示します。 −

Templating Inter

条件付き

条件ステートメントとループ構造も使用できます。

以下を考慮してください-

ユーザーがログインしている場合、ページには "Hi、User" が表示され、そうでない場合は "Login/Sign Up" リンクが表示されます。 これを達成するために、次のような単純なテンプレートを定義できます-

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

ルートを使用してこれをレンダリングするとき、次のプログラムのようにオブジェクトを渡すことができます-

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

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

含めるとコンポーネント

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

次のコードで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 express = require('express');
var app = express();

app.get('/components', function(req, res){
    res.render('content');
});

app.listen(3000);

localhost:3000/componentsに移動すると、次の出力が表示されます-

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

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

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

ExpressJS-静的ファイルの提供

静的ファイルは、クライアントがサーバーからそのままダウンロードするファイルです。 新しいディレクトリ public を作成します。 Expressでは、デフォルトで静的ファイルを提供できません。 次の組み込みミドルウェアを使用して有効にする必要があります。

app.use(express.static('public'));

注意-Expressは静的ディレクトリに関連するファイルを検索するため、静的ディレクトリの名前はURLの一部ではありません。

ルートルートがパブリックディレクトリに設定されているため、ロードするすべての静的ファイルはパブリックとしてルートと見なされることに注意してください。 これが正常に機能していることをテストするには、新しい public ディレクトリに画像ファイルを追加し、その名前を「 testimage.jpg 」に変更します。 ビューで、新しいビューを作成し、このファイルを次のように含めます-

html
   head
   body
      h3 Testing static file serving:
      img(src = "/testimage.jpg", alt = "Testing Image

あなたは次の出力を取得する必要があります-

静的ファイルの例

複数の静的ディレクトリ

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

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

app.use(express.static('public'));
app.use(express.static('images'));

app.listen(3000);

仮想パスプレフィックス

静的ファイルを提供するためのパスプレフィックスも指定できます。 たとえば、 '/static' のようなパスプレフィックスを指定する場合は、 index.js ファイルに次のコードを含める必要があります-

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

app.use('/static', express.static('public'));

app.listen(3000);

これで、たとえば、パブリックディレクトリにあるmain.jsというスクリプトファイルを含める必要がある場合は、次のスクリプトタグを使用します-

<script src = "/static/main.js"/>

この手法は、複数のディレクトリを静的ファイルとして提供する場合に役立ちます。 これらのプレフィックスは、複数のディレクトリを区別するのに役立ちます。

ExpressJS-フォームデータ

フォームはWebの不可欠な部分です。 私たちが訪問するほとんどすべてのウェブサイトは、私たちのために情報を送信または取得するフォームを提供します。 フォームの使用を開始するには、最初に_body-parser_(JSONおよびurlエンコードデータの解析用)およびmulter(マルチパート/フォームデータの解析用)ミドルウェアをインストールします。

_body-parser_と_multer_をインストールするには、ターミナルに移動して使用します-

npm install --save body-parser multer
*index.js* ファイルの内容を次のコードに置き換えます-
var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var app = express();

app.get('/', function(req, res){
   res.render('form');
});

app.set('view engine', 'pug');
app.set('views', './views');

//for parsing application/json
app.use(bodyParser.json());

//for parsing application/xwww-
app.use(bodyParser.urlencoded({ extended: true }));
//form-urlencoded

//for parsing multipart/form-data
app.use(upload.array());
app.use(express.static('public'));

app.post('/', function(req, res){
   console.log(req.body);
   res.send("recieved your request!");
});
app.listen(3000);

bodyパーサーとmulterをインポートした後、jsonおよびx-www-form-urlencodedヘッダーリクエストの解析に body-parser を使用し、multipart/form-dataの解析に multer を使用します。

これをテストするためにhtmlフォームを作成しましょう。 次のコードで form.pug と呼ばれる新しいビューを作成します-

html
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 = "Express forms")
         br
         button(type = "submit") Send my greetings

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

nodemon index.js

ここでlocalhost:3000/に移動し、必要に応じてフォームに入力して送信します。 次の応答が表示されます-

フォーム送信への応答

コンソールをご覧ください。次のスクリーンショットのように、JavaScriptオブジェクトとしてリクエストの本文が表示されます-

フォームのコンソール出力

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

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

ExpressJS-データベース

リクエストを受信し続けますが、どこにも保存しません。 データを保存するデータベースが必要です。 このために、 MongoDB と呼ばれるNoSQLデータベースを使用します。

Mongoをインストールして読むには、リンク:/mongodb/mongodb_environment [this link。]

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

Mongooseのセットアップ

Mongoをインストールしたので、他のノードパッケージをインストールしたのと同じ方法でMongooseをインストールしましょう-

npm install --save mongoose

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

use my_db

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

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

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

上記のコードは個人のスキーマを定義し、Mongoose Mode 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.jsnew get route を追加して、このドキュメントをレンダリングします-

app.get('/person', function(req, res){
   res.render('person');
});

localhost:3000/person 」に移動して、フォームに正しい出力が表示されているかどうかを確認します。 これは単なるUIであり、まだ機能していないことに注意してください。 次のスクリーンショットは、フォームがどのように表示されるかを示しています-

Mongoose Create

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

app.post('/person', function(req, res){
   var personInfo = req.body;//Get the parsed information

   if(!personInfo.name || !personInfo.age || !personInfo.nationality){
      res.render('show_message', {
         message: "Sorry, you provided worng info", type: "error"});
   } else {
      var newPerson = new Person({
         name: personInfo.name,
         age: personInfo.age,
         nationality: personInfo.nationality
      });

      newPerson.save(function(err, Person){
         if(err)
            res.render('show_message', {message: "Database error", type: "error"});
         else
            res.render('show_message', {
               message: "New person added", type: "success", person: personInfo});
      });
   }
});

上記のコードで、空のフィールドを受信した場合、またはフィールドを受信しなかった場合、エラー応答を送信します。 しかし、整形式のドキュメントを受け取ったら、Personモデルから newPerson ドキュメントを作成し、* newPerson.save()関数を使用してDBに保存します。 これはMongooseで定義され、引数としてコールバックを受け入れます。 このコールバックには、エラーと応答の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!
  • form(show_message.pug)*を正常に送信すると、次の応答を受け取ります-

Mongoose Response

*persons* を作成するためのインターフェイスが用意されました。

ドキュメントを取得する

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

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

この関数は、条件オブジェクトのフィールドに一致するすべてのドキュメントを検索します。 Mongoで使用されているのと同じ演算子は、mongooseでも機能します。 例えば、

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

これにより、個人のコレクションからすべてのドキュメントが取得されます。

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

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

必要な投影、つまり必要なフィールドを提供することもできます。 たとえば、*国籍*が_ "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 express = require('express');
var app = express();

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.get('/people', function(req, res){
   Person.find(function(err, response){
      res.json(response);
   });
});

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 express = require('express');
var app = express();

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.put('/people/:id', function(req, res){
   Person.findByIdAndUpdate(req.params.id, req.body, function(err, response){
      if(err) res.json({message: "Error in updating person with id " + req.params.id});
      res.json(response);
   });
});

app.listen(3000);

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

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

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

ドキュメントを削除する

*Create、Read* 、および *Update* について説明しましたが、Mongooseを使用してドキュメントを*削除*する方法を確認します。 ここには、更新とまったく同じ3つの関数があります。

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

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

Person.remove({age:20});

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

この関数は、条件オブジェクトに応じて、最も関連性の高いドキュメントを削除します。 同じことを理解するために、次のコードを実行してみましょう。

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

Model.findByIdAndRemove(id、[callback])

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

Person.findByIdAndRemove("507f1f77bcf86cd799439011");

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

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

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.delete('/people/:id', function(req, res){
   Person.findByIdAndRemove(req.params.id, function(err, response){
      if(err) res.json({message: "Error in deleting record id " + req.params.id});
      else res.json({message: "Person with id " + req.params.id + " removed."});
   });
});

app.listen(3000);

出力を確認するには、次のcurlコマンドを使用します-

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

これは、次のメッセージを生成する特定のIDを持つ人を削除します-

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

これで、MongoDB、Mongoose、Expressを使用して簡単なCRUDアプリケーションを作成する方法をまとめました。 Mongooseの詳細については、http://mongoosejs.com [APIドキュメント]をご覧ください。

ExpressJS-クッキー

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

以下は、HTTP Cookieの多数の用途です-

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

ExpressでCookieを使用するには、Cookieパーサーミドルウェアが必要です。 それをインストールするには、次のコードを使用します-

npm install --save cookie-parser

ExpressでCookieを使用するには、 cookie-parser が必要です。 cookie-parserは、_クライアントリクエストオブジェクトに添付されたCookieを解析するミドルウェアです。 これを使用するには、 index.js ファイルで必要になります。これは、他のミドルウェアを使用するのと同じ方法で使用できます。 ここでは、次のコードを使用します。

var cookieParser = require('cookie-parser');
app.use(cookieParser());

cookie-parserはCookieヘッダーを解析し、 req.cookies にCookie名をキーとするオブジェクトを設定します。 新しいCookieを設定するには、Expressアプリで次のような新しいルートを定義します。

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

app.get('/', function(req, res){
   res.cookie('name', 'express').send('cookie set');//Sets name = express
});

app.listen(3000);

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

console.log(document.cookie);

次のような出力が得られます(おそらく、ブラウザの拡張機能により、さらに多くのCookieが設定されている可能性があります)-

"name = express"

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

console.log('Cookies: ', req.cookies);

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

Cookies: { name: 'express' }

有効期限付きのCookieの追加

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

//Expires after 360000 ms from the time it is set.
res.cookie(name, 'value', {expire: 360000 + Date.now()});

有効期限を設定する別の方法は、 'maxAge' プロパティを使用することです。 このプロパティを使用して、絶対時間ではなく相対時間を提供できます。 以下は、このメソッドの例です。

//This cookie also expires after 360000 ms from the time it is set.
res.cookie(name, 'value', {maxAge: 360000});

既存のCookieを削除する

Cookieを削除するには、clearCookie関数を使用します。 たとえば、 foo という名前のCookieをクリアする必要がある場合は、次のコードを使用します。

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

app.get('/clear_cookie_foo', function(req, res){
   res.clearCookie('foo');
   res.send('cookie foo cleared');
});

app.listen(3000);

次の章では、Cookieを使用してセッションを管理する方法について説明します。

ExpressJS-セッション

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

_Express-session_が必要なので、次のコードを使用してインストールします。

npm install --save express-session
*session* および *cookie-parser* ミドルウェアを配置します。 この例では、セッションの保存にデフォルトのストア、つまりMemoryStoreを使用します。 これを実稼働環境で使用しないでください。 セッションミドルウェアは、すべての処理を行います。つまり、セッションの作成、セッションCookieの設定、 *req* オブジェクトでのセッションオブジェクトの作成です。

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

var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');

var app = express();

app.use(cookieParser());
app.use(session({secret: "Shh, its a secret!"}));

app.get('/', function(req, res){
   if(req.session.page_views){
      req.session.page_views++;
      res.send("You visited this page " + req.session.page_views + " times");
   } else {
      req.session.page_views = 1;
      res.send("Welcome to this page for the first time!");
   }
});
app.listen(3000);

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

アプリを実行して localhost:3000 に移動すると、次の出力が表示されます。

最初の訪問

ページに再度アクセスすると、ページカウンターが増加します。 次のスクリーンショットのページは42回更新されました。

最初の訪問

ExpressJS-認証

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

認証システムを作成するには、サインアップページとユーザーパスワードストアを作成する必要があります。 次のコードは、アカウントを作成してメモリに保存します。 これは、デモのみを目的としています。ユーザー情報の保存には、常に永続的なストレージ(データベースまたはファイル)を使用することをお勧めします。

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var session = require('express-session');
var cookieParser = require('cookie-parser');

app.set('view engine', 'pug');
app.set('views','./views');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Your secret key"}));

var Users = [];

app.get('/signup', function(req, res){
   res.render('signup');
});

app.post('/signup', function(req, res){
   if(!req.body.id || !req.body.password){
      res.status("400");
      res.send("Invalid details!");
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id){
            res.render('signup', {
               message: "User Already Exists! Login or choose another user id"});
         }
      });
      var newUser = {id: req.body.id, password: req.body.password};
      Users.push(newUser);
      req.session.user = newUser;
      res.redirect('/protected_page');
   }
});

app.listen(3000);

サインアップフォームの場合、* signup.jade。*という新しいビューを作成します

SIGNUP.JADE

html
   head
      title Signup
   body
      if(message)
         h4 #{message}
         form(action = "/signup" method = "POST")
         input(name = "id" type = "text" required placeholder = "User ID")
         input(name = "password" type = "password" required placeholder = "Password")
         button(type = "Submit") Sign me up!

localhost:3000/signupにアクセスして、このページが読み込まれるかどうかを確認します。

サインアップフォーム

両方のフィールドに必須属性を設定しているため、HTML5対応ブラウザーでは、IDとパスワードの両方を指定するまでこのフォームを送信できません。 ユーザーIDまたはパスワードなしでcurl要求を使用して登録しようとすると、エラーが表示されます。 次の内容を持つビューで protected_pa​​ge.pug という新しいファイルを作成します-

html
   head
      title Protected page
   body
      div Hey #{id}, How are you doing today?
      div Want to log out?
      div Logout

このページは、ユーザーがサインアップまたはログインしたばかりの場合にのみ表示されます。 次に、そのルートと、ログインおよびログアウトするルートを定義しましょう-

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var session = require('express-session');
var cookieParser = require('cookie-parser');

app.set('view engine', 'pug');
app.set('views','./views');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Your secret key"}));

var Users = [];

app.get('/signup', function(req, res){
   res.render('signup');
});

app.post('/signup', function(req, res){
   if(!req.body.id || !req.body.password){
      res.status("400");
      res.send("Invalid details!");
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id){
            res.render('signup', {
               message: "User Already Exists! Login or choose another user id"});
         }
      });
      var newUser = {id: req.body.id, password: req.body.password};
      Users.push(newUser);
      req.session.user = newUser;
      res.redirect('/protected_page');
   }
});
function checkSignIn(req, res){
   if(req.session.user){
      next();    //If session exists, proceed to page
   } else {
      var err = new Error("Not logged in!");
      console.log(req.session.user);
      next(err); //Error, trying to access unauthorized page!
   }
}
app.get('/protected_page', checkSignIn, function(req, res){
   res.render('protected_page', {id: req.session.user.id})
});

app.get('/login', function(req, res){
   res.render('login');
});

app.post('/login', function(req, res){
   console.log(Users);
   if(!req.body.id || !req.body.password){
      res.render('login', {message: "Please enter both id and password"});
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id && user.password === req.body.password){
            req.session.user = user;
            res.redirect('/protected_page');
         }
      });
      res.render('login', {message: "Invalid credentials!"});
   }
});

app.get('/logout', function(req, res){
   req.session.destroy(function(){
      console.log("user logged out.")
   });
   res.redirect('/login');
});

app.use('/protected_page', function(err, req, res, next){
console.log(err);
  //User should be authenticated! Redirect him to log in.
   res.redirect('/login');
});

app.listen(3000);

ユーザーがサインインしているかどうかを確認するミドルウェア関数_checkSignIn_を作成しました。 protected_pa​​ge はこの関数を使用します。 ユーザーをログアウトするには、セッションを破棄します。

ログインページを作成しましょう。 ビューに login.pug という名前を付けて、内容を入力します-

html
   head
      title Signup
   body
      if(message)
         h4 #{message}
         form(action = "/login" method = "POST")
         input(name = "id" type = "text" required placeholder = "User ID")
         input(name = "password" type = "password" required placeholder = "Password")
         button(type = "Submit") Log in

これで、簡単な認証アプリケーションが完成しました。アプリケーションをテストしましょう。 _nodemon index.js_を使用してアプリを実行し、localhost:3000/signupに進みます。

ユーザー名とパスワードを入力し、サインアップをクリックします。 詳細が有効/一意であれば、 protected_pa​​ge にリダイレクトされます-

保護されたページ

次に、アプリからログアウトします。 これにより、ログインページにリダイレクトされます-

認証ログイン

このルートは保護されているため、認証されていないユーザーがアクセスしようとすると、ログインページにリダイレクトされます。 これはすべて基本的なユーザー認証についてでした。 永続セッションシステムを使用し、パスワード転送にハッシュを使用することを常にお勧めします。 JSONトークンを利用して、ユーザーを認証するより良い方法が今あります。

ExpressJS-RESTFul API

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

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 the 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 the request.
DELETE or PUT /movies Invalid Should be invalid. DELETE *and PUT* should specify which resource they are working on.

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

index.js

var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();

var app = express();

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());

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

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

app.listen(3000);

アプリケーションのセットアップが完了したので、APIの作成に集中しましょう。

movies.jsファイルをセットアップすることから始めます。 映画を保存するためにデータベースを使用するのではなく、メモリに保存します。サーバーが再起動するたびに、私たちが追加した映画は消えてしまいます。 これは、データベースまたはファイルを使用して(node fsモジュールを使用して)簡単に模倣できます。

Expressをインポートしたら、ルーターを作成し、_module.exports_を使用してエクスポートします-

var express = require('express');
var router = express.Router();
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('/', function(req, res){
   res.json(movies);
});

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

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,})', function(req, res){
   var currMovie = movies.filter(function(movie){
      if(movie.id == req.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      res.json(currMovie[0])
   } else {
      res.status(404);//Set status to 404 as movie was not found
      res.json({message: "Not Found"});
   }
});

これにより、指定した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ルート

*POSTed* データを処理するには、次のルートを使用します-
router.post('/', function(req, res){
  //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){

      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      var newId = movies[movies.length-1].id+1;
      movies.push({
         id: newId,
         name: req.body.name,
         year: req.body.year,
         rating: req.body.rating
      });
      res.json({message: "New movie created.", location: "/movies/" + newId});
   }
});

これにより、新しいムービーが作成され、movies変数に保存されます。 このルートを確認するには、端末に次のコードを入力します-

curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" http://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', function(req, res){
  //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !req.params.id.toString().match(/^[0-9]{3,}$/g)){

      res.status(400);
      res.json({message: "Bad Request"});
   } else {
     //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(req.params.id));

      if(updateIndex === -1){
        //Movie not found, create new
         movies.push({
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         });
         res.json({message: "New movie created.", location: "/movies/" + req.params.id});
      } else {
        //Update existing movie
         movies[updateIndex] = {
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         };
         res.json({message: "Movie id " + req.params.id + " updated.",
            location: "/movies/" + req.params.id});
      }
   }
});

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

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

応答

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

ルートを削除

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

router.delete('/:id', function(req, res){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(req.params.id);//Gets us the index of movie with given id.

   if(removeIndex === -1){
      res.json({message: "Not found"});
   } else {
      movies.splice(removeIndex, 1);
      res.send({message: "Movie id " + req.params.id + " removed."});
   }
});

他のルートをチェックしたのと同じ方法でルートをチェックします。 削除に成功すると(たとえばid 105)、次の出力が得られます-

{message: "Movie id 105 removed."}

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

var express = require('express');
var router = express.Router();
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}
];
router.get('/:id([0-9]{3,})', function(req, res){
   var currMovie = movies.filter(function(movie){
      if(movie.id == req.params.id){
         return true;
      }
   });

   if(currMovie.length == 1){
      res.json(currMovie[0])
   } else {
      res.status(404); //Set status to 404 as movie was not found
      res.json({message: "Not Found"});
   }
});
router.post('/', function(req, res){
  //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      var newId = movies[movies.length-1].id+1;
      movies.push({
         id: newId,
         name: req.body.name,
         year: req.body.year,
         rating: req.body.rating
      });
      res.json({message: "New movie created.", location: "/movies/" + newId});
   }
});

router.put('/:id', function(req, res) {
  //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !req.params.id.toString().match(/^[0-9]{3,}$/g)){
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
     //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(req.params.id));

      if(updateIndex === -1){
        //Movie not found, create new
         movies.push({
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         });
         res.json({
            message: "New movie created.", location: "/movies/" + req.params.id});
      } else {
        //Update existing movie
         movies[updateIndex] = {
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         };
         res.json({message: "Movie id " + req.params.id + " updated.",
            location: "/movies/" + req.params.id});
      }
   }
});

router.delete('/:id', function(req, res){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(req.params.id);//Gets us the index of movie with given id.

   if(removeIndex === -1){
      res.json({message: "Not found"});
   } else {
      movies.splice(removeIndex, 1);
      res.send({message: "Movie id " + req.params.id + " removed."});
   }
});
module.exports = router;

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

ExpressJS-足場

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

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

npm install -g yeoman

Yeomanは、ジェネレーターを使用してアプリケーションの足場を作ります。 Yeomanで使用する npm で利用可能なジェネレーターを確認するには、このhttp://yeoman.io/generators/[リンク]をクリックしてください。 このチュートリアルでは、_ 'generator-Express-simple'_を使用します。 このジェネレータをインストールするには、端末で次のコマンドを入力します-

npm install -g generator-express-simple

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

yo express-simple test-app

アプリで使用するものなど、いくつかの簡単な質問が表示されます。 次の回答を選択するか、これらのテクノロジーについて既に知っている場合は、それらのテクノロジーを選択してください。

express-simple comes with bootstrap and jquery
[?] Select the express version you want: 4.x
[?] Do you want an mvc express app: Yes
[?] Select the css preprocessor you would like to use: sass
[?] Select view engine you would like to use: jade
[?] Select the build tool you want to use for this project: gulp
[?] Select the build tool you want to use for this project: gulp
[?] Select the language you want to use for the build tool: javascript
   create public/sass/styles.scss
   create public/js/main.js
   create views/layout.jade
   create views/index.jade
   create views/404.jade
   create app.js
   create config.js
   create routes/index.js
   create package.json
   create bower.json
identical .bowerrc
identical .editorconfig
identical .gitignore
identical .jshintrc
   create gulpfile.js

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

次に、新しいアプリケーションを作成し、すべての依存関係をインストールし、アプリケーションにいくつかのページ(ホームページ、404ページが見つかりませんなど)を追加し、作業するディレクトリ構造を提供します。

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

ExpressJS-エラー処理

Expressのエラー処理はミドルウェアを使用して行われます。 しかし、このミドルウェアには特別な特性があります。 エラー処理ミドルウェアは、他のミドルウェア関数と同じ方法で定義されますが、エラー処理関数* MUSTには3つではなく4つの引数*があります( err、req、res、next )。 たとえば、エラーに対して応答を送信するには、次のように使用できます-

app.use(function(err, req, res, next) {
   console.error(err.stack);
   res.status(500).send('Something broke!');
});

これまで、ルート自体のエラーを処理していました。 エラー処理ミドルウェアにより、エラーロジックを分離し、それに応じて応答を送信できます。 ミドルウェアで説明したnext()メソッドは、次の*ミドルウェア/ルートハンドラ*に移動します。

エラー処理のために、* next(err)*関数があります。 この関数を呼び出すと、すべてのミドルウェアがスキップされ、そのルートの次のエラーハンドラーに一致します。 例を通してこれを理解しましょう。

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

app.get('/', function(req, res){
  //Create an error and pass it to the next function
   var err = new Error("Something went wrong");
   next(err);
});

/*
 *other route handlers and middleware here
* ....
 */

//An error handling middleware
app.use(function(err, req, res, next) {
   res.status(500);
   res.send("Oops, something went wrong.")
});

app.listen(3000);

このエラー処理ミドルウェアは、ルートの後に戦略的に配置するか、エラータイプを検出し、それに応じてクライアントに応答する条件を含めることができます。 上記のプログラムは、次の出力を表示します。

エラー処理

ExpressJS-デバッグ

Expressはhttps://www.npmjs.com/package/debug[Debug]モジュールを使用して、ルートマッチング、ミドルウェア機能、アプリケーションモードなどに関する情報を内部的に記録します。

Expressで使用されるすべての内部ログを表示するには、アプリの起動時にDEBUG環境変数を* Express:**に設定します-

DEBUG = express:* node index.js

次の出力が表示されます。

デバッグログ

これらのログは、アプリのコンポーネントが正しく機能していない場合に非常に役立ちます。 この詳細な出力は、少々圧倒されるかもしれません。 ログに記録する特定の領域にDEBUG変数を制限することもできます。 たとえば、ロガーをアプリケーションとルーターに制限する場合は、次のコードを使用できます。

DEBUG = express:application,express:router node index.js

デバッグはデフォルトでオフになっており、実稼働環境では自動的にオンになります。 デバッグは、ニーズに合わせて拡張することもできます。詳細については、https://www.npmjs.com/package/debug [its npm page。]をご覧ください。

ExpressJS-ベストプラクティス

DjangoやRailsが物事やファイル構造などを定義した方法とは異なり、Expressは定義された方法に従っていません。 これは、好きな方法でアプリケーションを構築できることを意味します。 しかし、アプリケーションのサイズが大きくなると、明確に定義された構造を持っていない場合、それを維持することは非常に困難です。 この章では、アプリケーションを構築するために一般的に使用されるディレクトリ構造と懸念事項の分離について説明します。

最初に、ノードおよびExpressアプリケーションを作成するためのベストプラクティスについて説明します。

  • 常に npm init を使用してノードプロジェクトを開始します。
  • 依存関係は常に*-save または-save-dev *でインストールしてください。 これにより、別のプラットフォームに移動した場合、_npm install_を実行してすべての依存関係をインストールできます。
  • 小文字のファイル名とcamelCase変数に固執します。 npmモジュールを見ると、名前は小文字でダッシュで区切られています。 これらのモジュールが必要な場合は、いつでもキャメルケースを使用してください。
  • node_modulesをリポジトリにプッシュしないでください。 代わりに、npmは開発マシンにすべてをインストールします。
  • config ファイルを使用して変数を保存する
  • ルートを独自のファイルにグループ化および分離します。 たとえば、REST APIページで見た映画の例のCRUD操作を取り上げます。

ディレクトリ構造

次に、Expressのディレクトリ構造について説明します。

ウェブサイト

Expressには、アプリケーションを作成するためのコミュニティ定義の構造がありません。 以下は、Webサイトで主に使用されるプロジェクト構造です。

test-project/
   node_modules/
   config/
      db.js               //Database connection and configuration
      credentials.js      //Passwords/API keys for external services used by your app
      config.js           //Other environment variables
   models/               //For mongoose schemas
      users.js
      things.js
   routes/               //All routes for different entities in different files
      users.js
      things.js
   views/
      index.pug
      404.pug
        ...
   public/               //All static content being served
      images/
      css/
      javascript/
   app.js
   routes.js              //Require all routes in this and then require this file in
   app.js
   package.json

Expressを使用してWebサイトを構築する方法は他にもあります。 MVCデザインパターンを使用してWebサイトを構築できます。 詳細については、次のリンクをご覧ください。

[[1]]

and,

[[2]]

RESTful API

APIは設計が簡単です。パブリックまたはビューのディレクトリは必要ありません。 次の構造を使用してAPIを構築します-

test-project/
   node_modules/
   config/
      db.js               //Database connection and configuration
      credentials.js      //Passwords/API keys for external services used by your app
   models/               //For mongoose schemas
      users.js
      things.js
   routes/               //All routes for different entities in different files
      users.js
      things.js
   app.js
   routes.js              //Require all routes in this and then require this file in
   app.js
   package.json

yeoman generatorを使用して同様の構造を取得することもできます。

ExpressJS-リソース

この章では、このチュートリアルで使用したさまざまなリソースをリストします。