AngularJSでbackbone.jsのemulateHTTP相当を実現する

  • 投稿日:
  • by

backbone.jsのemulateHTTPというのは、PUTやDELETEをPOSTに変換するものです。なぜそんなことが必要かというと、PUTやDELETEが通らないHTTP Proxyがあるからです。

emulateHTTPでは、X-HTTP-Method-Overrideというヘッダーを使います。正確には、_methodというパラメータも追加されるのですが、それは対応しないものとします。X-HTTP-Method-Overrideはnode.jsのexpressやconnectでサポートされます。

app.use(express.methodOverride());

とすれば有効になります。

さて、こんな機能は当然angular.jsで用意されていて一行くらいの設定で使えるようになるだろうと思っていたら、そんなことはありませんでした。 検索すると、

http://manikanta.com/blog/2013/07/25/decorate-angularjs-http-service-to-convert-put/

がヒットしました。 これでできそうかと思ったのですが、実装が中途半端です。 具体的には、

$http.put({...});

のときは想定どおりに動くのですが、

$http({method: 'PUT', ...});

のような使い方ではうまく動きません。 そこで書き直してみることにします。

var App = angular.module('App');
App.config(['$provide', function($provide) {
  $provide.decorator('$http', ['$delegate', function($delegate) {
    var $http = function(config) {
      var method = config.method.toUpperCase();
      if (method === 'DELETE' || method === 'PUT') {
        config.headers || (config.headers = {});    
        config.headers['X-HTTP-Method-Override'] = method;
        config.method = 'POST';
      }
      return $delegate(config);
    };
    angular.extend($http, $delegate);
    $http.delete = function(url, config) {
      return $http(angular.extend(config || {}, {method: 'DELETE', url: url}));
    };
    $http.put = function(url, data, config) {
      return $http(angular.extend(config || {}, {method: 'PUT', url: url, data: data}));
    };
    return $http;
  }]);
}]);

こんな感じになりました。 もう少しスマートな方法はないかと、思ってしまいますね。 しかし、おかげで$provide.decoratorの使い方を覚えました。

上記コードは動作確認してないので、使用レポートをお待ちします。