grunt-contrib-connectのmiddlewareの順序による挙動について
grunt-contrib-connectとgrunt-connect-proxyでstubcellを設定したが POST
や DELETE
のリクエストが method not allowed
で弾かれてしまって嵌ったのでメモ。
middlewareの設定順序が不適切
最初に正しい方法。middlewaresの先頭にproxyを挟む必要がある。
connect: { server: { options: { base: ["htdocs"], middleware: (connect, options, middlewares) -> middlewares.unshift(require("grunt-connect-proxy/lib/utils").proxyRequest); return middlewares; } }, proxies: [ // ... proxyの設定 ... ] } }
middlewares.unshiftする必要性
引数で middlewares
を受け取った時、connect.static
と connect.directoryIndex
のmiddlewareがデフォルトで設定され、それらは GET
, HEAD
, OPTIONS
のMethodしか許可していないため。
今回の僕のような POST
や DELETE
のようなRESTな感じのリクエストを投げたい場合にこれらよりあとにmiddlewareを設定してしまうとプロキシに到達する前に method not allowed
となる。
middlewares.unshift
のように先頭に middlewareを追加するか、 引数で middlewares
を取らず、空の配列から新しくmiddlewaresを生成してしまうかするのが良いと思う。
背景
grunt-contrib-connect
で静的ファイル(htmlとかjsとか)を配信し、RESTFulなAPIサーバーのモックとして stubcell
を立てて、 grunt-connect-proxy
でプロキシしてアプリ開発を行っていた。
が、proxyしているRESTFulなサーバに DELETE
や POST
を投げても 405
のレスポンスが返ってくる。
その時のGruntfileはこんな感じで、middlewaresにproxyRequestをpushしていた。 この時、middlewaresの配列が空の配列であるという錯覚が僕の3時間を無駄にした。
connect: { server: { options: { base: ["htdocs"], middleware: (connect, options, middlewares) -> middlewares.push(require("grunt-connect-proxy/lib/utils").proxyRequest); return middlewares; } }, proxies: [ // ... proxyの設定 ... ] } }
調べた過程
ChromeのdevToolsを見ると、allowのヘッダが某かで付与されていた。 とりあえずmiddlewaresにallowを突っ込むヘッダを付与してみる。
moddleware.push(function (req, res, next) { res.setHeader('allow', 'GET, DELETE'); next(); });
しかし通らない。
stubcellやproxiesのソースを読み、console.logを直で仕込みどこまでリクエストが伝播しているのかを調べているうちに、そもそも grunt-connect-proxy
にリクエストが届いていないことが判明。
grunt-contrib-connect
の某かで405を投げてるっぽい。
grunt-contrib-connect
の中の node-connect
のコードを読むが、 405
を投げている箇所が見当たらない。
検討がまったくつかないけれど、とりあえず障碍の範囲は絞れたので、grunt-contrib-connect
の nextの実装に console.log をかまして様子を見る。
その過程で、どうやら、middlewareがproxyの前に幾つか処理されているらしいことがわかる。
gruntfile上で console.log(middleware)
するとすでに配列にstaticとdirectoryIndexのmiddlewareが入っているではないか!
push辞めてunshiftして解決。