Node.js express-validatorで入力値の検証を行う
express.jsでwebアプリケーションを作成。postされた値の入力チェックを行う際はexpress-validatorが便利です。
https://express-validator.github.io/docs/
使い方を見てみます。
ベースのアプリケーション
入力値チェックを行う前の基本的なアプリケーションとして、
名前(name)とメールアドレス(email)をサーバーにpostするプログラムを作成しました。
テンプレートエンジンにはejsを使用しています。
expressとejsをインストール。
$ npm install express ejs
・server.js
- const express = require('express');
- const app = express();
- const port = 3000;
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- app.post('/regist', async (req, res, next) => {
- // ここで入力値の検証を行いたい
- console.log(req.body.name);
- console.log(req.body.email);
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });
・views/index.ejs
- <!DOCTYPE html>
- <html lang="ja">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
- <title>validatorサンプル</title>
- </head>
- <body>
- <form method="post" action="regist">
- <div>
- 名前:<input type="text" name="name">
- </div>
- <div>
- メールアドレス:<input type="text" name="email">
- </div>
- <div>
- <input type="submit" value="登録">
- </div>
- </form>
- </body>
- </html>

このアプリケーションにexpress-validatorによる入力値の検証を追加してみます。
express-validator
express-validatorをインストールします。
$ npm install express-validator
こちらを参考に処理を追加しました。
https://express-validator.github.io/docs/
・server.js
- const express = require('express');
- const app = express();
- const port = 3000;
- const { body, validationResult } = require('express-validator');
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- app.post('/regist',
- body('name').isLength({ min: 1, max: 10 }), // nameは1文字以上10文字以下
- body('email').isEmail(), // emailはメールアドレス形式
- async (req, res, next) => {
- // エラーの状況を取得
- const errors = validationResult(req);
- // エラーが発生していたら内容を取得し、画面に表示
- if (!errors.isEmpty()) {
- res.render('index.ejs', {errors: errors.array()});
- return;
- }
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });
errors.array()で得られる内容は以下のような配列です。
- [
- { value: '', msg: 'Invalid value', param: 'name', location: 'body' },
- { value: '', msg: 'Invalid value', param: 'email', location: 'body' }
- ]
エラー発生時、内容を表示する処理をview側に追加します。
・views/index.ejs
- <!DOCTYPE html>
- <html lang="ja">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
- <title>validatorサンプル</title>
- </head>
- <body>
- <form method="post" action="regist">
- <div>
- 名前:<input type="text" name="name">
- </div>
- <div>
- メールアドレス:<input type="text" name="email">
- </div>
- <% if (typeof errors !== 'undefined') { %>
- <div>
- <ul>
- <% for (const error of errors) { %>
- <li><%= error.param %>:<%= error.msg %></li>
- <% } %>
- </ul>
- </div>
- <% } %>
- <div>
- <input type="submit" value="登録">
- </div>
- </form>
- </body>
- </html>
名前、メールアドレス共に空白のまま登録ボタンを押すと、エラーが表示されました。

検証ルールをまとめる
app.postの引数に検証ルールを直接記載せず、配列にまとめておいて指定することも可能です。
- const express = require('express');
- const app = express();
- const port = 3000;
- const { body, validationResult } = require('express-validator');
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- // ルールを配列でまとめる
- const registValidator = [
- body('name').isLength({ min: 1, max: 10 }), // nameは1文字以上10文字以下,
- body('email').isEmail(), // emailはメールアドレス形式
- ];
- app.post('/regist',
- registValidator,
- async (req, res, next) => {
- // エラーの状況を取得
- const errors = validationResult(req);
- // エラーが発生していたら内容を取得し、画面に表示
- if (!errors.isEmpty()) {
- res.render('index.ejs', {errors: errors.array()});
- return;
- }
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });
リストには、(req, res, next)の引数を持つ関数を割り当てればよいので、
こんな感じで、エラー処理もまとめてしまうことも可能です。
- const express = require('express');
- const app = express();
- const port = 3000;
- const { body, validationResult } = require('express-validator');
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- // ルールを配列でまとめる
- const registValidator = [
- body('name').isLength({ min: 1, max: 10 }), // nameは1文字以上10文字以下,
- body('email').isEmail(), // emailはメールアドレス形式
- // エラー処理まで行ってしまう
- async(req, res, next) => {
- // エラーの状況を取得
- const errors = validationResult(req);
- // エラーが発生していたら内容を取得し、画面に表示
- if (!errors.isEmpty()) {
- res.render('index.ejs', {errors: errors.array()});
- return;
- }
- // エラーが無ければnext呼び出し
- next();
- },
- ];
- app.post('/regist',
- registValidator,
- async (req, res, next) => {
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });
メッセージの日本語化
エラーメッセージの内容はwithMessageで指定可能です。
- const express = require('express');
- const app = express();
- const port = 3000;
- const { body, validationResult } = require('express-validator');
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- // ルールを配列でまとめる
- const registValidator = [
- // nameは1文字以上10文字以下
- body('name').isLength({ min: 1, max: 10 }).withMessage('名前は1文字以上10文字以下で入力してください'),
- // emailはメールアドレス形式
- body('email').isEmail().withMessage('メールアドレスを入力してください'),
- // エラー処理まで行ってしまう
- async(req, res, next) => {
- // エラーの状況を取得
- const errors = validationResult(req);
- // エラーが発生していたら内容を取得し、画面に表示
- if (!errors.isEmpty()) {
- res.render('index.ejs', {errors: errors.array()});
- return;
- }
- // エラーが無ければnext呼び出し
- next();
- },
- ];
- app.post('/regist',
- registValidator,
- async (req, res, next) => {
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });

使用できるルール
validator.jsをラップしたものなので、こちらに掲載されているルールが使用できます。
https://github.com/validatorjs/validator.js
カスタムバリデーション
独自のルールを指定するには、customでルールを追加します。
例として、nameに「admin」は使用できないルールを追加してみます。
- const express = require('express');
- const app = express();
- const port = 3000;
- const { body, validationResult } = require('express-validator');
- app.set('view engine', 'ejs');
- app.use(express.urlencoded({ extended: true }));
- app.get('/', async (req, res, next) => {
- res.render('index.ejs')
- });
- // ルールを配列でまとめる
- const registValidator = [
- // nameは1文字以上10文字以下
- body('name')
- .isLength({ min: 1, max: 10 }).withMessage('名前は1文字以上10文字以下で入力してください')
- .custom(value => {
- // 独自ルール追加
- if (value === 'admin') {
- throw new Error('名前に「admin」は使用できません')
- }
- return true;
- }),
- // emailはメールアドレス形式
- body('email').isEmail().withMessage('メールアドレスを入力してください'),
- // エラー処理まで行ってしまう
- async(req, res, next) => {
- // エラーの状況を取得
- const errors = validationResult(req);
- // エラーが発生していたら内容を取得し、画面に表示
- if (!errors.isEmpty()) {
- res.render('index.ejs', {errors: errors.array()});
- return;
- }
- // エラーが無ければnext呼び出し
- next();
- },
- ];
- app.post('/regist',
- registValidator,
- async (req, res, next) => {
- res.render('index.ejs');
- });
- app.listen(port, () => {
- console.log(`Example app listening at http://localhost:${port}`);
- });
