Express Generator で作成されたファイルを触って Express を理解したい4：res, req, next, エラー処理

# 主旨

Express 4.x が対象です。`express app_name --view=pug` として生成されたファイルを見ながら、`express` の仕組みを理解していく。

- この時事は、[Express Generator で作成されたファイルを触って Express を理解したい2：router, pug](https://qiita.com/mml/items/3cc90479df033c0998e4) の続きです。前回の記事では、`app`、`router` の all, get, all などのメソッドの違いと、パスの表記について記述しています。
- この記事では、res, req, next, エラー処理について記述しています。

公式ドキュメントの対応箇所は以下です：
- [Express](https://expressjs.com/ja/api.html)

- Response
 - res.send     : 任意の文字列、データをブラウザに返す。
 - res.render   : テンプレートエンジンを使ってページを生成する。
 - res.sendFile : 任意のファイルをブラウザに返す。
 - res.set    : HTTP レスポンスヘッダを設定する。
 - res.json   : JSON をブラウザに返す。
 - res.end    : あえて何も返さない。
 - res.cookie : cookie を設定する。
 - res.status : HTTP レスポンスコードを設定する。
 - res.locals : レスポンス限定のグローバル変数のように使える変数。
- Request
 - req.query  : URLクエストパラメータの内容を読み出す
 - req.get    : http ヘッダの内容を読み出す
 - req.cookie : cookie を読み出す
 - req.params : パス内の変数(パラメータ) '/:name' の値を読み出す
- next(): 関数の終了後に別の関数を実行させる
- HTTP関連のエラー処理: err

## 前提

以下の記事は、`express-generator` を使って下記のコマンドで `app.js` 以下のファイルを生成していると想定している。

```
$ express appname --view=pug
```

生成されたファイルは以下の通り。

```
project_dir
├── app.js          # アプリのメインファイル
├── bin
│   └── www            # yarn start 時に node bin/www として実行されるファイル
├── package.json       # ライブラリ等の依存関係やバージョン情報を格納したファイル
├── public          # static なファイルを置くフォルダ
│   ├── images         # http://localhost:8000/images 
│   ├── javascripts    # http://localhost:8000/javascripts 
│   └── stylesheets    # http://localhost:8000/stylesheets
│       └── style.css  # http://localhost:8000/stylesheets/style.css
├── routes          # router (ミドルウェア) 置き場
│   ├── index.js       # http://localhost:8000/ (トップページ)
│   └── users.js       # http://localhost:8000/users
└── views           # テンプレートファイル置き場
    ├── error.pug      # エラー時のテンプレート
    ├── index.pug      # index.js 用のテンプレート
    └── layout.pug     # index.pug や error.pug に読みこまれるテンプレート
```

実行時には 8000 番ポートを指定して使うものとする。

```
$ PORT=8000 yarn start
```

実行後、ブラウザで `http://localhost:8000` にアクセスしたときに、下記の表示になっているものとする。

<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F266247%2F8389c9ab-7a60-9055-def6-ccf760c1c19d.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=f25aa30c763746f5bfcaccc475857e38" width="60%"/>

# app.use / app.get  の第二引数 function

express-generator 生成された、`app.js` の `app.use` や `routes/index.js` の `router.get` の第二引数に `function()` が指定されている行がある。

たとえば `routes/index.js` は以下のようになっている。

```routes/index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;
```

`app.use` や `app.get` の第二引数を関数にする場合は、`function(req, res, next){}` という形にすると決まっている(ようだ)。第一引数のパスと URL がマッチしたときに、第二引数の function が実行される。引数には次の意味がある(ようだ)。

- `req`: この変数からブラウザから受けとったリクエストの情報を取得できる。
- `res`: この変数にブラウザに返す情報をセットする。
- `next`: 後述。省略可能。

以下、それぞれの引数について見ていく。
詳しい公式のドキュメントは下記を参照のこと:
- [Request](https://expressjs.com/ja/api.html#req)
- [Response](https://expressjs.com/ja/api.html#res)
- [Express.Static](https://expressjs.com/ja/api.html#express.static) この項目に next() の説明が少しある。router.all() にも少し説明がある。

## Response (res)

### 文字列をそのまま送る：res.send(str)

ブラウザに文字列を返す基本のメソッド。`str` に指定された文字列がそのままブラウザに返される。引数に、文字列でなくオブジェクトや配列を指定すると、JSON にして返してくれる。

express-generator の出力するファイルでは、`routes/user.js` の中で使われている。

```routes/user.js
var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/ef672b8f-933e-9c6f-8956-5fa4f861ccc4.png)

特に何も指定しないと、ヘッダの 'Content-type' は 'text/html' になるので、HTML タグを書けば HTML としてブラウザでは表示される。

この関数を呼ぶと http ヘッダを出力するので、複数個の `send` を使うとエラーになる。

```users.js
router.get('/', function(req, res, next) {
  res.send('respond with a resource.');
  res.send('second code.');
});
```

```
$ curl http://localhost:8000/users
GET /users 304 5.019 ms - -
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
```

このように、`function` の中で `send` を複数使うと、http ヘッダを複数回出力できないというエラーが出て、2つ目の `send` の内容はブラウザには出力されない。例えば下記のようなコードを書くと、`yarn start` はできるが、URL にアクセスした時にコンソールにエラーが出力される。

エラーを避けるためには、一度の `send` の呼出のみで、出力したい文字列をすべて一度で出力する必要がある。

```users.js
router.get('/', function(req, res, next) {
  var str = "<h1>超Lチカ</h1>";
  str += "<div> ほげほげ </div>";
  res.send('second code.');
});
```

出力に `Buffer` オブジェクトを指定すると、ブラウザに「ファイルをダウンロード」させることができる。たとえば下記のようなコードを書くと、

```users.js
app.get('/hoge.txt', function(req, res, next) {
    res.send(Buffer.from('hogehoge'));
}
```

ブラウザで http://localhost:8000/hoge.txt にアクセスしたとき、ブラウザに直接 "hogehoge" が表示されるのではなく、hoge.txt というファイル名でダウンロードされる。`Content-Type:` は別のコードで指定しない限り、`Content-Type: application/octet-stream` になる。

オブジェクトを指定すると、json を返してくれる。HTTP ヘッダも `Content-Type: application/json` にしてくれる。

```users.js
app.get('/hoge.txt', function(req, res, next) {
    res.send({hoge: 'hogehoge'});
}
```

```
$ curl http://localhost:8000/users
{"name":"hoge"}
```

### テンプレートを使ってHTMLを生成して返す： res.render('file',obj)

'file.pug' をテンプレートとして HTML を出力する.`obj` を指定すると、`obj` に設定された値を pug の変数に設定することができる。express-generator で出力されたファイルでは、`routes/index.js` の中で使用されている。

```routes/index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;
```

使用するテンプレートエンジンの名前と '.pug' を置くディレクトリは、'app.set' で指定しておく必要がある。express-generator で `--view=pug` と指定した場合、`app.js` の中に次のコードが生成される。

```app.js
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
```

このうち、'view engine' の行を消すとエラーになる。一方で 'views' の行を消しても '.pug' ファイルは読みこまれる。テンプレートファイルのデフォルトのディレクトリは 'views' になっているぽい。'views' 以外のディレクトリを指定したい場合は、この行を書きかえる必要がある。

`obj` としては `index.pug` の中で使える変数と値の組を指定できる。これに関しては、[Express Generator で作成されたファイルを触って Express を理解したい2：router, pug](https://qiita.com/mml/items/3cc90479df033c0998e4) この記事で書いたので、ここでは省略する。

```routes/index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
  res.render('index');
});

module.exports = router;
```

上記のコードで、`index.pug` の中の `title` 変数に 'Express' が挿入される。その結果、`render` 実行結果は下記のようになる。

<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F266247%2F8389c9ab-7a60-9055-def6-ccf760c1c19d.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=f25aa30c763746f5bfcaccc475857e38" width="60%"/>

`obj` の代わりに、`res.locals` を使って変数を設定することもできる。

```.js
  res.locals.title = '超Lチカ'
  res.render('index');
```

このコードの実行結果は、

```
res.render('index', { title: '超Lチカ'});
```

このコードと同じ実行結果になる。

### ファイルを返す: res.sendFile

他のファイルを読みこんで、ブラウザに返す。`express.static` と違って、返すファイルが置かれるディレクトリに制限はない。とりあえず試してみる。

`files` ディレクトリを作って、下記の内容で `files/hoge.html` を作っておく。

```files/hoge.html
<!DOCTYPE html>
<html><head></head><body>ほげほげ</body></html>
```

`routes/users.js` を下記のように書きかえる。コードは [res.sendFile](https://expressjs.com/ja/api.html#res.sendFile) の項目のほぼコピー。オプションなどの詳しい情報もリンク先のページにある。

```routes/users.js
var express = require('express');
var router = express.Router(); 
var path = require('path'); // path.join を使うために追加が必要

router.get('/:name', function (req, res, next) {
  var options = {
    // ファイルが置かれているディレクトリを指定する。
    // routes/users.js から ../files を参照するため、../ が必要
    root: path.join(__dirname, '../files'), 
    dotfiles: 'deny',  // . で始まるファイルは送信しない
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  }

  var fileName = req.params.name // :name で指定されたファイル名を読み取る
  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err)
    } else {
      console.log('Sent:', fileName)
    }
  })
})

module.exports = router;
```

http://localhost:8000/users/hoge.html にアクセスすると、`views/hoge.html ` の中身が表示される。

```
$ curl http://localhost:8000/users/hoge.html
<!DOCTYPE html>
<html><head></head><body>ほげほげ</body></html>
```

`Content-Type` は、express が拡張子を見て自動的に設定してくれる。必要があれば、ファイル名を見て自分で `headers` に `Content-Type` を設定することもできる。テキストファイルや html ファイルだけでなく、jpeg や mp4 などのバイナリファイルでも送信できる。

### http ヘッダを設定する: res.set

http ヘッダを設定できる。`Content-type` などを自分で指定したい時などに使う。ためしに `routes/users.js` を以下にように変更してみる。

```users.js
router.get('/', function(req, res, next) {
  res.set('Content-Type', 'text/plain')
  res.send('respond with a resource');
});
```

```
curl --dump-header -  http://localhost:8000/users
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/plain; charset=utf-8
Content-Length: 23
Connection: keep-alive

respond with a resource
```

こんな感じになる。ちなみにデフォルトの `Content-Type` は `text/html`。http ヘッダについては下記を参照のこと。

- [MDN: HTTP ヘッダー](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers)

### json を返す： res.json

オブジェクトを指定すると、JSON 形式でブラウザに返す。

```routes/user.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.json({hoge: 'hoge'})
});

