express routing

# express routing

## 基本

```
app.METHOD(PATH, HANDLER)
```

- app    : expressのインスタンス
- METHOD : post, get, put ...（HTTPメソッドを小文字にしたもの）
- PATH   : サーバ上のパス（URLのパス？）
- HANDLER: URLがPATHとマッチしたしたときに実行するメソッド

## 基本サンプル

- 基本はHTTPメソッド毎に、処理（メソッド）を割り当てる

```
// GET メソッドルート
app.get('/', function (req, res) {
  res.send('GET request to the homepage')
})

// POST メソッドルート
app.post('/', function (req, res) {
  res.send('POST request to the homepage')
})
```

- すべてのHTTPメソッドを割り当てる

```
// 共通処理を仕込んでメソッド毎の処理はnext()で処理する
app.all('/secret', function (req, res, next) {
  console.log('accessing the secret section ...')
  next()
})
```

- 簡略化: app.route()

同じURLをメソッドごとに指定しなくて済むので間違いが少なくなるメリットがある

```
app.route('/')
  .get(function (req, res) {
    res.send('GET request to the homepage')
  })
  .post('/', function (req, res) {
    res.send('POST request to the homepage')
  })
```


## パス指定

- 正規表現で指定ができる。

```
// 通常
app.get('/', function (req, res) {
  res.send('root')
})


// ?: 直前の文字が0個または1個
// +: 直前の文字が1個以上
// *: 0個以上の文字列

// /acd, /abcd がヒットする
app.get('/ab?cd', function (req, res) {
})

// /abcd, /abbcd, /abbbcd がヒットする
app.get('/ab+cd', function (req, res) {
})

// /abcd, /abxcd, /abPEKEPEKEcd がヒットする
app.get('/ab*cd', function (req, res) {
})


// 正規表現
// /butterfly , /dragonfly がヒットする
app.get('/.*fly$/', function (req, res) {
})

```


## パラメータ指定

- URLで指定した文字列をパラメータとして受け取ることができる。
  ":"付きでパラメータ指定をしておくと、**reqest.params** で参照できる。

```
app.get('/users/:userId/books/:bookId', function (req, res) {
  // http://localhost:3000/users/34/books/8989
  res.send(req.params) // {"userId": "34", "bookId": "8989"}
})
```

- 区切り文字("-", ".")

```
// ハイフン
app.get('/flights/:from-:to', function (req, res) {
  // http://localhost:3000/flights/LAX-SFO
  res.send(req.params) // {"from": "LAX", "to": "SFO"}
})

// ドット
app.get('/plantae/:genus.:species', function (req, res) {
  // http://localhost:3000/plantae/Prunus.persica
  res.send(req.params) // {"genus": "Prunus", "species": "persica"}
})
```

- 正規表現による指定
  カッコで括って指定可能文字列を絞ることができる
  **※バックスラッシュが文字列でエスケープされるので注意**

```
// userId には数字のみ
app.get('/user/:userId(\\d+)', function (req, res) {
  // http://localhost:3000/user/42
  res.send(req.params) // {"userId": "42"}
})
```


## ルートハンドラー

ハンドラで指定するコールバックメソッドの第3引数であるnext()を実行すると
次の順番のハンドラが数珠つなぎのように実行される。
ハンドラの順番の指定は以下のようになる。

- ハンドラを順番に第4引数以降に順に定義する
- 関数化しておいて、ハンドラで配列として定義する

```
// ハンドラで順に定義
app.get('/example/b', function (req, res, next) {
  console.log('first')
  next()
}, function (req, res) {
  console.log('second')
  res.send('Hello from B!')
})

// 関数を作成し、配列で指定
var cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}
var cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}
var cb2 = function (req, res) {
  console.log('CB2')
  res.send('Hello from C!')
}
app.get('/example/c', [cb0, cb1, cb2])

// 上記のMIX
app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('third')
  next()
}, function (req, res) {
  console.log('forth')
  res.send('Hello from D!')
})
```


## ルータの別ファイル化

express.Router クラスを使うことでルータ処理を別ファイルに記述することができる。
処理が多い場合に見やすさを確保できる？

```
// birds.js
var express = require('express')
var router = express.Router()

// 以後は router を使用して上記appと同じ様に扱える
router.use(function timelog(req, res, next){
  console.log('Time:', Date.now())
  next()
})

// URL は相対位置になるので、
// http://localhost:3000/birds/ を指定したときに実行される
router.get('/', function(req, res){
  res.send('Birds Home Page')
})

// http://localhost:3000/birds/about
router.get('/about', function(req, res){
  res.send('About Birds')
})

module.exports = router
```

```
// app.js
var birds = require('./birds')
app.use('/birds', birds)
```