REST化についての考察(まとめ)

ここではRucleus(仮称)でなぜRESTの設計を取り入れることにしたのか,どういう問題があるのかをまとめておきます。

RESTの意味とそのメリット


Rails 2.0の目玉の一つがRESTfulな設計が簡単になったことですが,RESTの機能自体はRails 1.2で導入されています。僕自身は「RESTってWebサービスのインタフェースの1つでSOAPほど面倒くさくないやつでしょ」ってくらいの認識しかなかったのですが,RESTについて調べると,そういうものではなくてWebアプリケーションの設計思想に近いものだということが分かってきました。

RESTfulなアプリケーションやサービスではURLはリソースを示します。例えばブログやアイテムがリソースです。Railsではモデルすなわちデータベースのテーブルがリソースになります。これに対して「何をするか」という「アクション」はHTTPのverb,すなわち「GET」や「POST」などで表現します。これをリソースのコントローラに対して適用します。つまり,モデルのクラス1つに対してコントローラのクラス1つが対応するような形になります。なおverbとしてHTTPの仕様では「DELETE」,「PUT」(データの更新)が定義されていますが,現在使われているブラウザが送信するのはGETとPOSTしかないため,Railsではフォームに特別なフィールドを作ってDELETE,PUTを実現します。

RESTのもう1つの特徴に内部状態に依存しないということがあります。クッキーやセッション・データによって表示内容を変えることがなく,URL(正確に言えば,HTTPヘッダに含まれる情報)で結果が決まります。これによって,ページ・キャッシュが実現しやすいというメリットがあります。サーバーに内部情報を保存する必要がないため分散処理も容易になります。

また,「respond to」による各種フォーマットのサポートという特徴もあります。例えばRailsのRESTサポートではXMLによる出力を標準的に利用できるようになっています。

これらRESTの特徴はNucleus(Rucleus)となじみがいいものです。例えば,初期の設定ではURLの解釈においてアプリケーションというコントローラにブログやカテゴリーといったリソースの情報を渡して「item」をアクションとしてIDを付けてアクセスするといった形にしていました。それよりはブログやアイテムをリソースとしてアクセスすると考えた方がすっきりします。また2番目の特徴は性能を考えたときにクリティカルになってきます。最後の各種フォーマットのサポートも,スキンを切り替えることでさまざまな出力を行うNucleusのスタイルと相性がいいです。

認証の問題


では,何が問題になって悩んでいたかというと,認証関係とURL周りです。まず,認証ですが,RESTではNucleusが従来やっているようなクッキーを使った認証というのは問題になります。BASIC認証やダイジェスト認証,WSSE認証といったHTTPで定められた認証が必要です。この中でWSSE認証はブラウザがサポートしていないため,JavaScriptでなにやらやる必要があるなど,採用には問題点があります。次にBASIC認証やダイジェスト認証を使ったときですが,いくつかの課題が生じます。①1つのURLでログイン・ユーザーとゲストで違ったページを表示するのが難しい,②ログイン時にダイアログ・ボックスが出るのが格好悪い,独自のページでログインさせたい,③ログアウトが困難,といったものです。

こちらのページにはこれらの条件を満足させてダイジェスト認証を使う方法が記載されていますが,詳しく読んでみると,ブラウザによってやり方を変えなければいけないなど,現実に採用するには難しい部分がかなりありそうです。上の問題で①が機能的に一番ほしいところですが,逆に言えばここだけ我慢すればいいという見方もできます。

URLの問題とその解決法


最後の問題となったのがURL周りです。冒頭に書いたようにRails 2.0ではREST対応のアプリケーションを簡単に作れるようになっていますが,URLに大きな制限を受けてしまいます。例えば,blogidが1のitemidが10というアイテムにアクセスする場合,URLは「blog/1/item/10」といった形式に固定化されてしまいます。ここを独自のURL設計にする方法が分からずに悩んでいたわけです。

現在のURL周りの処理はこんな感じです。例えば /blogname でブログにアクセスする場合
  map.blog ':blogname', :controller => "blogs", :action => 'show'
といった形で「blogs」をコントローラにしてshowというアクションを実行します。blognameからブログを見つける処理はshowの中に記述します。これに各種フォーマット対応をするために次のように追加します。
  map.blog ':blogname.:format', :controller => "blogs", :action => 'show'

アプリケーションのコントローラには
private
  def setblog
    if !params['blogname']
       $NCGlobals['blog'] = Blog.find(CONF['DefaultBlog'])
    else
       $NCGlobals['blog'] = Blog.find_by_bname(params['blogname']) || Blog.find(CONF['DefaultBlog'])
    end
  end
  
  def setcatid
    if params['catid']
       $NCGlobals['catid'] = params['catid'].to_i
    end
  end
  
  def setskin(skinname)
    if (skinname=='')
       $NCGlobals['skin'] = $NCGlobals['blog'].skin
    else
       skin = Skin.find_by_sdname(skinname)
       $NCGlobals['skin'] = (skin) ? skin :$NCGlobals['blog'].skin
    end
  end

public
  def blog(skinname='')
    setblog
    setcatid
    setskin(skinname)
    
    $NCGlobals['skintype'] = 'index'
    $NCGlobals['item'] = Array.new
    $NCGlobals['controller'] = self

    @contents = $NCGlobals['skin'].part($NCGlobals['skintype'])
    @controller = NCParser::DefaultSkinIndex.new $NCGlobals['controller']
    render :action=>'index.html.erb'
  end

といった形でblognameから実際のブログオブジェクトを見つけることなどが記述されます。また,blogs_controllerのshowメソッドは
  def show

    respond_to do |format|
      format.html { blog }
      format.xml  { blog('feeds/rss20') }
    end
  end

といった形になります。このようにしておくだけで /lab.xml というURLでアクセスするとRSS2.0のフィードを生成してくれるようになります。




21 Jan, 2008 | Foodyn ( 仕様 ) , Rails | / | Andy
« Prev item - Next Item »
---------------------------------------------

Comments


No comments yet. You can be the first!


Leave comment

© 2007 yoursite.com | Designed by DesignsByDarren
Ported to Nucleus CMS: Suvoroff