module.exports = router;
```

http://localhost:8000/users にアクセスすると、下記のようになる。

```
$ curl --dump-header -  http://localhost:8000/users
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 15
Connection: keep-alive

{"hoge":"hoge"}
```

Express 4.x からは、内部的には `res.send` でも引数がオブジェクトなら `res.json` をそのまま呼びだしているらしいので、`res.send` でも良いぽい。

```routes/user.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.send({hoge: 'hoge'})
});

module.exports = router;
```

```
$ curl --dump-header -  http://localhost:8000/users
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 15
Connection: keep-alive

{"hoge":"hoge"}
```

`res.send` に書きかえても、完全に同じ結果になる。

### 何も返さない: res.end

http リクエストに対して、何も返したくない場合に使う。

```routes/index.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.end();
});

module.exports = router;
```

http://localhost:8000/users にアクセスすると、下記のように何も返さずに接続が終了する。http ヘッダは返される。

```
$ curl --dump-header -  http://localhost:8000/users
HTTP/1.1 200 OK
X-Powered-By: Express
Connection: keep-alive
Content-Length: 0

$
```

`res.sendFile` でファイルが見つからなかったなどの処理エラー発生時に、ブラウザ側に何も返したくない場合に使う。`res.end` や `res.send` などを書かずに function の処理を終了すると、自動的に 404 エラーが発生し、ブラウザにエラーの発生を知らせてしまう (express-generator で生成した `app.js` の場合)。

### HTTP ステータス (404, 500など) を設定する: res.status

HTTP ステータスコードを設定できる。404 や 500 のコードを強制的に設定できる。

```app.js
app.use('/',function(req, res, next) {
  res.status(404).send(`404エラー`);
});
```

プログラムの最後に、上記のようなコードを書いておくと、どのパスにもマッチしなかった場合に "404エラー" と表示する、簡単なエラー表示ページを作ることができる。

ただし、この関数はコードを設定するだけで Error オブジェクトの作成はしない。そのため、この関数を使ったあとに `next()` 関数を使っても、後述するエラー処理関数 function(err,req,res,next) に処理をさせることはできない。

これについては、エラー処理の項目で後述する。

### Cookie を使う: res.cookie

cookie の設定ができる。

```routes/index.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.cookie('name', 'value', {
    maxAge: 10000,
    httpOnly: false
  }
  res.send('超Lチカ');
});

