やったこと
前回はServerless FrameworkをつかってAPI Gateway + LambdaでAPIを作ってみました。
https://qiita.com/Ntakato/items/d0778ecc03896a0ae196
ただ、validationくらいはできるようにしておきたい
そこで、今回はexpress-validatorを使ってvalidationできるようにしました。
express-validator
express-validator is a set of express.js middlewares that wraps validator.js validator and sanitizer functions.
やってみる
getting startをのぞいてみると
// ...rest of the initial code omitted for simplicity.
const { body, validationResult } = require('express-validator');
app.post(
'/user',
// username must be an email
body('username').isEmail(),
// password must be at least 5 chars long
body('password').isLength({ min: 5 }),
(req, res) => {
// Finds the validation errors in this request and wraps them in an object with handy functions
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
User.create({
username: req.body.username,
password: req.body.password,
}).then(user => res.json(user));
},
);
なるほど、APIの処理本体に入る前にmiddlewaresをかませてvalidationしていますね。
body('username').isEmail()
でusernameがemailなのかをチェックして、emailじゃなかったら
const errors = validationResult(req);
でerrorsにerrorが入って、400エラーにしていますね。
ただ、実用的にはこのような感じでvalidatorをrouterに書いてしまうのは見通しがよくなさそうです。
bodyにvalidationするものが多かったりしたら大変なことになりそうです。
そこで、ここら辺のvalidatorは別ファイルに定義しておいて使うようにしたいなーと思いました。
ということで、以下のようなファイル構成にしてみました。
.
├── app.js
├── local-app.js
├── router.js
├── routes
└── validator.js
コード全体はGitHubに上げておきますが、大事なところは以下
// router.js
const express = require('express')
const router = express.Router()
const validator = require('./validator')
router.get('/v1/fun2', (req, res) => {
res.json({ message: 'Function2!' })
})
router.get('/v1/fun2/user/:id', validator.userId, (req, res) => {
const { id } = req.params
const users = {
'user1': { name: 'Bob', age: 23 },
'user2': { name: 'Alice', age: 20 },
}
res.json({ ...users[id] })
})
module.exports = router
// validator.js
const { param, validationResult } = require('express-validator')
const badRequestErrorHandling = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next()
}
const userId = [
[
param('id').isString(),
param('id').isLength({ min: 5, max: 5 })
],
badRequestErrorHandling
]
module.exports = {
userId
}
これで、ローカル実行で試してみます。
まず、validationがOKな場合
$ curl localhost:3000/v1/fun2/user/user1
{"name":"Bob","age":23}
OKです。
つぎにvalidationがNGの場合
$ curl -i localhost:3000/v1/fun2/user/user11
HTTP/1.1 400 Bad Request
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 86
ETag: ******
Date: Sat, 30 Jan 2021 08:58:02 GMT
Connection: keep-alive
{"errors":[{"value":"user11","msg":"Invalid value","param":"id","location":"params"}]}
ちゃんと400エラーになってますね。
これでvalidationもできるようになりました。