body 付きの DELETE リクエストについて

2014年12月14日 23:28

今回は2つの問題が混在しているため、切り分けて考える必要がある。

まずは「body を含む DELETE」について。HTTP リクエストの DELETE は、クライアントからサーバにデータベースレコードなどの削除を要求するメソッドだが、Google App Engine においては、DELETE メソッドに body(オブジェクトボディ)を含めてはいけないようなのだ。では、RFC にはどう規定されているかといえば、section 9: Method Definitions を見る限り特に禁止しているわけでもない。

Stack Overflow を検索してみたところ、App Engine : 400 - Your client has issued a malformed or illegal request というそのものずばりな投稿があった。どうやら GAE のサーバは body を含む DELETE リクエストに対してエラーを返すようだ(以下の引用文では 501 エラーと書かれているが、実際には 400 エラー)。

Indeed, when the appspot frontends see a DELETE request that includes an body, such as your app, they return a 501. But, if you remove the body then it will serve a 200.

では、削除したいレコードを id で指定するなど、DELETE メソッドで何らかのパラメータを渡したい場合、どうすればいいか? おそらく webapp2.Route を使ってリクエスト URI にパラメータを含めてしまうのが一番簡単だろう。

app = webapp2.WSGIApplication([(r'/api/test/([^/]+)/?', TestHandler)], debug=True)

これなら、たとえば /api/test/12345 という URL で 12345 というパラメータを渡せる。TestHandler のほうは、こんな感じで。

class TestHandler(webapp2.RequestHandler):
    def delete(self, record_id):
        # record_id を使った削除処理

それから、もうひとつの問題……というか、AngularJS の $resource について。公式リファレンスの $resource を参照してみたところ、以下の記述を見つけた。

Each key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.

つまり、パラメータで与えられたキーに「余り」があれば、URL の検索クエリに追加されるというわけだ。ツイート中に書いた事象は不具合でもなんでもなく、$resource の仕様だったわけか。