ドットインストールのExpress入門 をやっていて、サンプルはExpress3系なのですが、4系でやっていたので色々ハマりました。
たいていはモジュールを別途インストールして〜で済んだのですが、
#12 ルーティングを確認しようでPUT
、DELETE
メソッドに対応させるためにapp.use( express.methodOverride() )
というミドルウェアを使うとありました。
Express4系では、別途method-override
を使うのだとわかったので
// app.js var methodOverride = require('method-override'); app.use( methodOverride() );
として、フォームには
// edit.ejs <form method="post" action="/posts/<%= id %>"> // 中略 <input type="hidden" name="_method" value="put"> <input type="submit" value="update"> </form>
のような_method
を追加したのですが、フォームを送信してもPUT・DELETEではなく、フォームのactionで指定しているPOSTメソッドとして解釈されてしまいました。
1. _method の付け方を変更する方法
override using a query value
To use a query string value to override the method, specify the query string key as a string argument to the methodOverride function. To then make the call, send a POST request to a URL with the overridden method as the value of that query string key. This method of using a query value would typically be used in conjunction with plain HTML
どうやら、methodOverride()
にメソッドを書き換えるためのキーを指定して、input[type="hidden"]で_method
を渡すのではなくフォームのアクションに?_method=
としてあげると良いようです。フォームのmethodがGETならinput[type="hidden"]でも上手くいくのかな???
GitHubのサンプルコードではrequire('connect')
していたので、これをインストールして、app.jsとedit.ejsを書き換えます。
$ npm install --save connect
// app.js var connect = require('connect'); var methodOverride = require('method-override'); app.use( methodOverride('_method') ); // キーを指定
// edit.ejs <form method="post" action="/posts/<%= id %>?_method=PUT"> // 中略 <input type="submit" value="update"> </form>
DELETEメソッドも同様にaction="/posts/<%= id %>?_method=DELETE"
にすれば、PUT・DELETEメソッドとして解釈されるようになりました。
2. ?method= ではなく input[type="hidden"]でmethodを渡す方法
POSTのフォームなのにURLに?_method
ってパラメーターが付いてるのがなんだか少しかっちょ悪い気がします... GitHubのページを見ていると、input[type="hidden"]で_methodを渡す方法も書かれていました。
custom logic
You can implement any kind of custom logic with a function for the getter. The following implements the logic for looking in req.body that was in method-override@1:
req.body
内に_method
パラメーターがあるか探してメソッドを書き換える処理を自前で書けば、ドットインストールのサンプルのようにフォーム内にinput[type="hidden", name="_method", value="put / delete"]でPUT・DELETEメソッドが使えるようになるようです。
フォームの有るedit.ejsは最初の状態のままでOKなので、app.jsを修正します。
// app.js var bodyParser = require('body-parser'); var connect = require('connect'); var methodOverride = require('method-override'); // ↓ これはドットインストールのサンプルで4系用に作ってたミドルウェア app.use( bodyParser.urlencoded() ); // method の変更処理を自前で書く方法にする app.use( methodOverride(function(req, res){ if (req.body && typeof req.body === 'object' && '_method' in req.body) { // look in urlencoded POST bodies and delete it var method = req.body._method; delete req.body._method; return method; } }) );
この方法で、ドットインストールのサンプルと同じ様にフォームの中にinputタグで_method
を書いておく方法でPUT・DELETEメソッドが使えるようになりました。
感想
Expressはなんとなく使ってたので、理解できてない部分が多かったので、最初からバージョンを合わせてレッスンするべきだったかもしれませんが、ハマって自分で調べることでより理解が進むような気もしているのでハマって良かったかなぁーと思うことにします。
method-override
でPUT・DELETEが使える、いわゆるREST(って言うのですかね?)にする方法がけっこう大変なので、もしかしたらもっと良いExpress4系のモジュールとかが有るるのでしょうか?気になります。
[参考]
- Express入門 (全21回) - プログラミングならドットインストール
- expressjs/method-override · GitHub
- javascript - Node.js - Express 4.x - method-override not handling PUT request - Stack Overflow
- yohei-y:weblog: REST 入門(その5) 四つの動詞 -- GET, POST, PUT, DELETE
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
- 作者: 山本陽平
- 出版社/メーカー: 技術評論社
- 発売日: 2010/04/08
- メディア: 単行本(ソフトカバー)
- 購入: 143人 クリック: 4,320回
- この商品を含むブログ (179件) を見る