サーチ…


前書き

Expressは、最小限で柔軟なNode.js Webアプリケーションフレームワークであり、Webアプリケーションを構築するための強力な機能を提供します。

Expressの公式ウェブサイトはexpressjs.comです。ソースはGitHubにあります

構文

  • app.get(path [、middleware]、コールバック[、コールバック...])
  • app.put(path [、middleware]、コールバック[、コールバック...])
  • app.post(path [、middleware]、コールバック[、コールバック...])
  • app ['delete'](パス[、ミドルウェア]、コールバック[、コールバック...])
  • app.use(path [、middleware]、コールバック[、コールバック...])
  • app.use(コールバック)

パラメーター

パラメータ詳細
path 指定されたコールバックが処理するパス部分またはURLを指定します。
middleware コールバックの前に呼び出される1つ以上の関数。基本的に、複数のcallback関数の連鎖。権限やエラー処理など、より具体的な処理に役立ちます。
callback 指定されたpathへの要求を処理するために使用される関数。それは次のように呼び出されるcallback(request, response, next)requestresponse 、およびnext 、以下に記載されています。
コールバック request コールバックが処理するために呼び出されているHTTPリクエストに関する詳細をカプセル化しているオブジェクトです。
response サーバーが要求にどのように応答するかを指定するために使用されるオブジェクト。
next 次の一致するルートに制御を渡すコールバック。オプションのエラーオブジェクトを受け入れます。

入門

最初にディレクトリを作成し、シェルにアクセスし、 npmを使用してExpressをインストールする必要がありますnpm install express --save

ファイルを作成し、 app.jsという名前を付け、次のコードを追加して新しいExpressサーバーを作成し、 app.getメソッドを使用してそのサーバーに1つのエンドポイント( /ping )を追加します。

const express = require('express');

const app = express();

app.get('/ping', (request, response) => {
    response.send('pong');
});

app.listen(8080, 'localhost');

スクリプトを実行するには、シェルで次のコマンドを使用します。

> node app.js

アプリケーションはlocalhostポート8080で接続を受け付けますapp.listenのhostname引数を省略すると、serverはマシンのIPアドレスとlocalhostで接続を受け入れます。ポートの値が0の場合、オペレーティングシステムは使用可能なポートを割り当てます。

スクリプトが実行されると、それをシェルでテストして、サーバーから期待される応答「pong」を受け取ることを確認できます。

> curl http://localhost:8080/ping
pong

また、Webブラウザを開いてurl http:// localhost:8080 / pingに移動して出力を表示することもできます

基本的なルーティング

まずエクスプレスアプリを作成します:

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

次に、このようなルートを定義することができます:

app.get('/someUri', function (req, res, next) {})

この構造体はすべてのHTTPメソッドに対して機能し、最初の引数としてパスが必要であり、そのパスのハンドラが要求オブジェクトと応答オブジェクトを受け取ります。したがって、基本的なHTTPメソッドの場合、これらはルートです

// GET www.domain.com/myPath
app.get('/myPath', function (req, res, next) {})

// POST www.domain.com/myPath
app.post('/myPath', function (req, res, next) {})

// PUT www.domain.com/myPath
app.put('/myPath', function (req, res, next) {})

// DELETE www.domain.com/myPath
app.delete('/myPath', function (req, res, next) {})

ここでサポートされている動詞の完全なリストを確認できます 。ルートとすべてのHTTPメソッドに対して同じ動作を定義する場合は、次のように使用できます。

app.all('/myPath', function (req, res, next) {}) 

または

app.use('/myPath', function (req, res, next) {})

または

app.use('*', function (req, res, next) {})

// * wildcard will route for all paths

1つのパスに対して複数のルート定義を連鎖させることができます

app.route('/myPath')
  .get(function (req, res, next) {})
  .post(function (req, res, next) {})
  .put(function (req, res, next) {})

