特集
次世代XML Webサービスを試す Part 3
SOAPメッセージのルーティング(後編)

5.WS-Referralを利用したルーティング(1)

インフォテリア株式会社
吉松 史彰
2003/02/27

Page1 Page2 Page3 Page4 Page5 Page6

WS-Referral

 WSEを使ってサーバ側で経路を指定する方法は、独自にルータを実装する以外にもう1つある。WS-Referral仕様に基づくリファラル・キャッシュを利用する方法だ。WS-Referralとは、特定のSOAP actor(SOAPを処理できるサーバと考えてよい)を示すURIが、どのエンド・ポイントに存在するかを示す文書の書き方の仕様だ。WS-Referral仕様の日本語訳はマイクロソフトのホームページで参照できる(WS-Referral仕様の日本語訳)。WS-Referralも、2003年1月現在では、まだどの標準化団体にも提出されていない、Microsoftが提唱している独自仕様だ。

 WS-Referral仕様では、次のようなリファラル文書の書き方を定義している。

<r:referrals
    xmlns:r="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <r:ref>
    <r:for>
      <r:exact>http://localhost/WSERouting/Service1.asmx</r:exact>
    </r:for>
    <r:if />
    <r:go>
      <r:via>http://localhost/WSERouting/c.ashx</r:via>
    </r:go>
    <r:refId>uuid:8f18381e-36d7-483e-9512-4ee45ef7524c</r:refId>
  </r:ref>
</r:referrals>
WS-Referral仕様によるリファラル文書の定義例

 リファラル文書は、referralsという名前のルート要素を持ち、referralsには複数のrefという子要素を持つことができる。ref要素には5つの子要素が定義されている(下表)。要素はすべてhttp://schemas.xmlsoap.org/ws/2001/10/referralという名前空間に属している。

要素名 内容 必須
for あて先に指定されたSOAP actor
if このリファラルが適用されるかどうかの条件
go forに指定されたactorを指すエンド・ポイント・アドレス
refId このリファラルを一意に識別するID
desc このリファラルの説明 ×
表 WS-Referral仕様で定義されているリファラル文書の要素

 例えば上記のリファラル文書は、

「http://localhost/WSERouting/Service1.asmxというSOAP actorにアクセスするには、http://localhost/WSERouting/c.ashxに転送すればよい」

という意味になる。if要素にはあて先以外の条件を指定できる。条件は独自に拡張して構わないが、WS-Referral仕様にはttl要素とinvalidates要素の2つが定義されている。ttl要素には有効期限となる時間(time-to-live)を、invalidates要素にはほかのリファラルのIDを指定して、それを無効化する効果がある(条件ではない)。

 for要素には、子要素としてprefixとexactを設定することができる。上記はexactを指定しているので、指定されたURIと正確に一致するSOAPメッセージのみが対象となる。prefixを指定すると、「URIが〜で始まる場合」という指定をしたことになる。for要素にはprefixとexactを2つ以上設定できる。その場合はOR条件となる。

 go要素には複数のvia子要素を設定できる。via子要素には通過点となるSOAPルータのアドレスを設定する。go要素にvia要素を複数設定した場合には、設定された中から1つだけが選択されて利用される。選択のアルゴリズムは決まっていない。

WSEとWS-Referral

 WSEでは、WS-Referral仕様にのっとって記述された文書をファイルから読み取って、それを元にSOAPメッセージの経路を決める機能がある。この機能はWSEのデフォルトのルータ実装であるRoutingHandlerが持っている。RoutingHandlerは、次に述べる手順により、リファラル文書を読み取って経路を構成することができる。このルータを利用した、以下の図のようなパターンのXML Webサービスとそのクライアントを作成してみよう。

リファラル文書によるルーティング
ルータはリファラル文書を読み取り、XML Webサービスまでの経路を構成することができる。

Visual Studio .NET(以下VS.NET)でASP.NET Webサービス・プロジェクトを新しく作成する。ここでは名前を「WSERouting」とした。

VS.NETの「参照の追加」機能でMicrosoft.Web.Services.dllへ参照を追加する。

Service1.asmx.csファイルに次のようなWebMethodを記述する。

[WebMethod]
public string Echo(string input) {
  return input;
}
Webサービスの本体となるメソッド

Web.configファイルを編集して、system.web要素の子要素になるように次の要素を記述して、XML Webサービスの実行時にSoapExtensionが起動されるようにする。

<webServices>
  <soapExtensionTypes>
    <add type="Microsoft.Web.Services.WebServicesExtension, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0"/>
  </soapExtensionTypes>
</webServices>
Web.configファイルでのSoapExtensionの設定
Webサービスの実行時にSoapExtensionが起動されるようにする。

