RESTの普及
SOAPは2000年以降、Webサービスという言葉とともに注目されましたが、仕様が複雑であるため扱いが難しく、代わってREST(Representational State Transfer)と呼ばれる単純な通信方法が利用されるようになりました。複雑なオブジェクトを統一された方法で交換する場合はSOAPが適していますが、上記の辞書ソフトのような単純なデータの呼び出しではREST方式が好まれます。
SOAPの場合、クライアントはサーバに対してXML文書のメッセージを送らなければなりません。これは、構造化された情報を送受信しなければならない場合には必要な処理ですが、簡単なデータの取得や更新では冗長です。
RESTは、Web上のリソースをURIで識別し、リソースの取得はGETメソッドで、更新はPUTメソッドで、削除はDELETEメソッドで行います。ただし、これはRESTアーキテクチャを厳密に説明するものであって、一般にはURIが一種のリモートプロシージャのような働きをするHTTPとXMLを組み合わせたソフトウェア機能をRESTと呼ぶ傾向もあります。
こうしたRESTの意味を考えた場合、多くのURIが暗黙的にREST型のサービスになっているとも考えられます。例えばRSSフィードなどは、Webサイトの最新の情報を配信する立派なサービスで、実際に多くのWebやアプリケーションに組み込まれています。
Amazonのような有名なオンライン・ショップも、商品を検索するWebサービスを公開しています。AmazonはSOAPとRESTの両方でサービスを公開していますが、RESTの利用者の方が圧倒的に多いと言われています。おそらく、Java や .NET Frameworkで実装されたアプリケーションからWebサービスを利用してオブジェクトを交換する場合はSOAPの方が適しています。しかし、スクリプトなどを用いてWebサイトにサービスを組み込む場合はRESTの方が便利でしょう。
REST型サービスを実装する
辞書ソフトの場合、受け取ったキーの結果をXML形式のテキストで返すことで、結果となる値の構造を表現することができます。この場合、サービスを利用する開発者には結果となるXMLの文書型定義や、辞書を提供するURIが受け取るパラメータの名前と型を事前に知らせる必要があります。
<?php $key = $_GET['key']; $DIC = array( "kitty" => "仔猫", "kitten" => "仔猫", "cat" => "猫", "siamese" => "シャム", "tortoiseshell" => "三毛", "persian" => "ペルシャ" ); header('Content-type: text/xml'); print <<<EOF <?xml version="1.0" encoding="UTF-8"?> <dictionary> <key>$key</key> <value>$DIC[$key]</value> </dictionary> EOF; ?>

サンプル 02は、受け取ったキーと、キーに関連付けられている値をXML形式で返す簡単な模擬サービスです。クライアントは、このXMLを解析することで、どれがキーに対応した値を表すテキストなのかを知ることができます。リソースが複雑になればXMLは大きな威力を発揮するでしょう。
クライアントの開発
得られたXMLは書式情報を持たないため、クライアント側のプログラムでXMLを解析し、適切なビューに変換する必要があります。HTTPリクエストが可能で、DOMが実装されている環境であればどのようなクライアントでもかまいませんが、この場ではAjaxによるWebベースのクライアントを開発してみましょう。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Ajax ベースのクライアント</title> <script type="text/javascript"> function GetValue(key) { //XMLHttpRequest オブジェクトを取得する var req = null; if ("XMLHttpRequest" in window) req = new XMLHttpRequest(); else if ("ActiveXObject" in window) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } //同期通信でサーバーからデータを取得 req.open("GET", "dic.php?key=" + key, false); req.send(null); //value 要素のコレクションを取得 var values = req.responseXML.getElementsByTagName("value"); if (values.length == 0) return null; //存在しなければ null //子ノードのコレクションを取得 var children = values.item(0).childNodes; if (children.length == 0) return null; //存在しなければ null //子ノードの先頭要素を取得 var value = children.item(0); if (value.nodeType != 3) return null; //テキスト型でなければ null return value.nodeValue; } </script> </head> <body> <h1>キーを入力してください</h1> <div> <input id="key" type="text" /> <input type="button" value="送信" onclick=" var keyInput = document.getElementById('key'); var resultDiv = document.getElementById('result'); resultDiv.innerHTML = GetValue(keyInput.value); "/> </div> <div id="result"></div> </body> </html>

サンプル 02のajax.htmlは、Ajaxの仕組みを利用してページ遷移を発生させずに辞書からデータを取得するWebアプリケーションです。JavaScriptコードのGetValue()関数では、XMLHttpRequestオブジェクトを生成してdic.phpにアクセスしています。取得したXMLから抽出したいノードを検索し、結果を返しています。
このページ自体はAjaxベースのWebアプリケーションのように機能していますが、最も重要なのはバックグラウンドでdic.phpによるサービスが働いていることです。サーバ側はビジネスロジックだけを担当し、プレゼンテーションは完全にクライアントに委ねることができています。従来のWebアプリケーションでは、ビジネスロジックとプレゼンテーションをサーバ側で分離することはあっても、得られる結果はHTMLに限られていたため、クライアント側でデータ処理を行うことができませんでした。
サンプル 02の方法を用いることで、辞書をガジェットや他のブログ、CMSのモジュールとして組み込むことが容易になります。
