LoginSignup
34
26

More than 5 years have passed since last update.

ExpressのMiddlewareを自作してみる

Last updated at Posted at 2015-03-21

http://expressjs.com/guide/using-middleware.html
expressのmiddlewareに興味がわいたので自作してみます。ですのでまず上記サイトを読むことにしました。

結論

app.use(function (req, res, next) {})
もしくは
app.use router か app.use routers
以下は上記サイトを自分なりに解釈した駄文になります。

Middlewareとは

  • request, response, next を受け取るfunction
  • どんなコードでもいい
  • requestとresponseを変更してよい
  • リクエストを終了してもいい
  • nextを呼びリクエストを続行してもいい
  • リクエストを終了しない場合はnextを必ず呼ぶこと
  • オプションでmiddlewareの対象となるパスを指定できる
  • アプリケーションレベル、ルーターレベル、エラーハンドリング、ビルドイン、サードパティの5種類がある

Application level middleware

  • using app.use()app.VERB()によりexpressインスタンスに紐づけされる。 VERBはgetとか。

全リクエストに紐づけされるmiddlewareの例

// a middleware with no mount path; gets executed for every request to the app
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

紐づけるパスを限定する例

// a middleware mounted on /user/:id; will be executed for any type of HTTP request to /user/:id
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});
// a route and its handler function (middleware system) which handles GET requests to /user/:id
app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

expressで作成したapp.jsのapp.use('/', routes);の前にとりあえず両方を記述してログを見てみました。
/にアクセスした場合

Time: 1426909974303

/user/3にアクセスした場合

Time: 1426909953812
Request Type: GET

できてますね。app.use('/', routes);より前に記述しないと/にアクセスしても実行されないので気を付けて。

またパスに対してmiddlewareを複数登録できるようです。'/user/:id'のmiddlewareを以下のように変更します。

app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

/user/3にアクセス

Time: 1426910635722
Request URL: /user/3
Request Type: GET

できましたね。あと別にバラバラに書いても問題ないみたいです。

app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
});

app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

注意点は途中でsendするmiddlewareなどリクエストを終了するmiddlewareがあると以降のmiddlewareは実行されない点です。


app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
});

app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

//実行されない
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

/user/3にアクセス

Time: 1426910635722
Request URL: /user/3

連続して書いた場合、middlewareはシリーズとして扱われます。この利点はシリーズの途中で実行を中止し、次の他のmiddlewareへ移行できる点です。ただしgetなどのVERBメソッドを使用する必要があります。

app.get('/user/:id', 
  function(req, res, next) {
    console.log('One in Middleware Series:');
    next();
  },
  function(req, res, next) {
    console.log('Two in Middleware Series::');
    next('route');
  },
  function(req, res, next) {
    console.log('Three but never run');
    next();
  }
);

app.get('/user/:id', function (req, res, next) {
  console.log('Another Middleware:');
  next();
});

app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

実行結果

One in Middleware Series:
Two in Middleware Series::
Another Middleware:

Router level middleware

express.Router()に紐づけされる以外はアプリケーションレベルと同じようです。

Error-handling middleware

他と異なり4つの引数を持ちます。
(err, req, res, next)

試しにエラーを強制的に発生させてみます。

app.get('/user/:id', function (req, res, next) {
  throw new Error("err")
  res.send('USER');
});

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

ブラウザ画面 Something broke!
コンソール

Error: err
    at app.use.err.status (/home/ubuntu/workspace/express/demo/app.js:54:9)
    at Layer.handle [as handle_request] (/home/ubuntu/workspace/express/demo/node_modules/express
...

できましたね。
詳しくはhttp://expressjs.com/guide/error-handling.html を参照とのことです。

Built-in middleware

4系からsessionなどの過去に組み込まれていたmiddlewareは全て分離したそうです。ただし静的ファイルを扱う express.staticだけは組み込まれているようです。

Third-party middleware

Expressは最小構成だから必要ならサードパティのミドルウェアで機能追加してねみたいな話でした。

まとめ

app.use(function (req, res, next) {})できればmiddleware作れる。最後まで読む必要なかったな!!
実際つくってみるとRouter返したほうがやりやすいかも。用途によるかな?

34
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
26