任意のHTTPメソッドに関数を追加することもできます。それらは最終コールバックの前に実行され、パラメータ(req、res、next)を引数として取ります。

// GET www.domain.com/myPath
app.get('/myPath', myFunction, function (req, res, next) {})

最後のコールバックを外部ファイルに保存して、1つのファイルにコードを入れすぎないようにすることができます。

// other.js
exports.doSomething = function(req, res, next) {/* do some stuff */};

そしてあなたのルートを含んでいるファイルで:

const other = require('./other.js');
app.get('/someUri', myFunction, other.doSomething);

これはコードをもっときれいにします。

リクエストからの情報の取得

リクエストしているURLから情報を取得する( reqはルートのハンドラ関数内のリクエストオブジェクトであることに注意してください)。このルート定義/settings/:user_idとこの特定の例/settings/32135?field=name考えてみましょう

// get the full path
req.originalUrl // => /settings/32135?field=name

// get the user_id param
req.params.user_id // => 32135     

// get the query value of the field
req.query.field // => 'name'

リクエストのヘッダーを取得することもできます。

req.get('Content-Type')
// "text/plain"

他の情報を取得するのを簡単にするために、ミドルウェアを使用することができます。たとえば、リクエストのボディ情報を取得するには、ボディリクエストの本文を使用可能なフォーマットに変換するbody-parserミドルウェアを使用できます。

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

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

このようなリクエストを考えてみましょう

PUT /settings/32135
{
  "name": "Peter"
}

あなたはこのように投稿された名前にアクセスできます

req.body.name
// "Peter"

同様の方法で、リクエストからクッキーにアクセスできます。また、 クッキーパーサーのようなミドルウェアも必要です

req.cookies.name

モジュラーエクスプレスアプリケーション

高速Webアプリケーションのモジュラルーターファクトリを作成するには:

モジュール:

// greet.js
const express = require('express');

module.exports = function(options = {}) { // Router factory
    const router = express.Router();

    router.get('/greet', (req, res, next) => {
        res.end(options.greeting);
    });

    return router;
};

応用:

// app.js
const express = require('express');
const greetMiddleware = require('./greet.js');

express()
    .use('/api/v1/', greetMiddleware({ greeting:'Hello world' }))
    .listen(8080);

これにより、アプリケーションをモジュール化し、カスタマイズし、コードを再利用できるようにします。

http://<hostname>:8080/api/v1/greetアクセスすると、出力はHello worldなりHello world

より複雑な例

ミドルウェアの工場の利点を示すサービスの例

モジュール:

// greet.js
const express = require('express');

module.exports = function(options = {}) { // Router factory
    const router = express.Router();
    // Get controller
    const {service} = options;

    router.get('/greet', (req, res, next) => {
        res.end(
            service.createGreeting(req.query.name || 'Stranger')
        );
    });

    return router;
};

応用:

// app.js
const express = require('express');
const greetMiddleware = require('./greet.js');

class GreetingService {
    constructor(greeting = 'Hello') {
        this.greeting = greeting;
    }

    createGreeting(name) {
        return `${this.greeting}, ${name}!`;
    }
}

express()
    .use('/api/v1/service1', greetMiddleware({
        service: new GreetingService('Hello'),
    }))
    .use('/api/v1/service2', greetMiddleware({
        service: new GreetingService('Hi'),
    }))
    .listen(8080);

アクセスする際http://<hostname>:8080/api/v1/service1/greet?name=World出力がされますHello, Worldとアクセスしhttp://<hostname>:8080/api/v1/service2/greet?name=Worldは出力がHi, Worldます。

テンプレートエンジンの使用

テンプレートエンジンの使用

次のコードはJadeをテンプレートエンジンとして設定します。 (注:2015年12月現在、Jadeの名前はpug変更されています)。

const express = require('express');  //Imports the express module
const app = express();  //Creates an instance of the express module

const PORT = 3000; //Randomly chosen port

app.set('view engine','jade'); //Sets jade as the View Engine / Template Engine
app.set('views','src/views'); //Sets the directory where all the views (.jade files) are stored.

