のらねこの気まま暮らし

技術系だけど、Qiita向きではないポエムとかを書くめったに更新されないヤツ

grunt-contrib-connectのmiddlewareの順序による挙動について

grunt-contrib-connectgrunt-connect-proxystubcellを設定したが POSTDELETE のリクエストが 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.staticconnect.directoryIndex のmiddlewareがデフォルトで設定され、それらは GET , HEAD, OPTIONS のMethodしか許可していないため。

今回の僕のような POSTDELETE のようなRESTな感じのリクエストを投げたい場合にこれらよりあとにmiddlewareを設定してしまうとプロキシに到達する前に method not allowed となる。

middlewares.unshift のように先頭に middlewareを追加するか、 引数で middlewares を取らず、空の配列から新しくmiddlewaresを生成してしまうかするのが良いと思う。

背景

grunt-contrib-connect で静的ファイル(htmlとかjsとか)を配信し、RESTFulなAPIサーバーのモックとして stubcell を立てて、 grunt-connect-proxy でプロキシしてアプリ開発を行っていた。

が、proxyしているRESTFulなサーバに DELETEPOST を投げても 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して解決。