Node.js + Express (ejsテンプレート) の環境において 404エラーページ と 500エラーページ を カスタムエラーページ にする方法をまとめます。
大きくは「エラー処理の実装」と「エラーページの実装」の2点を行います。
以下ではそれぞれについて詳しく見ていきます。
目次
概要
すべてのファイルを列挙しているわけではありませんが、前提となる主要なフォルダおよびファイルについて列挙します。
想定は以下のような環境です。
プロジェクト構成
PROJECT_ROOT
├ node_modules
│ └ …
├ public
│ └ …
├ routes
│ └ home.js
├ views
│ ├ home
│ │ └ index.js
│ ├ 404.ejs
│ └ 500.ejs
└ app.js
今回作成するのは エラー処理の実装箇所として app.ja
、 エラーページの実装として 404.ejs
および 500.ejs
を作成します。
テンプレートエンジンに "ejs" を利用しているので、エラーページの拡張子も "ejs" です。
エラー処理 の 実装
app.js
var express = require('express');
var fs = require('fs');
// express の実態 Application を生成
var app = express();
// テンプレートエンジンを EJS に設定
app.set('views', './views');
app.set('view engine', 'ejs');
// ルーティング設定
var files = fs.readdirSync('./routes');
for(var file of files){
app.use('/', require('./routes/' + file));
}
// カスタムエラーページ
app.use(function (request, response, next) {
// 出力するデータ
var data = {
method: request.method,
protocol: request.protocol,
version: request.httpVersion,
url: request.url
};
// エラーを返却
response.status(404);
if (request.xhr) {
response.json(data);
} else {
response.render('./404', { data: data });
}
});
app.use(function (error, request, response, next) {
// 出力するデータ
var data = {
method: request.method,
protocol: request.protocol,
version: request.httpVersion,
url: request.url,
name: error.name,
message: error.message,
stack: error.stack
};
response.status(500);
if (request.xhr) {
response.json(data);
} else {
response.render('./500', { data: data });
}
});
// サーバーをポート 3000 で起動
app.listen(3000);
404エラー も 500エラー も app.use
を利用しますが、引数となる関数が異なります。
両者に共通するのは app.js
の中でできるだけ最後の app.use
で記載するようにします。
(上記の例だとルーティング設定よりも後に登録する)
app.use
は上から順に登録および処理がされるので、エラー処理はできるだけ最後に行うよう設定します。
404エラーの場合、 function (request, response, next)
の 3引数 を持つ関数を引数に与えます。
エラーページを返す際、ステータスに 404
を設定して response.render
で返却します。
500エラーの場合、 function (error, request, response, next)
の 4引数 を持つ関数を引数に与えます。
最初の引数は エラーオブジェクト で、エラー名やメッセージ、スタックトレースが含まれています。
エラーページを返す際、400エラーと同様に、ステータスに 500
を設定して response.render
で返却します。
エラーページ の 実装
ページにあまりひねりはありません…単純に必要な情報を表示しています。
ただし、500エラーは開発を想定してエラー名、メッセージ、スタックトレースを出していますが、本番ではこのような情報が出ないようくれぐれも注意してください。
404.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>404 ERROR</title>
<link rel="icon" href="/public/images/favicon.ico" />
<link rel="stylesheet" href="/public/third_party/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="/public/stylesheets/index.css" />
<script type="text/javascript" src="/public/third_party/jquery/dist/jquery.js" defer></script>
<script type="text/javascript" src="/public/third_party/bootstrap/dist/js/bootstrap.js" defer></script>
</head>
<body>
<div class="container">
<h1>404 : Not Found</h1>
<h2>リクエスト</h2>
<table class="table table-bordered">
<tr>
<th class="col-md-2">request</th>
<td class="col-md-10">
<span><%= data.method %></span>
<span> </span>
<span><%= data.url %></span>
<span> </span>
<span><%= (data.protocol || "").toUpperCase() %>/<%= data.version %></span>
</td>
</tr>
</table>
</div>
</body>
</html>
500.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>500 ERROR</title>
<link rel="icon" href="/public/images/favicon.ico" />
<link rel="stylesheet" href="/public/third_party/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="/public/stylesheets/index.css" />
<script type="text/javascript" src="/public/third_party/jquery/dist/jquery.js" defer></script>
<script type="text/javascript" src="/public/third_party/bootstrap/dist/js/bootstrap.js" defer></script>
</head>
<body>
<div class="container">
<h1>500 : Internal Server Error</h1>
<h2>リクエスト</h2>
<table class="table table-bordered">
<tr>
<th class="col-md-2">request</th>
<td class="col-md-10">
<span><%= data.method %></span>
<span> </span>
<span><%= data.url %></span>
<span> </span>
<span><%= (data.protocol || "").toUpperCase() %>/<%= data.version %></span>
</td>
</tr>
</table>
<h2>エラー</h2>
<table class="table table-bordered">
<tr>
<th class="col-md-2">name</th>
<td class="col-md-10"><%= data.name %></td>
</tr>
<tr>
<th>message</th>
<td><%= data.message %></td>
</tr>
<tr>
<th>stack</th>
<td><%= data.stack %></td>
</tr>
</table>
</div>
</body>
</html>
以上が Node.js + Express (ejsテンプレート) でカスタムエラーページを作成する方法です。
これでデフォルトのしょぼいページからは脱却できるはハズ!!