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して解決。
grunt-init で jquery-plugin を作って travisCIに上げるまでのメモ
準備
以下をインストール
$ npm install -g grunt-init $ git clone https://github.com/gruntjs/grunt-init-jquery.git ~/.grunt-init/jquery
プロジェクトの作成
grunt-init jquery
をプロジェクトディレクトリで走らせるとplugin用のアセットを生成してくれる。
なお、既にルートディレクトリにpackage.json
が存在するとエラーになる模。様l
$ mkdir eg-grunt-init $ cd eg-grunt-init $ grunt-init jquery
生成されたコード
. ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE-MIT ├── README.md ├── eg-grunt-init.jquery.json ├── libs │ ├── jquery │ │ └── jquery.js │ ├── jquery-loader.js │ └── qunit │ ├── qunit.css │ └── qunit.js ├── package.json ├── src │ └── eg-grunt-init.js └── test ├── eg-grunt-init.html └── eg-grunt-init_test.js
とりあえず動かす
なにもオリジナルなコードは書かずに、そのまま動かす。
$ npm install $ npm test
すでにもうテストが動くという親切っぷり。 テストはqunitを使っている。そのまま使うか、mochaでも入れるか、は各自の自由なのかな。 また、jshintも設定されてるので、これに従えばjqueryの規約に沿ったコードになる様子。
サンプルコードは2indentで書かれているが、jshint的には特に規定はなく、そのまま4indentで書いてしまったが、好きに設定して良いのかもしれない。 まあ、minifyするか
pluginを実装する
かく。 テスト通らせる
travisCIに上げる
ここでちょっとあれこれしたのでメモ。
- grunt-cliをinstallする
- デフォルトではgrunt-cliが無いので、
npm install --save-dev grunt-cli
した
- デフォルトではgrunt-cliが無いので、
- vesionかえる
- package.jsonに定義されているversionが
0.0.0-ignored
だったので、npmとれなかった気配 - versionやnpmの流儀についてはちゃんと調べずここまで来ているので、なんか勘違いしてるきもするけど、とりあえず動いたので。
- package.jsonに定義されているversionが
おしまい
grunt-initはべんりだなーって思った。 でもqunitは使いにくい。
あ、あと。jquery-formize on Githubというpluginを書きました。form要素にデータ入れたりデータ取ったりエラーのスタイル当てるのにいい感じにしてくれる子がほしかった。 この子を書くときにgrunt-initに入門したので、色々勉強になった。まる。