module.exports = router;
```

http://localhost:8000/ にアクセスすると、下記のようになる。

```
$ curl --dump-header -  http://localhost:8000/
HTTP/1.1 200 OK
X-Powered-By: Express
Set-Cookie: name=value; Max-Age=60; Path=/; Expires=Sat, 20 May 2020 20:20:20 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 10
Connection: keep-alive

超Lチカ
```

cookie を読み出すときは `cookie-parser` と `req.cookies` を使う。`cookie-parser` は express-generator を使ってアプリを生成すると、デフォルトで読みこまれるようになっている。

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

cookie について詳しく書くと長くなるので、ここでは参考文献だけ挙げておく。

- [Express: res.cookie](https://expressjs.com/en/4x/api.html#res.cookie)
- [ExpressでCookieを利用する方法](https://www.wakuwakubank.com/posts/737-nodejs-express-cookie/)

## Request (req)

主にブラウザ側から送られてきた情報が入る変数。この変数を使って URL に付いているパラメータや POST で送られてきた内容、HTTP リクエストヘッダ、cookie などを読み出せる。

### URL パラメータ(クエリパラメータ) を読み出す: req.query

URL で http://localhost:8000?hoge=hogehoge みたいに、`?` の後に書かれる、いわゆる URL パラメータを読み出すことができる。パラメータが存在しないと、undefined になる。

```routes/index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.send(req.query.hoge);
});