//Creates a Root Route
app.get('/',function(req, res){
    res.render('index');  //renders the index.jade file into html and returns as a response. The render function optionally takes the data to pass to the view.
});

//Starts the Express server with a callback
app.listen(PORT, function(err) {
    if (!err) {
        console.log('Server is running at port', PORT);
    } else {
        console.log(JSON.stringify(err));
    }
});

同様に、 Handlebarshbs )やejsなどの他のテンプレートエンジンも使用できます。 Template Engineもnpm installてください。ハンドルバーはhbsパッケージ、 jade用にはjadeパッケージ、 ejs用にはejsパッケージがあります。

EJSテンプレートの例

EJS(他のExpressテンプレートと同様)では、サーバーコードを実行し、HTMLからサーバー変数にアクセスできます。
EJSでは、開始タグとして " <% "、終了タグとして " %> "を使用して終了しました。レンダリングパラメータとして渡される変数は、 <%=var_name%>
たとえば、サーバーコードに電源装置アレイがある場合
それを使用してループすることができます

<h1><%= title %></h1>
   <ul>
<% for(var i=0; i<supplies.length; i++) { %>
    <li>
        <a href='supplies/<%= supplies[i] %>'>
            <%= supplies[i] %>
        </a>
    </li>
<% } %>

この例では、サーバー側のコードとHTMLを切り替えるたびに、現在のEJSタグを閉じて後で新しいタグを開く必要があるため、ここではforコマンド内にliを作成してEJSタグを閉じる必要がありましたforの最後に中かっこの新しいタグを作成する
もう一つの例
入力側のデフォルトのバージョンをサーバー側からの変数にする場合は、 <%=
例えば:

 Message:<br>
<input type="text" value="<%= message %>" name="message" required>

ここでは、サーバー側から渡されるメッセージ変数が入力のデフォルト値になります。サーバー側からメッセージ変数を渡さなかった場合、EJSは例外をスローします。 res.render('index', {message: message});を使用してパラメータを渡すことができますres.render('index', {message: message}); (index.ejsというejsファイルの場合)。

EJSタグでは、 ifwhileまたは他のjavascriptコマンドを使用することもできます。

ExpressJSを使用したJSON API

var express = require('express');
var cors = require('cors'); // Use cors module for enable Cross-origin resource sharing

var app = express();
app.use(cors()); // for all routes

var port = process.env.PORT || 8080;

app.get('/', function(req, res) {
    var info = {
        'string_value': 'StackOverflow',
        'number_value': 8476
    }
    res.json(info);

    // or
    /* res.send(JSON.stringify({
        string_value: 'StackOverflow',
        number_value: 8476
    })) */

  //you can add a status code to the json response
   /* res.status(200).json(info) */
})

app.listen(port, function() {
    console.log('Node.js listening on port ' + port)
})

http://localhost:8080/ outputオブジェクトの場合

{
    string_value: "StackOverflow",
    number_value: 8476
}

静的ファイルの提供

Expressを使用してWebサーバーを構築する場合、動的コンテンツと静的ファイルを組み合わせて提供する必要があります。

たとえば、ファイルシステムに保存されている静的ファイルであるindex.htmlとscript.jsがあるとします。

静的ファイルを持つために 'public'という名前のフォルダを使用するのが一般的です。この場合、フォルダ構造は次のようになります。

project root
├── server.js
├── package.json 
└── public
    ├── index.html
    └── script.js

これは、静的ファイルを提供するようにExpressを構成する方法です。

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

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

注:フォルダが設定されると、index.html、script.js、および "public"フォルダ内のすべてのファイルがルートパスで利用可能になります(urlには/public/を指定しないでください)。これは、エクスプレスが構成された静的フォルダに関連するファイルを検索するためです。 仮想パスプレフィックスは 、以下のように指定できます。

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

リソースを/static/ prefixの下で利用できるようにします。

