3.8 Web 2.0時代のWebServices 〜SOAP/REST使い分けの指針
最終更新日:2007/06/07
荒本道隆
1.はじめに
かつて、Webサービスと言えばSOAPだった。企業内や企業間でSOAPを使ったシステム連携が行われ、アプリケーションサーバや開発ツールもSOAP対応が進んできた。特に、様々な開発言語用のSOAPライブラリが出てきたことで、SOAPが利用できない理由は無くなった。
一方、現状ではInternet上で公開されているWebサービスは、RESTが圧倒的に多いという状況である。SOAPを提供していても、RESTと併用している場合がほとんどで、多くの人がRESTを選択している。
そのような現実を踏まえ、SOAPとRESTについて「どう違うのか?」「どっちを使ったらいいんだ?」という疑問について、検討していく。
2.RESTとは
RESTとは、
Representational
State
Transfer の略で、HTTPを使って通信をおこなう手法である。明確な仕様がないために「どこまでをRESTと呼ぶか」については様々な主張があるが、ここでは『HTTPのGETメソッドを使ってあるURLにアクセスすると、
XMLが返ってくる』ものを
RESTと呼ぶ。セッションやPOSTを使えば複雑な事も実現可能だが、今回はGETを使ったシンプルなRESTを想定している。
RESTの、ある特定のURLにアクセスしてXMLを得るという動きは、WebブラウザがURLにアクセスしてHTMLを得るのとまったく同じである。違いは、HTMLの代わりにXMLを返す点だけである。
・RESTのサンプル
リクエスト |
GET /WebSite1/WebService.asmx/getHello?str=string HTTP/1.1
Host: localhost
|
レスポンス |
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">string</string>
|
RESTは、WebブラウザのAjaxや、クライアントアプリから使う場合もあるが、サーバ間のシステム連携でも使う。
RESTの最大の特徴は「WebブラウザにURLを入力すれば動作確認できる」事である。
Webブラウザで容易に動作確認ができるため、すでに存在しているサービスに対しては「まずはアクセスしてみて必要な情報が得られるか確認し、実際に使うかどうかはそれから考える」という使い方ができる。わざわざテスト用アプリを作る必要がない。
また、通常、クライアント/サーバを開発する場合には、「サーバが無ければ、クライアントを作っても動作確認できない」「クライアントが無ければ、サーバを作ってもアクセスされない」ため、「どちらか一方だけを開発」する場合でも、開発やテストの効率を考えるともう一方のテスト版を準備する必要がでてきてしまう。しかし、RESTであれば、サーバを開発する側はWebブラウザを使って動作確認ができるし、クライアントを開発する側は想定しているレスポンスをファイルに準備すればテストでき、開発の本質ではない部分の手間が省略できる。
RESTの使用例の一つに「RSS配信」がある。RSS配信では、特定のURLにアクセスすると、XMLのRSSフォーマットで記述されたデータが配信される。XMLで取得できることで、受信側で自由に加工することができる。その特徴を生かして、RSSリーダーでは異なるサイトから取得したニュースをまとめて管理したり、同じフォーマットで閲覧することができる。
RESTの定義方法には
WADL(Web Application Description Language)があるが、対応しているミドルウエアがまだ少なく、2007年6月の時点ではあまり使われていない。しかし、WADLは構造がシンプルで読み易いので、各国語のドキュメントを作成するよりも、WADLで記述した方が1つの言語で済み、より多くの人に読んでもらえるかもしれない。
それ以外の定義方法もあるが、現在はWADLが最も有力である。
WADLのサンプル(YahooSearch)
3.SOAPとは
SOAPとは、元々は
Simple
Object
Access
Protocol の略で、SOAPメッセージというXMLによってメッセージ交換をおこなう方法である。SOAPの仕様は、1.0, 1.1, 1.2 とバージョンアップを続けている。2000年5月に公開された1.1ではHTTP以外のSMTP, FTP,ファイル共有などが使えるようになり、2003年6月に標準化された1.2ではRESTと同じような
GETによるアクセスも利用可能になった。
(1.2からSimple Object Access Protocol の略ではなく、固有名詞になった)しかし、ここでは1.0から規定されていて最もSOAPらしい『HTTPのPOSTを使って
SOAPメッセージを交換するもの』を
SOAPと呼ぶ。
SOAPは、当初はシステム間連携を目的に、CSV(
Comma
Separated
Values)ファイルの交換、RPC(
Remote
Procedure
Call)の呼び出し、EDI(
Electronic
Data
Interchange)による連携、などそれまでの方式の欠点を補うために登場した。
SOAPは、エンドポイントと呼ばれるURLにSOAPメッセージを送ると、結果のSOAPメッセージが返ってくる。
送受信するSOAPメッセージはXMLで記述し、一番外側に<Envelope>、その下に<Header>と<Body>を記述する。<Header>と<Body>の下にはXMLでありさえすれば何を書いても良く、自由に拡張することができる。その代わりに、「必ずルート要素は<Envelope>」「その下は<Header>と<Body>」(<Header>は無くても良い)とすることで、システムで取り扱い易くした。
詳しくは、SOAPメッセージのスキーマを参照のこと。これは『定型の封筒に入れれば配達員は中身を知る必要が無く、中身の便箋に何を使っても何を書いても良い』のと似ている。
・SOAPのサンプル
リクエスト |
POST /WebSite1/WebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/getHello"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getHello xmlns="http://tempuri.org/">
<str>string</str>
</getHello>
</soap:Body>
</soap:Envelope>
|
レスポンス |
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getHelloResponse xmlns="http://tempuri.org/">
<getHelloResult>string</getHelloResult>
</getHelloResponse>
</soap:Body>
</soap:Envelope>
|
SOAPの定義方法には
WSDL(Web Services Description Language)がある。様々な言語(
Java,
C++,
.net,
PHP,
Perl, e.t.c.)でWSDLに対応したミドルウエアがあり、WSDLを読み込ませる事でSOAPを簡単に呼び出す事ができる。
また、JavaScriptのようにWSDLを読み込むミドルウエアがまだ無くても、SOAPメッセージと同じ構造のXMLメッセージを作成し、それをPOSTすることでSOAP呼び出しが実現できなくもない。
WSDLのサンプル(GoogleSearch)
4.RESTとSOAPの共通点
RESTもSOAPも、HTTPとXMLを使う事で、それまでの「CORBAによるメッセージ交換」「FTPを使ってCSVファイルを交換」などに比べると、様々なメリットがある。
- 通信内容がすべてテキストであることによる可読性
- HTTPSを使っての暗号化(サーバ証明/クライアント証明)
- HTTPプロキシを使ってFirewallを越える
- リアルタイムな応答
- HTTP, XMLをターゲットにしたライブラリやアプライアンスの流用
- XMLに対してXSLTを使ってのフォーマット変換
最大のメリットは、「今までのWebサイト開発のハード、ソフト、ノウハウがそのまま使える」ことである。
そして、残念ながらいくつかのデメリットもある。
- HTTPは長時間の接続維持ができないので、すぐに応答を返す必要がある
- XMLの構造をスキーマに定義する必要がある
HTTPを使っていることで、非常に時間のかかる処理の応答を待つ事ができない。その前にHTTPのタイムアウトになってしまうからである。解決方法としては「定期的に実行結果をポーリングで問い合わせる」「SOAPであれば、HTTP以外を使う」などがあるが、それぞれ一長一短がある。
RESTもSOAPもXMLを使うが、XMLを使う以上スキーマを定義する必要がある。「スキーマを定義せずにサービスを提供する」ということも不可能ではないが、利用者側の負担が大きくなってしまうし、XMLを使うメリットが半減してしまう。
サービスを提供する側は、Internetなどを通じて多くの人に利用してもらうためには、スキーマの定義を慎重におこなわなければならない。RSSで使われている
RDFのように規定済みのスキーマが利用できれば問題ないが、オリジナルのスキーマを規定しようとすると、利用者が多ければ多いほど、もしも変更した場合の影響範囲が広くなってしまう。XMLの最大の利点である『拡張性が高い』を聞いて、「拡張して新要素を増やす分には問題ないだろう」と思うかもしれないが、スキーマが「使える要素名を明確にし、限定する」ので、後でスキーマを変更して要素が増減すると、そのスキーマの利用者全員が対応を迫られてしまう。
またスキーマは、同じXML構造を表すのにも異なった定義方法が可能である。スキーマの解読はミドルウエアによって違うので、複雑なスキーマ定義は問題が発生するかもしれない。そのため、できるだけ平易な表現で記述し、いくつかのミドルウエアで動作確認を行ってから配布した方が確実である。
・スキーマのサンプル
<?xml version="1.0" encoding="utf-8"?>
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="getHello">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="str" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="getHelloResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="getHelloResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />
</s:schema>
|
5.RESTの特徴
RESTの最大の特徴は「
利用し易い」「
確認し易い」である。WebブラウザにURLを入力するだけで、動作確認をおこなうことができる。これは、古くからあるSMTPやFTPのプロトコルが、telnetコマンドを使って手動で動作確認ができる事と同様に、Internet上のサービスに対して「簡単に動作確認ができる」というのは、非常に便利である。
また、HTTP(もしくはTCP/IP)とXMLがあれば使えるので、多くの開発言語で利用できる。
RESTでは、入力パラメータとして可変の部分をURLの一部として表現する。
例. | http://hostname/hoge.cgi?id=1234 |
| http://hostname/hoge.cgi/id/1234/ |
| 改行、スペース、日本語などはエンコード |
そのため、パラメータの数が多くなってくると、URLが非常に長くなる危険がある。「
RFC2616 Hypertext Transfer Protocol -- HTTP/1.1」によれば、HTTPの仕様上はURLに長さ制限はないが、ネットワーク環境によっては問題が起きる可能性があるので、長くなり過ぎないように注意しなければならない。
開発については、cgiなどのWebアプリ開発とまったく同じである。
サーバ側 |
入力 | Java:request.getParameter("param1")
PHP:$_GET['param1']
その他:QUERY_STRINGなど |
出力 | HTMLではなくXMLを返す |
クライアント側 |
リクエスト | HTTPかTCPを操作するメソッドを利用
JavaScript:XMLHttpRequest、ActiveXObject ("Microsoft.XMLHTTP")
Java:HttpURLConnection
|
|
レスポンス | XMLが返ってくるので、DOM APIで操作 |
日本語を扱う場合は、文字コードの扱いや、特殊文字の文字化けに注意しなければならない。「一貫してUTF-8で通す」とするのが確実である。
クライアントとしては、多くの開発言語でHTTPもしくはTCPが扱えるので、ほとんどの環境で開発可能である。もしも開発言語からTCPが使えなくても、外部コマンド呼び出しさえできれば、
telnetコマンドや
wgetコマンドを使ってRESTを呼び出す事もできる。
6.SOAPの特徴
SOAPの最大の特徴は「
WS-*による拡張性」である。WS-*とはさまざまなSOAPの機能拡張の総称である。
W3C(World Wide Web Consortium)や
OASIS(Organization for the Advancement of Structured Information Standards)などの標準化団体によって標準化されており、特定ベンダーによる囲い込みの心配が少なく、様々な開発言語で利用できる可能性がある。
WS-*には、検討中の物まで含めると、非常に沢山の仕様がある。
通常、「SOAPのためのミドルウエア」と言った場合、これらのWS-*までは含んでいない。WS-*を使うためには、目的のWS-*を使うためのミドルウエアの導入が必要だし、まだそのミドルウエアが存在していないかもしれない。
また、「WS-*を導入すれば、問題がすべて簡単に解決する」わけではないので、十分な検証作業が必要である。
XMLコンソーシアムのsPlatでも、
WS-Securityの最大の特徴であるEnd-to-Endのセキュリティを実現しようとした場合の課題について検討しているが、現状のWS-Security用ミドルウエアではPoint-to-Pointは問題ないが、End-to-Endの場合は簡単に実現できないのが現状である。
WS-*では、1つの仕様の扱う範囲が広く、他仕様と関連する場合もある。同じミドルウエア同士で接続するのであれば問題は少ないだろうが、違うミドルウエア同士で接続するのであれば、残念ながら「簡単につながる」わけではない。
7.開発方法
例として、サービス提供側の開発の流れを追っていく。ここでは、RESTとSOAPの両方を提供する場合を考えていく。
- 送受信するXMLデータの構造を定義する
まずは、送受信するXMLデータの構造(=スキーマ)を定義する。ここで入力パラメータが単純であればRESTにも対応できるし、複雑であればSOAPのみとなってしまう。
利用できる標準化されたスキーマ定義があれば良いのだが、無い場合にはスキーマを作成する必要がある。Javaなどの開発言語で書いたデータBeanによってスキーマ定義を自動生成してくれるツールもあるが、そのツールに依存した記述方法で出力する危険がある。「できるだけ多くの人に利用して欲しい」のであれば、平易な記述方法だけを使い、複数のツールで正常に読み込めて、想定通りの動きをするか確認するのが確実である。
- SOAPに対応するのであれば、WSDLを記述する
スキーマを使って、WSDLを記述する。WSDLを作成することでインターフェイスが明確になる。
WSDLをミドルウエアに読み込ませれば、スケルトンを自動生成してくれるので、あとは実際の処理やDBアクセスなどの中身を開発するだけである。
スキーマやWSDLを記述するのは大変だが、特定のツールに依存しないためにも、後のメンテナンス性を確保するためにも、自動生成に頼らない方が確実である。
提供側が受信するパラメータが単純であれば、『SOAPを作成すれば自動的にRESTにも対応してくれる』ミドルウエア(Axis2, .net Framework等)もある。
中身の開発については、各開発言語ごとの開発手法を使うこと。
- RESTに対応するのであれば、入出力のサンプルを作成する
WADLも書いた方がもちろん良いのだが、今のところ利用できるツールが少ないため、ドキュメントとしてしか利用できないだろう。
指定されるURLと結果のXMLのサンプルデータを作成する。サンプルデータを作っておけば「仕様が明確になる」「テストデータとして使える」「利用者へサンプルとして提供する」と活用できるので、作っておいて損はない。
SOAPの場合も、サンプルのSOAPメッセージを作成しておくと、色々と便利である。
- テスト
RESTであればブラウザでアクセスしてみるのが簡単である。
また、ミドルウエアが提供してくれるテスト画面を使う方法もあるが、HTTPを使っているメリットの1つとして、Webサイト用のテストツールがそのまま使える。Webサイトのテストや負荷試験のために、無料/有料のさまざまなツールがあるが、そのほとんどが使える。SOAPであっても、POSTデータとしてXMLを送信すれば結果のXMLを受信できるし、パラメータを動的に変化させるテストもWebサイトの場合と同様である。
サービス提供側の流れは以上である。上記以外の部分については、Webサイト開発と同じである。
次に、サービス利用者でRESTを使いたければ、HTTPもしくはTCPの機能を利用し、URLを作成すれば利用することができる。
例えば、JavaScriptからのRESTの呼び出しは、以下のようなコードで実現できる。
・RESTアクセスのサンプル(JavaScript)
function requestRest(){
var endpoint = "http://ホスト名/WebSite1/WebService.asmx"; // 送信先
var param1 = "keywork"; // パラメータ
// URLを生成
var url = endpoint + "/getHello?str=" + encodeURI(param1) + "&dummy="+(new Date().getTime());
// XMLHttpRequestを作成
try {
xmlhttp = new XMLHttpRequest(); // Netscape, Firefoxなど
} catch (e){
try {
xmlhttp = new ActiveXObject ("Msxml2.XMLHTTP"); // IE
} catch (e){
try {
xmlhttp = new ActiveXObject ("Microsoft.XMLHTTP"); // IE
} catch (e){
// XMLHttpRequestの作成に失敗
}
}
}
xmlhttp.onreadystatechange = method1; // レスポンスを受け取った時に呼ばれるメソッドを指定
xmlhttp.open('GET', url, true);
xmlhttp.setRequestHeader ("Content-Type","text/xml; charset=utf-8");
xmlhttp.send(); // RESTで送信
}
function method1() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText); // 結果をデバッグ表示
}
}
|
URLの最後に、現在のミリ秒を追加しているのは、途中の経路でキャッシュを参照されるのを防ぐためである。
「パラメータの型は合っているか?」「必須パラメータはセットされているか?」「関係無いパラメータはセットされていないか?」は呼び出し前に自動でチェックはできない。サーバからエラーが返ってきて、初めて問題が分かる。
サービス利用者でSOAPを使いたい人は、SOAP対応のミドルウエアを利用し、WSDLを読みこめば簡単に利用することができる。
通常であれば、その自動生成されたコードでSOAPを呼び出す。
しかし、開発言語によってはミドルウエアが無いかもしれないし、何かの理由でミドルウエアが追加できない環境かもしれない。そのような場合にも、DOMのAPIを駆使してSOAPメッセージを作成したり、元SOAPメッセージをStringで持っておいてパラメータ部分だけを変更すれば、利用できないわけではない。
例えば、JavaScriptからのSOAPの呼び出しは、以下のようなコードでなんとか実現できる。
・SOAPアクセスのサンプル(JavaScript)
function requestSoap(){
var endpoint = "http://ホスト名/WebSite1/WebService.asmx"; // 送信先
var param1 = "keywork"; // パラメータ
// SOAPメッセージを作成
var msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\
<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n\
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n\
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n\
<soap:Body>\n\
<getHello xmlns=\"http://tempuri.org/\">\n\
<str>" + param1 + "</str>\n\
</getHello>\n\
</soap:Body>\n\
</soap:Envelope>";
// XMLHttpRequestを作成
try {
xmlhttp = new XMLHttpRequest(); // Netscape, Firefoxなど
} catch (e){
try {
xmlhttp = new ActiveXObject ("Msxml2.XMLHTTP"); // IE
} catch (e){
try {
xmlhttp = new ActiveXObject ("Microsoft.XMLHTTP"); // IE
} catch (e){
// XMLHttpRequestの作成に失敗
}
}
}
xmlhttp.onreadystatechange = method2; // レスポンスを受け取った時に呼ばれるメソッドを指定
xmlhttp.open('POST', endpoint, true);
xmlhttp.setRequestHeader ("Content-Type","text/xml; charset=utf-8");
xmlhttp.setRequestHeader ("SOAPAction","\"http://tempuri.org/getHello\"");
xmlhttp.send(msg); // SOAPメッセージを送信
}
function method2() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
xmlDoc = xmlhttp.responseXML; // 結果をDOMオブジェクトとして取得
}
}
|
しかし、これではパラメータの型はチェックされないし、 "<"のような文字が入っていてもそのまま送信してしまう。DOMのAPIを使っていないために、送信前に「スキーマに合致しているか?」や「XMLとして正しいか?」をチェックすることができない。ミドルウエアで自動生成されたコードを使っていれば、コンパイル時に問題を検出できたり、インラインヘルプといった開発ツールの支援機能を有効に使うことができる。
それを自前で実装すると、コンパイラなどによるチェックが働かないので、正しくないSOAPメッセージを送信してしまう危険がある。その場合、SOAPの特徴である「送信データがXML」のメリットがあまり生かされない。それでも、「サーバがSOAPしか対応しておらず、クライアントがSOAPに対応できない」場合には、上記のように「形だけSOAPのフリ」をすることで、サーバを呼び出すことができるのである。
やっとSOAPが使えるようになり始めた2000年頃は、「異なる実装・開発言語間であっても簡単につながる」ということが非常にアピールされていた。それほど、CORBAやRPCなどの他のシステム間連携プロトコルは「つながらない現実があった」わけである。また、バイナリで通信するために自力で接続問題を解決する事が困難だった。SOAPやRESTはテキストで通信するので、通信内容を人間が確認することができるし、問題部分にWebサーバのフィルタ機能を使って通信内容に手を加えての解決も可能である。
8.その他のアプローチ
SOAPやREST以外にも、ブラウザからHTTPを使ったメッセージ交換の方法として、以下のようなアプローチがある。
サーバからHTMLやHTMLの一部を返す方法は、ずっと以前から使われている。<div>タグの中身だけを差し替えたり、最も単純な例として<frame>タグを使って画面の一部を書き換えることで、元画面を残しつつ画面の一部を更新する手法は以前から使われている。
逆に、「通常のHTMLを返す」サイトに対して、「XHTMLに変換する」プロキシを通すことで、通常サイトの情報をXMLとして操作する手法もある。
JSON(
Java
Script
Object
Notation)は、RESTとほぼ同じだが、レスポンスとしてXMLではなくJavaScriptにおけるオブジェクトの表記法を使ったデータを返す。
JavaScriptで簡単にオブジェクトに変換でき、XMLと比べるとデータの転送量が少なくて済み、XMLをパースする必要がないので高速に処理できる。ただし、JavaScriptに特化したデータ形式に変換してしまうので、JavaScript以外では扱い辛くなってしまう。
JSONP(
JSON with
Padding)は、JavaScriptにはドメイン境界の問題があるために、JSONでは他サイトに対するリクエストを直接行うことができない。そのため、自サイトにプロキシを設置する必要があった。その問題を回避するために、JSONPでは「<script src="
http://...">の指定なら、他ドメインにアクセスできる」という特性を利用し、ドメイン境界の問題を解決している。
ただし、これはJavaScriptのセキュリティの抜け道を使った方法なので、セキュリティ上あまりよい方法ではないし、ブラウザによっては使用できないかもしれない。
ライブラリの提供は、
Yahoo!,
Google,
Amazon S3などでは様々な開発言語用のライブラリが提供されている。これらのライブラリを使えば、RESTやSOAPを意識せずにサービスを利用することが可能である。Ajaxが注目されるキッカケとなった
GoogleMapsは、HTMLを修正するだけで自分のサイトに簡単に埋め込めたので、cgiが使えないサイトでも利用することができ、より多くの人に利用してもらう事が出来たのだろう。
しかし、ライブラリを提供するのはコストがかかるし、利用者側にとっても「ライブラリの使い方を覚える」という別の学習コストが発生してしまう。
9.どちらを選択すべきか?
実際に開発してみると、WS-*の機能が必須でない限り、RESTかSOAPという事はあまり問題にはならない。HTTPのGETしか使えない環境でない限り、HTTPを直接操作すればどちらにも何とかアクセスできて結果が取得できるし、cgiやservletの機能を使えばサービスも提供できる。実際には、想定しているサービス利用者の特徴に合った方を選択する、というのが現実的であろう。
RESTは、簡単に試せるし、初期の学習コストが低いというメリットがある。サーバ側はWebサイト開発と同じ技術が使えるし、クライアント側はHTTPとXMLを解析するためのDOM APIが使えれれば、開発言語を選ばず利用できる。
RESTは「GETを使っているので、入力パラメータが少ない」というのが最大の弱点にもなるが、「POSTで大量のパラメータを送る」というのも可能である。これは<form method="POST">と同じである。
このような特徴をふまえると、RESTでは
不特定多数を対象にした、入力パラメータが少ない情報配信や検索サービス等での利用に向いている。多くの入力パラメータを送信したい場合には、POSTを使ったり、セッションを使って複数に分割して送る必要があり、利用する側が「単純なRESTとは違う送信方法」をコーディングするという手間が発生してしまう。Internet上に無料で使える検索サービスが多数あるが、このような不特定多数が利用できる情報取得サービスが、まさにREST向きである。
SOAPは、高機能であるがゆえに、初期の学習コストが高くついてしまう。ミドルウエアが無いと手軽に使えないので、使用するミドルウエアについても学習しなければならない。逆に、ミドルウエアにWSDLを読み込ませる事によって、SOAPを呼び出すためのスタブ生成やスキーマに対応するBean生成などが自動化されるというメリットがある。そうすれば「SOAPを使っている」という事を意識せずに開発が行える。RESTでの自動化は進んでいないが、単純な文字列の結合で済むのであまり必要とされないだろう。
SOAPを選択する最大の動機は、WS-*である。しかし、残念ながらWS-*でなければならない場面は今のところ多くないし、WS-*以外の方法を使うことで解決できる可能性もある。
(例えば、WS-Securityの否認のような機能が必要であれば、httpsと通信メッセージ保管によって『内容証明郵便』のような機能を第三者に提供するようなサービスが登場するかもしれない)
このような特徴をふまえると、SOAPでは
複雑な入力を必要としたり、入出力に対してチェックを必要とするようなサービス等での利用に向いている。大量のデータ登録、システム間連携やB2Bなどに向いている。また、WS-*を必須とする場合には、SOAPでなければならない。
・各方式の比較
| SOAP | REST | JSON |
学習容易性 | × | ○ | ○ |
コーディング量(自動生成分は除く) | ○ | × | ○ |
テストのし易さ | × | ◎ | × |
開発ツール | ○ | × | × |
導入の容易性 | × | ○ | ○ |
開発にかかるトータル時間 | × | ○ | ◎ |
複雑なデータの入力 | ○ | × | × |
複雑なデータの出力 | ○ | ○ | △ |
厳密な型チェック | ○ | × | × |
汎用性(扱える開発言語の種類) | ○ | ○ | × |
標準化団体 | W3C | - | ecma |
拡張性(WS-*) | ◎ | × | × |
サーバとクライアントの両方を自前で開発し、他に公開しないのであれば、RESTとSOAPのどちらを選んでも差を感じないだろう。もしJavaScriptからしかアクセスしないのであれば、JSONを使った方がパフォーマンスや開発効率が良いかもしれない。
しかし、公開されているサービスを利用する側から見ると、提供されている物を使うという事になってしまう。そこで、RESTとSOAPの両方が使えると選択肢が増えて利用し易いのだが、それ以上にサービスの提供形態が使い勝手を大きく左右する。
サービスの提供方法は、以下のように変化してきている。
- リクエストとレスポンスの生メッセージの提示
- WSDL,WADLなどの提供
- クライアント用ライブラリの提供
ライブラリを提供されると利用者にとっては便利なのだが、それを使えない環境の場合には対処できなくなってしまう。提供する側は、過去の形式も更新しつつ、新しい方法でも提供する必要がある。
また、サービスを提供する上では、以下のような課題がある。
- ユーザー認証方式
- サービスの粒度
- ドメイン境界
- セキュリティ
まずは、認証が必要かどうかを考える必要がある。もし、認証が必要であるなら、認証と目的のリクエストを別にするのか、それとも1回のリクエスト中にBASIC認証かパラメータの一部にユーザー情報を含めるかを決める。また、マッシュアップをおこなうと事態がより複雑になる。認証するユーザーは、大元の利用者なのか、そのサービスを直接呼び出しているサイトなのか、外部認証サービスを利用するのか、など、ポータルサイトと同様の課題が発生する。
どの方式でサービスを提供するにしても、「
サービスの粒度」は非常に重要である。大き過ぎると使いにくいし、小さ過ぎると何度も呼び出さないといけないので面倒になる。
ブラウザからの利用を想定すると、ブラウザのドメイン境界の制限があある。
GoogleMapsのように、HTMLの修正だけで組み込める形で提供できれば理想的だが、そのためにJSONPのような手法を使うとブラウザのセキュリティ更新で動かなくなる危険もある。ブラウザのJavaScriptからダイレクトに利用する場合と、Webサーバが中継して利用する場合の両方を想定する必要がある。
セキュリティについては、非常に多くの点に十分に注意しなければならない。「途中の経路での盗聴」「不正アクセスによる情報漏えい」「攻撃によるデータ破壊」など、もし攻撃を受けると大きな被害を受けてしまう。しかし、これらの攻撃については、Webサイト構築での経験が非常に参考になるはずである。
利用する側にとっては、Webサイトを利用する場合と同じような要望が出てくるだろう。
- RESTを使いたいのに、提供されているサービスはSOAPしかない→ゲートウエイ
- 1画面に表示したい情報を取得するために、何度もサービスを呼び出す必要がある→ゲートウエイ
- マッシュアップするサービス群が、REST/SOAPがバラバラで、スキーマも全然違う→アグリゲーション
- 過去のある時点でのレスポンスが欲しい→アーカイブサービス、REST向き
- 応答が遅い→キャッシュサービス、REST向き
そして、Internet上でこれらのサービスを提供するサイトが登場してくるはずである。RESTとSOAPの変換サービスは、特定のサービス用の物であればすでに色々と登場しているし、様々なサービスをまとめて1つのRESTに変換してくれる
Yahoo!Pipesもある。
RESTは使い易く、簡単に導入できる。SOAPならミドルウエアやライブラリを有効に利用できれば、楽に開発ができる。そのため、RESTとSOAPの両方を提供した方が、利用者にとって便利なのは言うまでもない。
Copyright (c) XML コンソーシアム 2007 All rights reserved.
Copyright (c) アドソル日進株式会社 2007 All rights reserved.
「エンタープライズ・システムのためのWeb 2.0」目次に戻る