module.exports = router;
```

```
$ curl http://localhost:8000?hoge=hogehoge
hogehoge
$ curl http://localhost:8000

$ curl http://localhost:8000?hoge=aaaa
aaaa
$ 
```

クエリパラメータの書式については下記を参照のこと:
- [URL クエリパラメータの正しい設定方法](https://help.webantenna.info/8821/)



### http リクエストヘッダの内容を読み出す: req.get

http リクエストヘッダの内容を読み出せる。対応するヘッダが無いと `undefined` が返される。

```index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  var hoge = req.get('hoge');
  if ( hoge == null ) hoge = '超Lチカ';
  res.send(hoge);
});

module.exports = router;
```

下記のように `hoge: hogehoge` というヘッダを追加して http://localhost:800 にアクセスすると、ヘッダに指定した値 ("hogehoge") が表示される。

```
$ curl --header 'hoge: hogehoge' --dump-header -  http://localhost:8000/
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 8
Connection: keep-alive

hogehoge
```

### パスの中で指定された変数(パラメータ)を読み出す: req.params

`app.use` の第一引数で '/:name' のように `:` 付きで指定されたパラメータにマッチする部分を読み出せる。例:

```routes/users.js
var express = require('express');
var router = express.Router();

router.get('/:name', function(req, res, next) {
  res.send(req.params.name);
});