複数のフォルダ

同時に複数のフォルダを定義することは可能です:

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

リソースを提供するとき、Expressは定義順にフォルダーを検査します。同じ名前のファイルの場合は、最初に一致するフォルダのファイルが提供されます。

Django-styleの名前付きルート

大きな問題の1つは、貴重な名前付きルートが、Expressのすぐ外でサポートされていないことです。解決方法は、サポートされているサードパーティ製のパッケージをインストールすることです(たとえば、 express-reverse

npm install express-reverse

あなたのプロジェクトにプラグインしてください:

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

次に、次のように使用します。

app.get('test', '/hello', function(req, res) {
  res.end('hello');
});

このアプローチの欠点は、 高度なルータの使用法に示すように、 route Expressモジュールを使用できないことです。この問題を回避するには、ルータのファクトリにパラメータとしてappを渡す:

require('./middlewares/routing')(app);

それを次のように使用します。

module.exports = (app) => {
    app.get('test', '/hello', function(req, res) {
      res.end('hello');
    });
};

これからは、関数を定義して指定されたカスタム名前空間とマージし、適切なコントローラを指す方法を理解することができます。

エラー処理

基本的なエラー処理

デフォルトでは、Expressはレンダリングする/viewsディレクトリ内の「エラー」ビューを探します。 「エラー」ビューを作成して、エラーを処理するためにビューディレクトリに配置するだけです。エラーには、エラーメッセージ、ステータス、およびスタックトレースが書き込まれます。たとえば、次のようになります。

views / error.pug

html
  body
      h1= message
      h2= error.status
      p= error.stack

高度なエラー処理

ミドルウェア関数スタックの最後に、エラー処理ミドルウェア関数を定義します。これらには、3つの引数(err, req, res, next)代わりに4つの引数があります。

app.js

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;

    //pass error to the next matching route.
    next(err);
});

// handle error, print stacktrace
app.use(function(err, req, res, next) {
    res.status(err.status || 500);

    res.render('error', {
        message: err.message,
        error: err
    });
});

通常のミドルウェア機能と同じように、いくつかのエラー処理ミドルウェア機能を定義することができます。

ミドルウェアと次のコールバックの使用

Expressは、複数のハンドラ間で単一ルートのロジックを切断するために使用できるすべてのルート・ハンドラおよびミドルウェア機能にnextコールバックを渡します。引き数なしでnext()を呼び出すと、次の一致するミドルウェアまたはルートハンドラに続行するようにexpressに指示します。エラーでnext(err)を呼び出すと、エラーハンドラミドルウェアがトリガされます。 next('route')を呼び出すと、現在のルート上の後続のミドルウェアをバイパスし、次の一致するルートにジャンプします。これにより、ドメインロジックを自己完結型でテストが簡単で、保守や変更が容易な再利用可能なコンポーネントに分離することができます。

複数の一致するルート

/api/fooまたは/api/barへのリクエストは、初期ハンドラを実行してメンバを検索し、各ルートの実際のハンドラに制御を渡します。

app.get('/api', function(req, res, next) {
  // Both /api/foo and /api/bar will run this
  lookupMember(function(err, member) {
    if (err) return next(err);
    req.member = member;
    next();
  });
});

app.get('/api/foo', function(req, res, next) {
  // Only /api/foo will run this
  doSomethingWithMember(req.member);
});

app.get('/api/bar', function(req, res, next) {
  // Only /api/bar will run this
  doSomethingDifferentWithMember(req.member);
});

エラーハンドラ

エラーハンドラは、署名function(err, req, res, next)持つミドルウェアです。 app.get('/foo', function(err, req, res, next) )などのルートごとに設定できますが、通常はエラーページをレンダリングする単一のエラーハンドラで十分です。

app.get('/foo', function(req, res, next) {
  doSomethingAsync(function(err, data) {
    if (err) return next(err);
    renderPage(data);
  });
});

