HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

nusoapを使ってみる

SOAP自体、今更感が満載だが、使われているもの(何)に遭遇してしまったので、さらっと試してみようかということで。

まずは環境。

以下のようなディレクトリ構成を作る。

 + soap_test
 |  + nusoap  (nusoap-0.9.5.zip に含まれるlibディレクトリをコピーしたもの)
 |  |  - nusoap.php
 |  |     :
 |  + test1
 |  |  + server
 |  |  |  - index.php
 |  |  + client
 |  |  |  - index.php
 |  + test2
 |  |  + server
 |  |  |  - index.php
 |  |  + client
 |  |  |  - index.php
 |  + test3
 |  |  + server
 |  |  |  - index.php
 |  |  + client
 |  |  |  - index.php
 |  |  - test3.wsdl

で、このsoap_testディレクトリをApache httpdのDocumentRootに設定。

まずはシンプルに

とりあえずメソッドを呼び出すだけのサンプル。(test1)
サーバー側:

<?php
    date_default_timezone_set('Asia/Tokyo');

    require_once('../../nusoap/nusoap.php');

    define('NAME_SPACE', 'http://example.com/hhelibex');

    $server = new nusoap_server(false);

    $server->debug_flag=false;
    $server->configureWSDL('SOAP-Test1 API WSDL', NAME_SPACE);
    $server->wsdl->schemaTargetNamespace = NAME_SPACE;

    $server->wsdl->addComplexType(
        'CalcResults',
        'comprexType',
        'struct',
        'all',
        '',
        array(
            'add' => array('name' => 'add', 'type' => 'xsd:int'),
            'sub' => array('name' => 'sub', 'type' => 'xsd:int'),
            'mul' => array('name' => 'mul', 'type' => 'xsd:int'),
            'div' => array('name' => 'div', 'type' => 'xsd:int'),
        )
    );
    $server->register('calc',
                    array('arg1' => 'xsd:int', 'arg2' => 'xsd:int', 'arg3' => 'xsd:string'),
                    array('param' => 'xsd:string', 'msg' => 'xsd:string', 'result' => 'tns:CalcResults'),
                    NAME_SPACE,
                    NAME_SPACE . '#calc',
                    'rpc',
                    'encoded',
                    'method calc(arg1, arg2, arg3)'
                );

    function calc($arg1, $arg2, $arg3) {
        $ret['param'] ="arg1 => " . var_export($arg1, true)
                    . ", arg2 => " . var_export($arg2, true)
                    . ", arg3 => " . var_export($arg3, true);
        $ret['msg'] = "おーけー: {$arg1} * {$arg2}";
        $ret['result'] = array(
            'add' => $arg1 + $arg2,
            'sub' => $arg1 - $arg2,
            'mul' => $arg1 * $arg2,
            'div' => $arg1 / $arg2,
        );
        return $ret;
    }

    $HTTP_RAW_POST_DATA = file_get_contents("php://input");
    $server->service($HTTP_RAW_POST_DATA);
?>

クライアント側:

<pre><?php
    date_default_timezone_set('Asia/Tokyo');

    require_once('../../nusoap/nusoap.php');

    $endPoint = 'http://localhost/test1/server/index.php';

    // 呼び出してみる
    $client = new nusoap_client($endPoint, false);
    $params = array('arg1' => 35, 'arg2' => 7, 'arg3' => 'てすと1の1');
    $result = $client->call('calc', $params);

    print_r($result);

    // パラメータ名を逆にしても結果は変わらない(⇒WSDLを見てない)
    $client = new nusoap_client($endPoint, false);
    $params = array('arg2' => 35, 'arg1' => 7, 'arg3' => 'てすと1の2');
    $result = $client->call('calc', $params);

    print_r($result);
?></pre>

出力される結果は次のような感じ(一部改行を削除しています)。

Array
(
    [param] => arg1 => 35, arg2 => 7, arg3 => 'てすと1の1'
    [msg] => おーけー: 35 * 7
    [result] => Array
        (
            [add] => 42
            [sub] => 28
            [mul] => 245
            [div] => 5
        )
)
Array
(
    [param] => arg1 => 35, arg2 => 7, arg3 => 'てすと1の2'
    [msg] => おーけー: 35 * 7
    [result] => Array
        (
            [add] => 42
            [sub] => 28
            [mul] => 245
            [div] => 5
        )
)

WSDLを解釈させる(1)

サーバー側にあるWSDL定義を参照するサンプル。(test2)
サーバー側:
内容的にはtest1と同じなので省略。
クライアント側:

