POST されたフォームデータを Express で 受け取る方法
POST されるフォームデータの形式
HTML の form タグで、 method="POST" としてフォームの内容をサーバーにサブミットした場合、 HTTP リクエストのボディ部にはフォームの内容が param1=value1¶m2=value2 という風にパラメータ名と値がセットされます。
例えば、form タグの中に input 要素が二つあり、それぞれの名前 (name 属性) が country と city であるとします。 このときに、それぞれのフィールドに Japan、Tokyo と入力してサブミットすると HTTP POST リクエストのボディ部には country=Japan&city=Tokyo という値がセットされます。
この形式のデータの Content-Type は application/x-www-form-urlencoded といいます。単に「フォームデータ」とか「POST パラメータ」などと呼ぶ時は、この形式を指します。
こうしてサーバーにポストされたデータは、Express ではどのように読み取れば良いでしょうか。
body-parser の urlencoded() メソッドを利用
Express でフォームデータを読み込むには body-parser を利用すると簡単です。
body-parser は次のコマンドでインストールできます。
npm install body-parser
body-parser の urlencoded() メソッドは、フォームデータを解析するミドルウェアを返します。
このミドルウェアは Content-Type が application/x-www-form-urlencoded である POST リクエストのボディ部を解析し、 リクエストオブジェクトの body プロパティにフォームデータの内容を表すオブジェクトをセットします。
Express v4.16.0 以降では body-parser を別途インストールすることなく、 express.urlencoded() メソッドが利用できます。
urlencoded() メソッドの extended オプションによる違い
urlencoded() メソッドを呼ぶときに extended オプションを渡します。
extended オプションが true のとき、 ボディ部の解析に qs ライブラリが利用され、body に設定できるオブジェクトがより柔軟に操作できるようになります。
qs を利用する場合、例えば address[city]=Los Angeles&address[country]=United States というフォームデータを渡すと、 [] 内をプロパティとして認識し次のようなオブジェクトに変換されます。
{
address: {
city: 'Los Angeles',
country: 'United States'
}
}
一方、 qs を利用しない場合 (extended: false の場合) には、 上記のフォームデータは単純に次のように認識されます。
{
'address[city]': 'Los Angeles',
'address[country]': 'United States'
}
body-parser でフォームデータを受け取るサンプルコード
それでは、実際に動作確認をしてみましょう。
Node のプロジェクトを作成して、 express と body-parser をインストールします。
mkdir test
cd test
npm init -y
npm install express body-parser
まずは HTML ファイルを保存するためのフォルダを public という名前で作成します。
mkdir public
public フォルダ内に param1.html という名前で次のファイルを作成します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Param 1</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
</style>
</head>
<body>
<form method="POST" action="/foo">
<input type="text" name="country" placeholder="country" />
<input type="text" name="city" placeholder="city" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
次の内容を param1.js として作成します。
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
// body-parser
app.use(bodyParser.urlencoded({ extended: true }))
// static built-in middleware
app.use(express.static('public'))
// GET /foo
app.post('/foo', (req, res) => {
console.log('--- post() /foo called ---')
console.log(req.body)
res.send('Done')
})
// Start Listenings
app.listen(3000, () => console.log('Listening on http://localhost:3000/...'))
このスクリプトを実行します。
node param1.js
Listening on http://localhost:3000/...
ブラウザから http://localhost:3000/param1.html を要求します。表示されたフォームに、 適当に値を入力して Submit をクリックします。
すると Node 側 (サーバー側) では、次のようにフォームの内容が表示されます。
--- post() /foo called ---
{ country: 'United States', city: 'Los Angeles' }
フォームに入力した内容が取得できています。
さらに、ブラウザのデバッガコンソールで POST リクエストの内容をみると次のようになっています。
Content-Type も、実際に送信されたデータも想定通りであることが確認できます。