// In the case that doSomethingAsync return an error, this special
// error handler middleware will be called with the error as the 
// first parameter.
app.use(function(err, req, res, next) {
  renderErrorPage(err);
});

ミドルウェア

上記の各機能は、実際には要求が定義されたルートと一致するたびに実行されるミドルウェア機能ですが、1つのルートに任意の数のミドルウェア機能を定義できます。これにより、ミドルウェアを別々のファイルで定義し、共通ロジックを複数のルートにわたって再利用することができます。

app.get('/bananas', function(req, res, next) {
  getMember(function(err, member) {
    if (err) return next(err);
    // If there's no member, don't try to look
    // up data. Just go render the page now.
    if (!member) return next('route');
    // Otherwise, call the next middleware and fetch
    // the member's data.
    req.member = member;
    next();
  });
}, function(req, res, next) {
  getMemberData(req.member, function(err, data) {
    if (err) return next(err);
    // If this member has no data, don't bother
    // parsing it. Just go render the page now.
    if (!data) return next('route');
    // Otherwise, call the next middleware and parse
    // the member's data. THEN render the page.
    req.member.data = data;
    next();
  });
}, function(req, res, next) {
  req.member.parsedData = parseMemberData(req.member.data);
  next();
});

app.get('/bananas', function(req, res, next) {
  renderBananas(req.member);
});

この例では、各ミドルウェア機能は、それ自身のファイルまたはファイルの他の場所の変数のいずれかになり、他のルートで再利用できるようになります。

エラー処理

基本的なドキュメントはここにあります

app.get('/path/:id(\\d+)', function (req, res, next) { // please note: "next" is passed
    if (req.params.id == 0) // validate param
        return next(new Error('Id is 0')); // go to first Error handler, see below

    // Catch error on sync operation
    var data;
    try {
        data = JSON.parse('/file.json');
    } catch (err) {
        return next(err);
    }

    // If some critical error then stop application
    if (!data)
        throw new Error('Smth wrong');

    // If you need send extra info to Error handler
    // then send custom error (see Appendix B)
    if (smth)
        next(new MyError('smth wrong', arg1, arg2))

    // Finish request by res.render or res.end
    res.status(200).end('OK');
});    

// Be sure: order of app.use have matter
// Error handler
app.use(function(err, req, res, next)) {
    if (smth-check, e.g. req.url != 'POST') 
        return next(err); // go-to Error handler 2.

    console.log(req.url, err.message);

    if (req.xhr) // if req via ajax then send json else render error-page
        res.json(err);
    else 
        res.render('error.html', {error: err.message});  
});

// Error handler 2
app.use(function(err, req, res, next)) {
    // do smth here e.g. check that error is MyError
    if (err instanceof MyError) {
        console.log(err.message, err.arg1, err.arg2);
    }     
    ...
    res.end();
});

付録A

// "In Express, 404 responses are not the result of an error, 
// so the error-handler middleware will not capture them." 
// You can change it.
app.use(function(req, res, next) {
    next(new Error(404)); 
});

付録B

// How to define custom error
var util = require('util');
...
function MyError(message, arg1, arg2) {
    this.message = message;
    this.arg1 = arg1;
    this.arg2 = arg2;
    Error.captureStackTrace(this, MyError);
}
util.inherits(MyError, Error);
MyError.prototype.name = 'MyError';

フック:任意のreqの前と任意のresの後にコードを実行する方法

app.use()とミドルウェアは "before"に使用でき、 closeイベントとfinishイベントの組み合わせは "after"に使用できます。

app.use(function (req, res, next) {
    function afterResponse() {
        res.removeListener('finish', afterResponse);
        res.removeListener('close', afterResponse);

        // actions after response
    }
    res.on('finish', afterResponse);
    res.on('close', afterResponse);

    // action before request
    // eventually calling `next()`
    next();
});
...
app.use(app.router);

この例は、デフォルトで応答後にログに追加されるロガーミドルウェアです。