<pre><?php
    date_default_timezone_set('Asia/Tokyo');

    require_once('../../nusoap/nusoap.php');

    $endPoint = 'http://localhost/test2/server/index.php?wsdl';

    // 呼び出してみる
    $client = new nusoap_client($endPoint, true);
    $params = array('arg1' => 35, 'arg2' => 7, 'arg3' => 'てすと2の1');
    $result = $client->call('calc', $params);

    print_r($result);

    // パラメータ名を逆にしてもちゃんと解釈してくれる
    $client = new nusoap_client($endPoint, true);
    $params = array('arg2' => 35, 'arg1' => 7, 'arg3' => 'てすと2の2');
    $result = $client->call('calc', $params);

    print_r($result);
?></pre>

クライアント側の変更点は、エンドポイントのURLにパラメータ「?wsdl」をつけ、nusoap_clientのコンストラクタの第二引数に「true」を指定するようにした点。
ブラウザで上記エンドポイントURLを参照してみると分かるのだが、「?wsdl」パラメータをつけることでWSDL定義を取得することができるので、それを利用している。もちろん、どこかに保存した静的なファイルを参照してもOK。


出力される結果は次のような感じ(一部改行を削除しています)。

Array
(
    [param] => arg1 => 35, arg2 => 7, arg3 => 'てすと2の1'
    [msg] => おーけー: 35 * 7
    [result] => Array
        (
            [add] => 42
            [sub] => 28
            [mul] => 245
            [div] => 5
        )
)
Array
(
    [param] => arg1 => 7, arg2 => 35, arg3 => 'てすと2の2'
    [msg] => おーけー: 7 * 35
    [result] => Array
        (
            [add] => 42
            [sub] => -28
            [mul] => 245
            [div] => 0
        )
)

今度は、クライアント側で指定したパラメータ名どおりにパラメータが渡されているのが分かる。

WSDLを解釈させる(2)

ローカルにある静的なWSDL定義を参照するサンプル。(test3)
サーバー側:

<?php
    date_default_timezone_set('Asia/Tokyo');

    require_once('../../nusoap/nusoap.php');

    define('NAME_SPACE', 'http://example.com/hhelibex');

    $server = new nusoap_server(new wsdl('../test3.wsdl'));

    $server->debug_flag=false;

    function calc($arg1, $arg2, $arg3) {
        $ret['param'] ="arg1 => " . var_export($arg1, true)
                    . ", arg2 => " . var_export($arg2, true)
                    . ", arg3 => " . var_export($arg3, true);
        $ret['msg'] = "おーけー: {$arg1} * {$arg2}";
        $ret['result'] = array(
            'add' => $arg1 + $arg2,
            'sub' => $arg1 - $arg2,
            'mul' => $arg1 * $arg2,
            'div' => $arg1 / $arg2,
        );
        return $ret;
    }

    $HTTP_RAW_POST_DATA = file_get_contents("php://input");
    $server->service($HTTP_RAW_POST_DATA);
?>

クライアント側:

<pre><?php
    date_default_timezone_set('Asia/Tokyo');

    require_once('../../nusoap/nusoap.php');

    $endPoint = new wsdl('../test3.wsdl');

    // 呼び出してみる
    $client = new nusoap_client($endPoint, true);
    $params = array('arg1' => 35, 'arg2' => 7, 'arg3' => 'てすと3の1');
    $result = $client->call('calc', $params);

    print_r($result);

    // パラメータ名を逆にしてもちゃんと解釈してくれる
    $client = new nusoap_client($endPoint, true);
    $params = array('arg2' => 35, 'arg1' => 7, 'arg3' => 'てすと3の2');
    $result = $client->call('calc', $params);

    print_r($result);
?></pre>

ここで指定している「../test3.wsdl」は、test2で「?wsdl」パラメータをつけて得られるWSDL定義を保存したものと同様の内容("Test2"⇒"Test3"に書き換えているが)。


出力される結果は次のような感じ(一部改行を削除しています)。

Array
(
    [param] => arg1 => 35, arg2 => 7, arg3 => 'てすと3の1'
    [msg] => おーけー: 35 * 7
    [result] => Array
        (
            [add] => 42
            [sub] => 28
            [mul] => 245
            [div] => 5
        )
)
Array
(
    [param] => arg1 => 7, arg2 => 35, arg3 => 'てすと3の2'
    [msg] => おーけー: 7 * 35
    [result] => Array
        (
            [add] => 42
            [sub] => -28
            [mul] => 245
            [div] => 0
        )
)

test2と同様に、クライアント側で指定したパラメータ名どおりにパラメータが渡されているのが分かる。

注意する必要があるかもしれないもの(謎)

文字エンコーディングについて

さらっと流してきたが、文字エンコーディングに関して注意する点があるようなないような、らしい(どっち)。

  • マルチバイト文字を扱う場合は、サーバー側とクライアント側で使用する文字エンコーディングは合わせておいたほうが無難。
    • ついでに言うと、クライアント側のプログラムで出力の文字エンコーディングを指定していないので、そのあたりも必要。
パスについて

上記のプログラムではいくつかのファイルを相対パスで参照しているが、絶対パスで書いたほうが確実かも。(よく分からないけど)