Node.js の express で POST した値を取ろうとしたら request.body が undefined になる

request.body が undefined になるので調べました。

環境

  • Node.js: v8.9.4
  • express: 4.16.2

再現確認

次のようなファイルを作成しました。

// app.js
const express = require('express')
const app = express()

app.get('/', (req, res) => {
  const body = `
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>app.js</title>
      </head>
      <body>
        <form method="post">
          <input type="text" id="text1" name="text1" value="text1.value">
          <input type="submit">
        </form>
      </body>
    </html>
  `
  res.send(body)
})

app.post('/', (req, res) => {
  console.log(req.body)
  res.send(req.body)
})

app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})

Node.js で実行します。

$ node app.js

http://localhost:3000/ のアドレスにアクセスします。 ボタンをクリックします。 すると、コンソールに undefined と表示されます。

公式の API リファレンス

公式の API リファレンスから引用します。

req.body

Contains key-value pairs of data submitted in the request body. By default, it is undefined, and is populated when you use body-parsing middleware such as body-parser and multer.

Express 4.x - API Reference

標準では request の body は undefined って書いてあります。 一般的には body-parser ミドルウェアを使うそうです。

対処

次のようにファイルを修正しました。

// app.js
const bodyParser = require('body-parser') // body-parser
const express = require('express')
const app = express()
app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

app.get('/', (req, res) => {
  const body = `
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>app.js</title>
      </head>
      <body>
        <form method="post">
          <input type="text" id="text1" name="text1" value="text1.value">
          <input type="submit">
        </form>
      </body>
    </html>
  `
  res.send(body)
})

app.post('/', (req, res) => {
  console.log(req.body)
  res.send(req.body)
})

app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})

1 行目と 4 行目を追加しました。

また Node.js で実行します。

$ node app.js

http://localhost:3000/ のアドレスにアクセスします。 ボタンをクリックします。 すると、コンソールに { text1: 'text1.value' } と表示されました。

終わり

久しぶりに express を使ってみたのですが、バージョン 3 と 4 ではかなり違うみたいでした。 以前はバージョン 3 を使っていたのかどうか、記憶が怪しいのですが、 body-parser とか使わずに値が取れた気がしています。

それ以外にもいろいろ express 本体から独立して、ミドルウェアと呼ばれる機能群ができているようです。

改めて Fast, unopinionated, minimalist web framework for Node.js の express はお手軽にウェブアプリケーションが作れて便利です。 サーバー側とクライアント側で ECMAScript が使えるところがいいです。