module.exports = router;
```

これでアプリを実行し、http://localhost:8000/users/xxxx にアクセスすると、"xxxx" と表示される。"xxxx" の部分を変更すると、変更した文字列になる(はず)。パラメータの名前は、英数字とアンダースコアのみが使える。また、パスの中で複数のパラメータを指定することもできる。

詳しくは[Express Generator で作成されたファイルを触って Express を理解したい3：use,get,post,all,パスの表記](https://qiita.com/mml/items/d3299df45ed2b05aaa26)の「余談: URL 中のファイル名を変数に読みこむ」で書いたので、そちらをどうぞ。

## function 終了後にもさらに処理を続ける: next

特定の `app.use` や `app.get` で処理をした後に、続けて別の処理をさせたい時に使います。

```app.js
app.use(function(req,res,next){
  res.locals.title = 'Express 4.x';
  next();
});

app.use('/aaa', function(req,res,next){
  res.render('index');
});

app.use('/bbb', function(req,res,next){
  res.render('index');
});
```

このコードを実行すると、"/aaa" にアクセスしても、"/bbb" にアクセスしても、Express 4.x と表示される。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/4851fc3d-b3a5-ed1b-1e59-a773dad965fc.png" width="60%"/>

最初の `app.use` は、パスの指定がないので、すべてのパスにマッチして `res.locals.title` に "Express 4.x" という文字列を設定している。そのあと `next` 関数を呼ぶことで、さらに続けてパスにマッチする `app.use` や `app.get` をさせることができる。

たとえば "/aaa" という URL でアクセスされたときは、ひとつ目の `app.use` にマッチして処理がなされたあと、さらに `app.use('/aaa', ...)` でもパスにマッチして処理がなされる。

ここで、最初の `function` のコード中の `next()` を削除すると、"/aaa" にアクセスしても 404 エラーが表示されるようになる。これは、最初の `app.use` の中で `res.send` や `res.end` などの、文字列を出力する関数を使わないまま `function` の処理が終了するため、express では結果的に何の文字列も出力されなかったと判断し、エラー処理が実行される。

`next` がある場合は、後続の `app.use('/aaa', ...)` の中で `res.render` が使われ、ページの出力が行なわれているため、エラー処理はなされない。

`next` は、`logger` や `express.static` などの、すべてのパスに対して適用される機能を持つ、ミドルウェア(ライブラリ)の中でよく使われている。すべてのパスに対して適用するような関数やライブラリを書く時には、(おそらく)使う必要がある。

参考:
- [Express.Static](https://expressjs.com/ja/api.html#express.static) この項目に next() の説明が少しある。router.all() にも少し説明がある。

`next` 関数に `err` オブジェクトを引数として渡す場合は、少し違った意味になる。詳しくは下記の「エラー処理」を参照されたい。

## HTTP関連のエラー処理: err

`app.use` 内でエラー処理を行なう時は、`req`, `res`, `next` に加えて `err` の4 つの引数を持つ関数を書く必要がある。引数の順序は `err, req, res, next` と決まっている。これ以外の順序にすると、関数が正常に実行されない。通常のミドルウェアと異なり、4つ目の引数`next` も省略できない

エラー処理関数は、`throw(err)` のようにしてエラーオブジェクトが `throw` された時か、いずれかの関数で `next(err)` のようにエラーオブジェクトを引数とした `next` 関数が呼ばれたときで、なおかつ `app.use` などで指定されたパスにマッチしたときに実行される。



パスにマッチしたとしても、エラーが `throw` されていなければ、処理はなされない。たとえば、

```app.js
app.use('/', function( err, req, res, next ){
  res.send('何が何でもエラー');
});