この "ミドルウェア"は、注文が問題になるようにapp.router前に使用されていることを確認してください。


オリジナル投稿はこちら

POSTリクエストの処理

app.getメソッドを使用してExpressでリクエストを処理するのと同じように、app.postメソッドを使用してポストリクエストを処理できます。

しかし、POSTリクエストを処理する前に、 body-parserミドルウェアを使用する必要があります。単にPOSTPUTDELETEなどの要求の本体を解析します。

Body-Parserミドルウェアはリクエストの本文を解析し、 req.body利用可能なオブジェクトに変換します

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

const express = require('express');

const app = express();

// Parses the body for POST, PUT, DELETE, etc.
app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: true }));

app.post('/post-data-here', function(req, res, next){

    console.log(req.body); // req.body contains the parsed body of the request.

});

app.listen(8080, 'localhost');

Cookieパーサーでクッキーを設定する

以下は、 cookie-parserモジュールを使用してCookieを設定および読み込む例です。

var express = require('express');
var cookieParser = require('cookie-parser'); // module for parsing cookies
var app = express();
app.use(cookieParser());

app.get('/setcookie', function(req, res){
    // setting cookies
    res.cookie('username', 'john doe', { maxAge: 900000, httpOnly: true });
    return res.send('Cookie has been set');
});

app.get('/getcookie', function(req, res) {
    var username = req.cookies['username'];
    if (username) {
        return res.send(username);        
    }

    return res.send('No cookie found');
});

app.listen(3000);

Expressのカスタムミドルウェア

Expressでは、リクエストのチェックや応答のヘッダーの設定に使用できるミドルウェアを定義できます。

app.use(function(req, res, next){ });    // signature

次のコードは、 userをリクエストオブジェクトに追加し、次の一致するルートにコントロールを渡します。

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

//each request will pass through it
app.use(function(req, res, next){
    req.user = 'testuser';
    next();    // it will pass the control to next matching route
});

app.get('/', function(req, res){
    var user = req.user;
    console.log(user); // testuser
    return res.send(user);
});

app.listen(3000);

Expressでのエラー処理

Expressでは、アプリケーションで発生したエラーを処理する統合エラーハンドラを定義できます。すべてのルートとロジックコードの最後にハンドラを定義します。

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

//GET /names/john
app.get('/names/:name', function(req, res, next){
    if (req.params.name == 'john'){
        return res.send('Valid Name');
    } else{
        next(new Error('Not valid name'));    //pass to error handler
    }
});

//error handler
app.use(function(err, req, res, next){
    console.log(err.stack);    // e.g., Not valid name
    return res.status(500).send('Internal Server Occured');
});

app.listen(3000);

ミドルウェアの追加

ミドルウェア機能は、アプリケーションの要求応答サイクルで要求オブジェクト(req)、応答オブジェクト(res)、および次のミドルウェア機能にアクセスできる機能です。

ミドルウェアの機能は、任意のコードを実行し、 resおよびreqオブジェクトを変更し、応答サイクルを終了し、次のミドルウェアを呼び出すことができます。

非常に一般的なミドルウェアの例はcorsモジュールです。 CORSサポートを追加するには、単にインストールして、それを必要とし、次の行を追加します。

app.use(cors());

ルータまたはルーティング機能の前に

こんにちは世界

ここでは、Expressを使用して基本的なhello worldサーバーを作成します。ルート:

  • '/'
  • '/ wiki'

そして、残りは "404"、つまりページが見つかりません。

'use strict';

const port = process.env.PORT || 3000;

var app = require('express')();
    app.listen(port);

app.get('/',(req,res)=>res.send('HelloWorld!'));
app.get('/wiki',(req,res)=>res.send('This is wiki page.'));
app.use((req,res)=>res.send('404-PageNotFound'));

注:エクスプレスは順番に経路を積み重ね、それぞれの要求に対して順番に処理するため、最終ルートとして404ルートを配置しています。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow