RailsでXMLをPOSTしてParamsで受ける

今日の小ネタ。ブラウザではなく適当なクライアントからXMLデータを受けてハッシュで扱いたいとき。

といってもRails側は特になにもすることがない(2.3.2使用)。Rails2.0からPOSTはFormにランダム文字列が埋め込まれてCSRF対策がされているのでまずこれを無効にします。
無効にした場合、どうやって対策をとればいいのかはまだ調べてないっす。

application_controller.rbに以下のコードがあるのでコメントアウト

  protect_from_forgery # See ActionController::RequestForgeryProtection for details

で、クライアント側。RubyでPOSTしてみます

require "net/http"

data = "<xml><key1>hogehoge</key1><key2>fugafuga</key2></xml>"
header ={
  'Content-Length' => data.length.to_s,
  'Content-Type' => "application/xml"
}

client = Net::HTTP.new("yourdomain.com", 80)

res = client.post("/api", data, header)
p res.body

(ナイスなXMLジェネレータは調べてない)

ポイントはヘッダのContent-typeでApplication/xmlを指定することです。そうすることでRailsXMlをParseした結果をParamsから取得できるようになります。
ここのContent-typeを変えることでYAMLJSONなどの形式も対応している模様。

後は普通に
params[:xml][:key1]のようにアクセスすればhogehogeが返ってきます。
ちなみにモデル関係ないからといってルートノード作らないとエラーになりました(XMLだから当然か)。
普通にparams[:item][:name]のようにアクセスするにはitemをルートノードにするとヘルパー使用時のフォームからの入力と同じように扱えますね。



参考:
http://d.hatena.ne.jp/lifrenthy/20080416/1208329622
上記の例では怪しい文字は使ってないので問題ないけども、ここによると、XMLデータはURI.encodeしないとハマるらしいので気をつけなくては。

http://d.hatena.ne.jp/mallowlabs/20080329/1206799301
ApplicationControllerでコメントアウトしてしまうとその他の部分もすべて無効になってしまうので外部からXMLを受けるControllerだけbefore_skip_filterで飛ばすほうがかしこいようだ。