Web.configファイルを編集して、configuration要素の直下に次の子要素を記述する。これによって、RoutingHandlerがリファラル文書を取得できるようになる。referral.xmlがリファラル文書の名前だ。

<configSections>
  <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<microsoft.web.services>
  <referral>
    <cache name="referral.xml" />
  </referral>
</microsoft.web.services>
Web.configファイルによるリファラル文書の指定

Web.configと同じフォルダにreferral.xmlという名前のファイルを作成する。内容は次のようなリファラル文書だ。

<r:referrals xmlns:r="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <r:ref>
    <r:for>
      <r:exact>http://localhost/WSERouting/Service1.asmx</r:exact>
    </r:for>
    <r:if />
    <r:go>
      <r:via>http://localhost/WSERouting/c.ashx</r:via>
    </r:go>
    <r:refId>uuid:4f9f03e2-11b6-46d5-8677-122446c40042</r:refId>
  </r:ref>
  <r:ref>
    <r:for>
      <r:exact>http://localhost/WSERouting/c.ashx</r:exact>
    </r:for>
    <r:if />
    <r:go>
      <r:via>http://localhost/WSERouting/b.ashx</r:via>
    </r:go>
    <r:refId>uuid:87847570-df11-4e01-99db-1afd810bc4f7</r:refId>
  </r:ref>
  <r:ref>
    <r:for>
      <r:exact>http://localhost/WSERouting/b.ashx</r:exact>
    </r:for>
    <r:if />
    <r:go>
      <r:via>http://localhost/WSERouting/a.ashx</r:via>
    </r:go>
    <r:refId>uuid:b58c9200-2b8c-4710-9a5d-26c7cb5eb0f5</r:refId>
  </r:ref>
</r:referrals>
リファラル文書となるreferral.xml
Web.configと同じフォルダに作成する。

 この文書では、Service1.asmxに対する要求はc.ashxを経由し、c.ashxに対する要求はb.ashxを経由し、b.ashxに対する要求はa.ashxを経由することになっている。つまり、

  a.ashx → b.ashx → c.ashx → Service1.asmx

という経路が作成されることになる。

Web.configファイルを編集して、system.web要素の子要素になるように次の要素を記述して、HTTPハンドラをHTTPパイプラインに挿入する。

<httpHandlers>
  <add type="WSERouting.NopRouter, WSERouting"
                                      path="a.ashx" verb="*" />
  <add type="WSERouting.NopRouter, WSERouting"
                                      path="b.ashx" verb="*" />
  <add type="WSERouting.NopRouter, WSERouting"
                                      path="c.ashx" verb="*" />
  <add type="Microsoft.Web.Services.Routing.RoutingHandler, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" path="*.ashx" verb="*" />
</httpHandlers>
Web.configファイルでのHTTPハンドラの設定
各.ashxに対する処理クラスを記述している。a.ashx、b.ashx、c.ashxはNopRouterクラスが、それ以外の*.ashxに対してはRoutingHandlerクラスが処理を行う。

 通常の*.ashxに対する要求はRoutingHandlerクラスが処理するが、a.ashx、b.ashx、c.ashxはNopRouterクラスが処理を行う設定になっている。NopRouterクラスの実装は次のようなものだ。要するに何もしないのである。

namespace WSERouting {
  public class NopRouter : RoutingHandler {

    protected override void ProcessRequestMessage(
        SoapEnvelope message, Path outgoingPath) {}

    protected override void
      ProcessResponseMessage(SoapEnvelope message) {}
  }
}
NopRouterクラスの実装
このクラスは何もしないルータを記述している。

 RoutingHandlerは、呼び出されるたびにWeb.configの設定を確認してリファラル文書から経路を作成しようとする。つまり、a.ashx、b.ashx、c.ashxに対してRoutingHandlerが処理を行ってしまうと、すでに設定してある経路に対してさらに経路を設定することになり、経路がループしてしまう。最初に作成された経路を使ってあとは処理を転送するだけにするために、何もしないルータをRoutingHandlerとは別に用意してそれを指定しているわけだ。今回はすべてのルータが同じ拡張子を利用しているため、拡張子で処理を分けているASP.NETでは違いを判断できない。仕方なくこのようなハッキングを行っている。


 INDEX
  [特集]次世代XML Webサービスを試す Part 3
  SOAPメッセージのルーティング
    1.SOAPメッセージのルーティングを規定するWS-Routing
    2.WSEでのWS-Routing利用
    3.WS-RoutingのSOAPメッセージ
    4.WSEによるルータの実装
  5.WS-Referralを利用したルーティング(1)
    6.WS-Referralを利用したルーティング(2)
 
 「特集:次世代XML Webサービスを試す」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間