質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1522閲覧

node.jsでexpress-validatorが使えない

lin.ming

総合スコア50

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2019/11/30 10:12

編集2019/12/08 08:31

書籍「入門Node.jsプログラミング」でnode.jsを勉強中です。
本の半ば辺りでわからない箇所が出てきました。

express-validatorを使うのですが、そこでエラーが出ます。
つまづくまでは他のライブラリ(mongoose等)を使っていて、ちゃんと使えたのですが、express-validatorを使うところでエラーが出ます。
Visual Studio CodeのIntellisenseが効かなかったので嫌な予感がしたのですが、案の定実行するとエラーが出ます。

エラーが発生する最小のコードは以下の通りです。

node.js

1const express = require("express"); 2app = express(); 3const router = express.Router(); 4const expressValidator = require("express-validator"); 5 6router.use(expressValidator);

エラーメッセージは以下の通りです。

bash

1/Users/linming/Documents/nodejs/test/node_modules/express/lib/router/index.js:451 2 throw new TypeError('Router.use() requires a middleware function') 3 ^ 4 5TypeError: Router.use() requires a middleware function 6 at Function.use (/Users/linming/Documents/nodejs/test/node_modules/express/lib/router/index.js:451:11) 7 at Object.<anonymous> (/Users/linming/Documents/nodejs/test/index.js:6:8) 8(後略)

package.jsonは以下の通りです。

json

1{ 2 "name": "test", 3 "version": "1.0.0", 4 "description": "", 5 "main": "index.js", 6 "scripts": { 7 "test": "echo \"Error: no test specified\" && exit 1" 8 }, 9 "author": "", 10 "license": "ISC", 11 "dependencies": { 12 "express": "^4.17.1", 13 "express-validator": "^6.3.0", 14 "router": "^1.3.3" 15 } 16}

検証環境は、macOS Mojave 10.14.6、node.jsはv12.10.0です。
バージョンの問題でしょうか?
知見のある方、どうぞよろしくお願いします。

追記
以下のコードを試しました。

node.js

1const http = require("http"); 2const express = require("express"); 3app = express(); 4const router = express.Router(); 5const { check, validationResult } = require('express-validator'); 6 7app.use("/", router); 8 9router.get('/', (req, res) => { 10 res.writeHead(200, { 11 "Content-Type": "text/html" 12 }); 13 let web = "<html><head></head>" + 14 '<body><form action = "/path" name ="form" method = "POST" />' + 15 '<input type = "text" name = "email" />' + 16 '<input type = "submit" name = "submit">' + 17 "</body>" + 18 "</html>" 19 res.write(web); 20 res.end(); 21}); 22 23router.post('/path', [check("email").isEmail()], (req, res) => { 24 const errors = validationResult(req); 25 if (!errors.isEmpty()) { 26 res.status(400).end(); 27 return; 28 } 29 res.status(200).end(); 30}); 31 32app.listen(3000);

コンパイルは通るのですが、メールアドレスを入力しても400エラーになります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

エラー原因は router.use(<ミドルウェア関数>) とすべき箇所を router.use(<オブジェクト>) となっているためですね。

書籍「入門Node.jsプログラミング」でnode.jsを勉強中です。

本の半ば辺りでわからない箇所が出てきました。

NodeJS のモジュールは、OSS です。書籍が出版された時期とは実装が変わる可能性がありますので、gitHUB でモジュールそのものをチェックする必要があります。

express-validator の package.json を確認し、main の場所を確認すると、モジュールとして export されるソースが分かります。そこから、提供される機能を知ることができます(TypeScriptで書かれていました)。

その他、参考程度にはなるということで「express-validator」を検索して「使ってみた系」のブログ記事を覗いてみるのも使い方を広げる手段になるでしょう。
こうした記事も、ブログ記事が書かれた時点の実装に過ぎないことを理解して読みましょう。

追記)
公式からは、第二引数にバリデーションのための引数をArray形式で与えて利用するようです。