app.use('/', indexRouter);
```

このように記述し http://localhost:8000/ にアクセスしても、上のエラー処理関数は実行されずに、下の `indexRouter` が実行される。上の関数を処理する段階では、http エラーは発生していない (Error オブジェクトが `throw` されていない) ために、このような処理になる。

一方で、以下のようなコードを書くと、エラー処理がなされるようになる。

```app.js
app.get('/', function (req, res) {
  throw new Error('何が何でもエラー');
})

app.use('/', function( err, req, res, next ){
  res.send(err.message);
});

app.use('/', indexRouter);
```

下記のように `next` を使ってもエラー処理がなされる。next でエラーを投げる時は、**`next` 関数の後に処理を何もかかないこと**。

```app.js
app.get('/', function (req, res,next) {
  next(new Error('何が何でもエラー'));
})

app.use('/', function( err, req, res, next ){
  res.send(err.message);
});

app.use('/', indexRouter);
```

一見すると同じように見えるが、`res.sendFile` のような **非同期関数の中でエラーが発生した場合は `throw` でなく `next` を使え** (そうしないと express がエラーをキャッチできない) と[公式ドキュメントの冒頭](http://expressjs.com/en/guide/error-handling.html#error-handling)に書かれているので、基本的に Error オブジェクトはすべて next 関数で渡したほうがよさそう。どうしても非同期な関数で `throw` を使いたければ `Promise` を使う必要がある。(`Promise` については下記)

- [Promiseについて0から勉強してみた](https://qiita.com/toshihirock/items/e49b66f8685a8510bd76)

この Error オブジェクトを自力で生成しようとすると、エラーコードを正しく設定したり、メッセージを生成するなどの処理を自力で適切に書く必要があり、まあまあ面倒だったりする。Error オブジェクトの生成を楽にする方法として、たとえば`http-errors` の `createError` のようなライブラリの関数を使う方法がある。

express-generator では、デフォルトで `http-errors` モジュールを使う下記のようなエラー処理のコードを生成する。

```app.js
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler； 引数が4つある function はエラー処理関数と認識される。
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
```

`createError(404)` は [http-error モジュール](https://www.npmjs.com/package/http-errors)の関数で、ここより前の `app.use` のいずれでも処理が行われなかった場合に、404 コードを持つ Error オブジェクトを作成する。作成された Error オブジェクトを `next` 関数の引数とすることで、後続のエラー処理関数に処理を実行させる。

そして、`app.js` 内の末尾にある `app.use(function(err, req, res, next)` は、Error オブジェクトが生成されているとき (next 関数に err オブジェクトが渡されているか、Error オブジェクトが throw されているとき)で、なおかつパスにマッチする場合のみ実行される。この `app.use` ではパスは指定されていないので、すべてのパスにマッチする。

関数内の `res.status(err.status || 500)` では、エラーコードがすでに定義されているときはそのままのエラーコードを使い、そうでないときはコードを 500 に設定している。`res.status` は、あくまでHTTP レスポンスコードを設定するだけで、Error オブジェクトの生成を行なってはいない。

エラーの内容は `res.locals.message` と `res.locals.error` にセットされ `error.pug` をテンプレートとして HTML を生成し、ブラウザに返している。これらの処理により、ブラウザにはエラー内容が表示されることになる。

エラー処理関数をプログラム内に全く記述しなかった場合は、`throw` や `next` 関数で渡された Error オブジェクトが`node.js` 内のエラー処理関数で受け取られ、デフォルトのエラーメッセージが表示される。たとえば、404 エラーだと下記のような表示になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/5724ee64-bec9-e8f0-47ff-792ae72fa051.png)

エラー処理について(公式):
- [Express: Error Handling](http://expressjs.com/en/guide/error-handling.html#error-handling)

HTTPレスポンスステータスコードについて:
- [MDN: HTTP レスポンスステータスコード](https://developer.mozilla.org/ja/docs/Web/HTTP/Status)