2011年11月27日日曜日

Railsの擬似RESTにPut/Deleteを投げる2つの方法

前置き

RailsではRESTfulなインターフェースが基本です。
RESTfulの設計思想では、以下のように処理によってhttpのメソッドの使い分けをすることとされています。

  • データを参照したいときは、GET
  • データを新規登録したいときは、POST
  • データを更新したいときは、PUT
  • データを削除したいときは、DELETE


しかし、現状では、ブラウザはPUT、DELETEメソッドを実装していません。
つまり、現在のWeb環境では、純粋なRESTfulインターフェースを使うことはできないのです。

仕方ないので、Railsでは、
PUT/DELETEをしたいときは、httpのメソッド的にはPOSTを使いながらも、
これはPUTです、これはDELETEです、というフラグを合わせることで、
RESTfulっぽいインターフェースを実現しています。
これが擬似REST方式です。


このあたりはRailsのフレームワークが隠蔽してくれるので、
アプリのプログラマは普段はあまり意識する必要はありません。


ただし、先日、これを強く意識する必要に迫られることがあったので、メモ。

RailsアプリのクライアントがWebブラウザである場合は、何も意識する必要はありません。Web画面のsubmitボタンを押せば、それがPutなのか、Deleteなのか分かるように、Railsがhtmlを作ってくれているからです。大抵のRailsアプリのクライアントはWebブラウザですね。

そうではなくて、Railsアプリのクライアントを自作する場合が問題となります。
例えばどこか外部のWebAPI(Amazonの本屋のWebAPIとか)を利用する場合、そのサービスの使い方(インターフェース)を知る必要がありますよね?
その外部のWebAPIがRailsで作られたWebサービスなのであれば、RailsアプリのAPIを知らなければいけません。そのRailsアプリのAPIが擬似REST方式だとしたら、擬似RESTへのリクエストの投げ方を知らないといけないのです。
(Railsは基本、擬似RESTですが、Routingを自分で定義すれば擬似RESTでないAPIも自由に作れます。以下に説明するように、ブラウザ以外からGET/POST以外の擬似RESTを使うのは少し面倒なので、ブラウザ以外から利用することを主としたWebAPIで、PUT/DELETEを実装したいなら、無理して擬似RESTにしない方がいいと思います。)

Railsの擬似RESTにリクエストを投げる方法


前置きが長くなってしまった、、ここから本題です。
GET/POSTメソッドのリクエストを投げたいときは、そのままGET/POSTのhttpリクエストを投げればいいだけなので、省略します。以下、Railsの擬似RESTインターフェースに、PUT/DELETEメソッドのリクエストを投げる方法について説明します。

方法1:_methodパラメータを指定する。



clnt = HTTPClient.new
body = {
  'param1'=>'hoge',
  '_method'=>'put',
}
res = clnt.post(SERVER_URI, body)


方法2:X-Http-Method-Overrideを指定する。



req = Net::HTTP::Post.new(path, initheader = {'Content-Type' =>'application/json'})
res = Net::HTTP.new(HOST, PORT).start {|http|
  req["X-Http-Method-Override"] = "put"
  http.request(req)
}


Content-TypeにJsonを指定すると、なぜか方法1が使えなかった。
方法2ならいけました。

0 件のコメント:

コメントを投稿