普段思ったことや、雑記。

Menu & Search

Express4でPOST値の取得でundefinedになってハマった話

2015年7月1日

お膳立て〜Expressと他Node.jsのWebアプリケーションフレームワーク〜

本ブログ初の技術ネタ。こちらの記事でも宣言しているように、普段Node.jsを使ってWebサービスの開発をしている。Node.jsのWebアプリケーションフレームワークには、

Express

http://expressjs.com/

を使用している。Expressの魅力というか、メリットは、やはりNode.js界隈でいうとわりと昔から開発されていて、他のNode.jsのWebアプリケーションフレームワークよりも安定性がある程度期待できること、あとはExpress用のミドルウェアの充実、特に周辺環境が活発に整備されていることだろう。少し古めの記事ではあるが、Node.js関連のWebアプリケーションフレームワークの盛り上がり具合でいうと、この記事が分かりやすい。

2014年 Webアプリケーションフレームワークトレンド(Node.js) – Qiita

http://qiita.com/oukayuka/items/14bfdcb6b5411a2b4b7c

上記の記事で分かるように、他フレームワークと比較しても知見が多そうなことも、Expressを選ぶ要因と成り得る。ちなみに、この記事の時点(2015年6月20日)でトップのMeteorはGitHubでのスター数25,990、Expressは19,502、Sailsは11,035であって、順位的には変動ナシといった具合だ。じゃあ、スター数で見てMeteorでいいじゃん、という方は待ってほしい。Expressはフルスタックのフレームワークではないのに対して、Meteorはフルスタックのフレームワークである。ちなみに、Sailsもフルスタックのフレームワークで、Railsの思想に影響を受けているようだ。これは個人的な主張なので流してもらってまったく構わないが、Node.jsなノリを存分に体験したいのなら、フレームワークはExpressでいいと思う。Sailsは内部にExpressを組み込んでいるそうだし、ExpressはNode.jsのWebアプリケーションフレームワークの中では特に長く開発されてきたし、安定性も優れたものなのだ。

本題

というわけで、本題。お膳立ては終了。ここからは普通に本題のExpressでPOSTによる値の取得でハマった件について、最近のNode.js関連のことで一番ハマったので、書いておく。Expressやってる人がPOSTで値を受け取る場合、まずbody-parserミドルウェアというものを使うということを知り、その設定をしに取り掛かる。だが、ここで問題が起こる。Node.js関連のことをWebでちまちま調べているときによく起こりがちだが、そのバージョンでは設定の仕方が違いますということだ。近いバージョンなので、似たようなこと書けば通るだろう、と思って記述したコードも、どうにも通らない。

例えば、Google検索で「express4 req.body undefined」という具合に調べてみても、なかなかバチっと答えが決まらないわけである。とりあえず、こんなんかな?みたいなようなことを4時間もGoogle先生に聞くことを繰り返してしまった…。

というわけで結論、最強はやはりミドルウェアの公式ページである。

最新のバージョンのOSSの使い方は、公式に行け!である。本当にこれは新しいOSSを追う上で重要な行動だと思った。たとえば、僕がハマったbodyParserでの値の取得のコードはこうだ。

var express = require('express’);
var bodyParser = require('body-parser')var app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.post(‘/', function(req,res,next){
  console.log(req.body);
});
var server = app.listen(3000, function () {
  console.log('Server starting.');
});

どうしてこうなったかというと、「 body-parserの値ってreq.bodyに入ってるんだぜ!urlencodedで設定しないとダメよ」…と多くで解説されていたからずーっとこう書いてみていたが、一見合っているようで間違っている。この状態で、プログラムを実行していくと、console.log(req.body)の箇所でエラーで終了してしまうundefindedと出力され、意図する値が取得できない。body-parserの公式を参照した結果、実際には、Express4.1系での最新のbody-parserの使い方はこうだった。

var express = require('express’);
var bodyParser = require('body-parser')var app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.post(‘/', function(req,res,next){
  res.setHeader('Content-Type', 'text/plain');
  console.log(req.body);
});

var server = app.listen(3000, function () {
  console.log('Server starting.');
});

不正解コードとの違いは、

res.setHeader('Content-Type', 'text/plain');

の1行だけである。自分はHTTP通信とかTCP/IPはあまり勉強していないので、浅はかなコメントになるが、見た感じ送られてきた情報に対し、ヘッダー情報を付与してはじめてExpressが扱えるような状態になっているのだろう。
これは、Node.jsの公式ドキュメントによると、この命令はこうだ。

HTTP Node.js v0.12.6 Manual & Documentation

https://nodejs.org/api/http.html#http_response_setheader_name_value

というわけで、間違ったこと書いてんじゃねーwとツッコミを入れてくれたPipesh代表山田さんありがとうございます。ドキュメントを確認したところ、リクエストに対して返す情報のヘッダーはtaxt/plainの形式にして’Content-Type’, ‘text/plain’にしてください、そのままおっしゃる通りでした。

これはハマった、本当にハマった。僕みたいな愚かなことを繰り返さないように、このエントリーがExpress4.1にてbody-parserでやはりundefinedが出てしまった方を助けになることを祈っている。そして、自分のようにOSSの最新の正しい情報は、公式に行くというのが最強の方法ことを学習し、トラブルにかける労力が少しでも減ることを祈っている。

Article Tags
mmiyauchi

プログラムを書きながらTranceを聴くのが良いですね。みなさんも聴いたほうがいいですよ、Trance。EDMよりハードトランスでしょ。

Related article

Redux(react-redux)における適切な配列要素の更新

2021年8月23日…

CloudFlareの『SSL/TLS 暗号化モード(HTTPS通信設定)』を使用したとき、『ERR SSL VERSION OR CIPHER MISMATCH』のエラーでChromeで発生し、接続できない場合の対処

英語の記事は見当たっ…

Dart(Flutter)についての所見

Dart(Flutter)についての所見

第一印象では、クロス…

Discussion about this post

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Type your search keyword, and press enter to search