const { check, validationResult } = require('express-validator'); app.post('/user', [ // username must be an email check('username').isEmail(), // password must be at least 5 chars long check('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(422).json({ errors: errors.array() }); } User.create({ username: req.body.username, password: req.body.password }).then(user => res.json(user)); });

Routerでも利用された方の記事もありましたので、参考になるかもしれません。

追記2)
まずは「公式ドキュメント」のサンプルコードのような実装を試しましょう。

router.post("/path", [/*重要*/], (req,res)=>{  const errors = validationResult(req); if(!errors.isEmpty()) { // エラー時の処理(ここでは、単に エラーコード 400 で応答) res.status(400).end(); return; } // エラーがなかったときの処理(ここでは、単に エラーコード 200 で応答) res.status(200).end(); })

コード内で 重要 と示した箇所に パラメータに対するバリデーション関数 を与えます。

投稿2019/11/30 16:52

編集2019/12/08 01:38
AkitoshiManabe

総合スコア5432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lin.ming

2019/12/01 20:16 編集

ご親切にありがとうございます。 GitHub の使い方がわからないなりに見てみたのですが、github の package.json で "main": "./src/index.js", とあり、src フォルダをみたのですが、"index.js" はなく、"index.ts" がありました。 TypeScript の読み方がわかりません。 試しに main.js に const expressValidator = require("express-validator"); const { check, validationResult } = require('express-validator'); const { sanitizeBody} = require("express-validator"); を書いたのですが、 req.sanitizeBody("email").normalizeEmail({ の箇所で ERROR occurred: TypeError: req.sanitizeBody is not a function と怒られました。
AkitoshiManabe

2019/12/01 22:10

> TypeScript の読み方がわかりません 私も詳細は分かってないです。が、ドキュメント https://express-validator.github.io/docs/ を確認すると、「ミドルウェア内で利用するユーティリティ関数を提供しているに過ぎず、req を書き換えたりする express 用ミドルウェアというわけではない」様子ですね。ドキュメントの方もご確認ください。
lin.ming

2019/12/02 00:02

英語なのでざっとしか読んでいませんが、コントローラに const {body} = require("express-validator"); const {sanitizeBody} = require("express-validator"); const {check} = require("express-validator"); を追加して、いくつかのエラーを潰したのですが、 getValidationResult() の修正方法がわかりません。(ググってみたのですけど、見つかりませんでした。)
AkitoshiManabe

2019/12/02 07:41

npm でインストールした node_modules/express-validator/src に *.js もあるので、そちらを覗いてみるという手もあります。(コードの変更はしないように注意しましょう)
lin.ming

2019/12/07 05:48

該当パスで grep したのですが、見つけられませんでした・・・。
lin.ming

2019/12/08 00:22

module.exports = { validationResult() .then((error) => { if (!error.isEmpty()) { let messages = error.array().map(e => e.msg); req.skip = true; req.flash("error", messages.join(" and ")); res.locals.redirect = "/users/new"; next(); } else { next(); } }); と書いてみたのですが、 ERROR occurred: TypeError: Cannot read property 'Symbol(express-validator#contexts)' of undefined と表示されます。どのように修正すればよろしいでしょうか?
AkitoshiManabe

2019/12/08 01:41

追記しました。まずは、テスト用のURLを想定してルーターのPathを作り、ドキュメントのサンプルコードを書いてみましょう(そこに立ち戻ったほうが良いです)。
lin.ming

2019/12/08 08:32

質問に追記しました。 コンパイルは通るのですが、メールアドレスを入力しても400エラーになります。
lin.ming

2019/12/08 09:35

はい、ステータスコードを400から500に変えたら500エラーが出たので、きちんとPOSTされていると思います。 しかし、 > router.post('/path', [check("email").normalizeEmail().isEmail()], (req, res) => { と書き換えて、正しいメールアドレスを入力してもエラーになります。
AkitoshiManabe

2019/12/08 10:14

> メールアドレスを入力してもエラーになります。 バリデーションの機能を正しく使えてないだけですので、正しい使い方を見つけましょう。 https://express-validator.github.io/docs/validation-result-api.html#result も試してみましょう if文の直前で console.log( error.mapped() ) としてみて、結果を確認してみるなど。そこからヒントが得られるかもしれません。
lin.ming

2019/12/13 21:39

console.log(errors.mapped()で、{ email: { value: undefined, msg: 'Invalid value', param: 'email', location: 'body' } } と表示されました。 メールアドレスが正しく送られてないのでしょうか?
lin.ming

2020/01/05 09:14

パスが「/」のところで、 '<input type = "text" name = "email" />' + 、「/path」に POST された所に、 router.post('/path', [check("email").isEmail()], (req, res) => { と書いたのですが、 value: undefined が返ってくるということは、validator 云々でなく、もっと基本的なところで間違っているということでしょうか?
AkitoshiManabe

2020/01/05 09:26

errors = validationResult(req); のある関数内で、req をチェックしてみてはどうでしょう。エラーをレスポンスしているので、関数は動いているはずです。nodejs オリジナルの オブジェクトの内容をチェックします。 https://nodejs.org/api/http.html#http_class_http_incomingmessage ---- console.log( req ); // IncomingMessage errors = validationResult(req); //console.log( req );
lin.ming

2020/01/17 23:15

console.log(req) やってみたのですが、大量にログを吐いて、どの項目を見ればいいのかわかりませんでした。 キーワードでも教えていただけるとありがたいのですが。
AkitoshiManabe

2020/01/18 03:51

express (現行) 入れて確認しました。 2点確認事項があります。 1. body-parser モジュールは導入:POST時の validation に必要。 $ npm install body-parser (環境に合わせて-g -s オプション) 2. 開発中 のexpress でbody-parser を有効にする。 app.use( express.urlencoded({ extended:true }) ); 入門書にもとづくご質問でしたのに気が回っておらず、申し訳ありません。 上記、2点、確認してみてください。
lin.ming

2020/01/19 12:01

上記2点実行後、以下のコードでテストしてみました。 ========= const http = require("http"); const express = require("express"); app = express(); const router = express.Router(); const { check, validationResult } = require('express-validator'); app.use( express.urlencoded({ extended:true }) ); app.use("/", router); router.get('/', (req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); let web = "<html><head></head>" + '<body><form action = "/path" name ="form" method = "POST" />' + '<input type = "text" name = "email" />' + '<input type = "submit" name = "submit">' + "</body>" + "</html>" res.write(web); res.end(); }); router.post('/path', [check("email").isEmail()], (req, res) => { //console.log(req); const errors = validationResult(req); console.log(errors.mapped()); if (!errors.isEmpty()) { res.status(400).end(); return; } res.write("It Works!"); res.status(200).end(); }); app.listen(3000); ========== 正しいメールアドレスを入力してサブミットすると、ブラウザには「It Works」と表示され、 コンソールには ========= {} ========= と表示されました。 不正なパスワードを入力すると、ブラウザには 400 エラーが表示され、コンソールには ========= { email: { value: 'linming', msg: 'Invalid value', param: 'email', location: 'body' } } ========= と表示されるようになりました。 つまり正しく動作していると思います。 長い間お付き合いいただきありがとうございました。 これから入門書のコードに反映を進めていきますが、またつまづいた場合はよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問