Node.js + Express のプログラミング環境で作ったアプリケーションで、「全てのリクエストに対する共通の前処理」を行う方法を紹介します。
Node.js + Express を使って HTTP リクエストを処理するアプリケーションの例として以下のようなコードを想定します(ルーティングを使っていませんが、使っている場合でも同様に可能です):
上記例では GET /, GET /hello, POST /hello という3種類の HTTP リクエストに対するハンドラが定義されていて、それぞれに対応する異なる処理が個別に行われるようになっています。HTTP リクエストはもっと多くても少なくても構いません。
このような条件下において「全ての HTTP リクエストに対して、リクエストパラメータに id=XXX が含まれていたら、それを記録する」という処理を追加したい場合にどうするか? というのが今回のお題です。その実装例が以下赤字部分です(以下ではシンプルに id の値を記録ではなく表示しているだけです):
app.use( '/path', function( req, res, next ){ ... } ); で /path への全 HTTP リクエスト(GET, POST, PUT, DELETE, ..)のハンドラを用意します。この /path 部分を '/*' とすることで全てのパスへの全てのリクエストに対するハンドラが定義できます。
このハンドラの中で id=XXXX というパラメータが指定されているかを調べ、指定されていたらその値(req.query.id)を取り出して表示しています。実際にはここで取り出した id 値を表示するだけでなく、記録したり、別の処理に使ったりすることを想定しています。
この処理で最も大事なのは最後に next(); を実行していることです。シングルスレッド処理の Node.js ではこれでハンドリング処理を終了とするのではなく、「次の処理へ」と指示することで個別のハンドラへの処理も行わせています。これによって共通の事前処理をした上で、個別処理も行う、という実装が可能になります。
Node.js + Express を使って HTTP リクエストを処理するアプリケーションの例として以下のようなコードを想定します(ルーティングを使っていませんが、使っている場合でも同様に可能です):
var express = require( 'express' ); var bodyParser = require( 'body-parser' ); var app = express(); app.use( bodyParser.urlencoded( { extended: true, limit: '10mb' } ) ); app.use( bodyParser.json() ); app.get( '/', function( req, res ){ res.contentType( 'application/json; charset=utf-8' ); res.write( JSON.stringify( { status: true, message: 'get /' }, 2, null ) ); res.end(); }); app.get( '/hello', function( req, res ){ res.contentType( 'application/json; charset=utf-8' ); res.write( JSON.stringify( { status: true, message: 'get /hello.' }, 2, null ) ); res.end(); }); app.post( '/hello', function( req, res ){ res.contentType( 'application/json; charset=utf-8' ); res.write( JSON.stringify( { status: true, message: 'post /hello.' }, 2, null ) ); res.end(); }); var port = process.env.port || 3000; app.listen( port ); console.log( 'server started on ' + port );
上記例では GET /, GET /hello, POST /hello という3種類の HTTP リクエストに対するハンドラが定義されていて、それぞれに対応する異なる処理が個別に行われるようになっています。HTTP リクエストはもっと多くても少なくても構いません。
このような条件下において「全ての HTTP リクエストに対して、リクエストパラメータに id=XXX が含まれていたら、それを記録する」という処理を追加したい場合にどうするか? というのが今回のお題です。その実装例が以下赤字部分です(以下ではシンプルに id の値を記録ではなく表示しているだけです):
var express = require( 'express' );
var bodyParser = require( 'body-parser' );
var app = express();
app.use( bodyParser.urlencoded( { extended: true, limit: '10mb' } ) );
app.use( bodyParser.json() );
//. 全てのリクエストに対して前処理
app.use( '/*', function( req, res, next ){
//. HTTP リクエスト URL に id=XXX というパラメータが含まれていたら表示する
var id = req.query.id;
if( id ){
console.log( 'id: ' + id );
}
next(); //. 個別処理へ
});
app.get( '/', function( req, res ){
res.contentType( 'application/json; charset=utf-8' );
res.write( JSON.stringify( { status: true, message: 'get /' }, 2, null ) );
res.end();
});
app.get( '/hello', function( req, res ){
res.contentType( 'application/json; charset=utf-8' );
res.write( JSON.stringify( { status: true, message: 'get /hello.' }, 2, null ) );
res.end();
});
app.post( '/hello', function( req, res ){
res.contentType( 'application/json; charset=utf-8' );
res.write( JSON.stringify( { status: true, message: 'post /hello.' }, 2, null ) );
res.end();
});
var port = process.env.port || 3000;
app.listen( port );
console.log( 'server started on ' + port );
app.use( '/path', function( req, res, next ){ ... } ); で /path への全 HTTP リクエスト(GET, POST, PUT, DELETE, ..)のハンドラを用意します。この /path 部分を '/*' とすることで全てのパスへの全てのリクエストに対するハンドラが定義できます。
このハンドラの中で id=XXXX というパラメータが指定されているかを調べ、指定されていたらその値(req.query.id)を取り出して表示しています。実際にはここで取り出した id 値を表示するだけでなく、記録したり、別の処理に使ったりすることを想定しています。
この処理で最も大事なのは最後に next(); を実行していることです。シングルスレッド処理の Node.js ではこれでハンドリング処理を終了とするのではなく、「次の処理へ」と指示することで個別のハンドラへの処理も行わせています。これによって共通の事前処理をした上で、個別処理も行う、という実装が可能になります。