CodeIgniter XML-RPC 與 XML-RPC 服務(wù)器類

2018-07-21 15:40 更新

XML-RPC 與 XML-RPC 服務(wù)器類

CodeIgniter 的 XML-RPC 類允許你向另一個(gè)服務(wù)器發(fā)送請(qǐng)求, 或者建立一個(gè)你自己的 XML-RPC 服務(wù)器來(lái)接受請(qǐng)求。

什么是 XML-RPC ?

這是一種在兩臺(tái)計(jì)算機(jī)之間使用 XML 通過(guò)互聯(lián)網(wǎng)進(jìn)行通信的簡(jiǎn)單方法。 一臺(tái)計(jì)算機(jī) , 我們稱之為客戶端 , 發(fā)送一個(gè) XML-RPC 請(qǐng)求給另外一臺(tái)計(jì)算機(jī), 我們稱之為服務(wù)器,當(dāng)服務(wù)器收到請(qǐng)求時(shí),對(duì)其進(jìn)行處理然后將結(jié)果返回給客戶端。

例如,使用 MetaWeblog API 時(shí),XML-RPC 客戶端(通常是桌面發(fā)布工具) 將會(huì)發(fā)送請(qǐng)求到你站點(diǎn)上的 XML-RPC 服務(wù)器,這個(gè)請(qǐng)求可能是發(fā)布一篇新博客, 或者編輯一篇已有的博客。當(dāng) XML-RPC 服務(wù)器收到該請(qǐng)求時(shí),它會(huì)決定使用 哪個(gè)類和方法來(lái)處理該請(qǐng)求,請(qǐng)求處理完成后,服務(wù)器將發(fā)送一條回復(fù)消息。

關(guān)于 XML-RPC 的規(guī)范,你可以查看 XML-RPC 的網(wǎng)站。

使用 XML-RPC 類

初始化類

跟 CodeIgniter 中的其他類一樣,可以在你的控制器中使用 $this->load->library() 方法加載 XML-RPC 類和 XML-RPC 服務(wù)器類。

加載 XML-RPC 類如下:

$this->load->library('xmlrpc');

一旦加載,XML-RPC 類就可以像下面這樣使用:

$this->xmlrpc

加載 XML-RPC 服務(wù)器類如下:

$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');

一旦加載,XML-RPC 服務(wù)器類就可以像下面這樣使用:

$this->xmlrpcs

注解

當(dāng)使用 XML-RPC 服務(wù)器類時(shí),xmlrpc 和 xmlrpcs 都需要加載。

發(fā)送 XML-RPC 請(qǐng)求

向 XML-RPC 服務(wù)器發(fā)送一個(gè)請(qǐng)求,你需要指定以下信息:

  • 服務(wù)器的 URL
  • 你想要調(diào)用的服務(wù)器方法
  • 請(qǐng)求 數(shù)據(jù)(下面解釋)

下面是個(gè)基本的例子,向 Ping-o-Matic 發(fā)送一個(gè)簡(jiǎn)單的 Weblogs.com ping 請(qǐng)求。

$this->load->library('xmlrpc');

$this->xmlrpc->server('http://rpc.pingomatic.com/', 80);
$this->xmlrpc->method('weblogUpdates.ping');

$request = array('My Photoblog', 'http://www.my-site.com/photoblog/');
$this->xmlrpc->request($request);

if ( ! $this->xmlrpc->send_request())
{
    echo $this->xmlrpc->display_error();
}

解釋

上面的代碼初始化了一個(gè) XML-RPC 類,并設(shè)置了服務(wù)器 URL 和要調(diào)用的方法 (weblogUpdates.ping)。然后通過(guò) request() 方法編譯請(qǐng)求, 例子中請(qǐng)求是一個(gè)數(shù)組(標(biāo)題和你網(wǎng)站的 URL)。最后,使用 send_request() 方法發(fā)送完整的請(qǐng)求。如果發(fā)送請(qǐng)求方法返回 FALSE ,我們會(huì)顯示出 XML-RPC 服務(wù)器返回的錯(cuò)誤信息。

請(qǐng)求解析

XML-RPC 請(qǐng)求就是你發(fā)送給 XML-RPC 服務(wù)器的數(shù)據(jù),請(qǐng)求中的每一個(gè)數(shù)據(jù)也被稱為請(qǐng)求參數(shù)。 上面的例子中有兩個(gè)參數(shù):你網(wǎng)站的 URL 和 標(biāo)題。當(dāng) XML-RPC 服務(wù)器收到請(qǐng)求后, 它會(huì)查找它所需要的參數(shù)。

請(qǐng)求參數(shù)必須放在一個(gè)數(shù)組中,且數(shù)組中的每個(gè)參數(shù)都必須是 7 種數(shù)據(jù)類型中的一種 (string、number、date 等),如果你的參數(shù)不是 string 類型,你必須在請(qǐng)求數(shù)組中 指定它的數(shù)據(jù)類型。

下面是三個(gè)參數(shù)的簡(jiǎn)單例子:

$request = array('John', 'Doe', 'www.some-site.com');
$this->xmlrpc->request($request);

如果你的數(shù)據(jù)類型不是 string ,或者你有幾個(gè)不同類型的數(shù)據(jù),那么你需要將 每個(gè)參數(shù)放到它單獨(dú)的數(shù)組中,并在數(shù)組的第二位聲明其數(shù)據(jù)類型:

$request = array(
    array('John', 'string'),
    array('Doe', 'string'),
    array(FALSE, 'boolean'),
    array(12345, 'int')
);
$this->xmlrpc->request($request);

下面的 數(shù)據(jù)類型 一節(jié)列出了所有支持的數(shù)據(jù)類型。

創(chuàng)建一個(gè) XML-RPC 服務(wù)器

XML-RPC 服務(wù)器扮演著類似于交通警察的角色,等待進(jìn)入的請(qǐng)求, 并將它們轉(zhuǎn)到恰當(dāng)?shù)暮瘮?shù)進(jìn)行處理。

要?jiǎng)?chuàng)建你自己的 XML-RPC 服務(wù)器,你需要先在負(fù)責(zé)處理請(qǐng)求的控制器中初始化 XML-RPC 服務(wù)器類,然后設(shè)置一個(gè)映射數(shù)組,用于將請(qǐng)求轉(zhuǎn)發(fā)到合適的類和方法, 以便進(jìn)行處理。

下面是個(gè)例子:

$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');

$config['functions']['new_post'] = array('function' => 'My_blog.new_entry');
$config['functions']['update_post'] = array('function' => 'My_blog.update_entry');
$config['object'] = $this;

$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();

上例中包含了兩個(gè)服務(wù)器允許的請(qǐng)求方法,數(shù)組的左邊是允許的方法名, 數(shù)組的右邊是當(dāng)請(qǐng)求該方法時(shí),將會(huì)映射到的類和方法。

其中,'object' 是個(gè)特殊的鍵,用于傳遞一個(gè)實(shí)例對(duì)象,當(dāng)映射的方法無(wú)法使用 CodeIgniter 超級(jí)對(duì)象時(shí),它將是必須的。

換句話說(shuō),如果 XML-RPC 客戶端發(fā)送一個(gè)請(qǐng)求到 new_post 方法, 你的服務(wù)器會(huì)加載 My_blog 類并調(diào)用 new_entry 函數(shù)。如果這個(gè)請(qǐng)求是到update_post 方法的,那么你的服務(wù)器會(huì)加載 My_blog 類并調(diào)用 update_entry 方法。

上面例子中的函數(shù)名是任意的。你可以決定這些函數(shù)在你的服務(wù)器上叫什么名字, 如果你使用的是標(biāo)準(zhǔn)的 API,比如 Blogger 或者 MetaWeblog 的 API, 你必須使用標(biāo)準(zhǔn)的函數(shù)名。

這里還有兩個(gè)附加的配置項(xiàng),可以在服務(wù)器類初始化時(shí)配置使用。debug 設(shè)為 TRUE 以便調(diào)試, xss_clean 可被設(shè)置為 FALSE 以避免數(shù)據(jù)被安全類庫(kù)的 xss_clean 函數(shù)過(guò)濾。

處理服務(wù)器請(qǐng)求

當(dāng) XML-RPC 服務(wù)器收到請(qǐng)求并加載類與方法來(lái)處理時(shí),它會(huì)接收一個(gè)包含客戶端發(fā)送的數(shù)據(jù)參數(shù)。

在上面的例子中,如果請(qǐng)求的是 new_post 方法,服務(wù)器請(qǐng)求的類與方法會(huì)像這樣:

class My_blog extends CI_Controller {

    public function new_post($request)
    {

    }
}

$request 變量是一個(gè)由服務(wù)端匯集的對(duì)象,包含由 XML-RPC 客戶端發(fā)送來(lái)的數(shù)據(jù)。 使用該對(duì)象可以讓你訪問(wèn)到請(qǐng)求參數(shù)以便處理請(qǐng)求。請(qǐng)求處理完成后, 發(fā)送一個(gè)響應(yīng)返回給客戶端。

下面是一個(gè)實(shí)際的例子,使用 Blogger API 。Blogger API 中的一個(gè)方法是 getUserInfo(), XML-RPC 客戶端可以使用該方法發(fā)送用戶名和密碼到服務(wù)器,在服務(wù)器返回的數(shù)據(jù)中, 會(huì)包含該用戶的信息(昵稱,用戶 ID,Email 地址等等)。下面是處理的代碼:

class My_blog extends CI_Controller {

    public function getUserInfo($request)
    {
        $username = 'smitty';
        $password = 'secretsmittypass';

        $this->load->library('xmlrpc');

        $parameters = $request->output_parameters();

        if ($parameters[1] != $username && $parameters[2] != $password)
        {
            return $this->xmlrpc->send_error_message('100', 'Invalid Access');
        }

        $response = array(
            array(
                'nickname'  => array('Smitty', 'string'),
                'userid'    => array('99', 'string'),
                'url'       => array('http://yoursite.com', 'string'),
                'email'     => array('jsmith@yoursite.com', 'string'),
                'lastname'  => array('Smith', 'string'),
                'firstname' => array('John', 'string')
            ),
                         'struct'
        );

        return $this->xmlrpc->send_response($response);
    }
}

注意

output_parameters() 函數(shù)獲取一個(gè)由客戶端發(fā)送的請(qǐng)求參數(shù)數(shù)組。 上面的例子中輸出參數(shù)將會(huì)是用戶名和密碼。

如果客戶端發(fā)送的用戶名和密碼無(wú)效的話,將使用 send_error_message() 函數(shù)返回錯(cuò)誤信息。

如果操作成功,客戶端會(huì)收到包含用戶信息的響應(yīng)數(shù)組。

格式化響應(yīng)

和請(qǐng)求一樣,響應(yīng)也必須被格式化為數(shù)組。然而不同于請(qǐng)求信息,響應(yīng)數(shù)組 只包含一項(xiàng) 。 該項(xiàng)可以是一個(gè)包含其他數(shù)組的數(shù)組,但是只能有一個(gè)主數(shù)組,換句話說(shuō), 響應(yīng)的結(jié)果大概是下面這個(gè)樣子:

$response = array('Response data', 'array');

但是,響應(yīng)通常會(huì)包含多個(gè)信息。要做到這樣,我們必須把各個(gè)信息放到他們自己的數(shù)組中, 這樣主數(shù)組就始終只有一個(gè)數(shù)據(jù)項(xiàng)。下面是一個(gè)例子展示如何實(shí)現(xiàn)這樣的效果:

$response = array(
    array(
        'first_name' => array('John', 'string'),
        'last_name' => array('Doe', 'string'),
        'member_id' => array(123435, 'int'),
        'todo_list' => array(array('clean house', 'call mom', 'water plants'), 'array'),
    ),
    'struct'
);

注意:上面的數(shù)組被格式化為 struct,這是響應(yīng)最常見(jiàn)的數(shù)據(jù)類型。

如同請(qǐng)求一樣,響應(yīng)可以是七種數(shù)據(jù)類型中的一種,參見(jiàn) 數(shù)據(jù)類型 一節(jié)。

發(fā)送錯(cuò)誤信息

如果你需要發(fā)送錯(cuò)誤信息給客戶端,可以使用下面的代碼:

return $this->xmlrpc->send_error_message('123', 'Requested data not available');

第一個(gè)參數(shù)為錯(cuò)誤編號(hào),第二個(gè)參數(shù)為錯(cuò)誤信息。

創(chuàng)建你自己的客戶端與服務(wù)端

為了幫助你理解目前為止講的這些內(nèi)容,讓我們來(lái)創(chuàng)建兩個(gè)控制器,演示下 XML-RPC 的客戶端和服務(wù)端。你將用客戶端來(lái)發(fā)送一個(gè)請(qǐng)求到服務(wù)端并從服務(wù)端收到一個(gè)響應(yīng)。

客戶端

使用文本編輯器創(chuàng)建一個(gè)控制器 Xmlrpc_client.php ,在這個(gè)控制器中, 粘貼以下的代碼并保存到 applications/controllers/ 目錄:

<?php

class Xmlrpc_client extends CI_Controller {

    public function index()
    {
        $this->load->helper('url');
        $server_url = site_url('xmlrpc_server');

        $this->load->library('xmlrpc');

        $this->xmlrpc->server($server_url, 80);
        $this->xmlrpc->method('Greetings');

        $request = array('How is it going?');
        $this->xmlrpc->request($request);

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            echo '<pre>';
            print_r($this->xmlrpc->display_response());
            echo '</pre>';
        }
    }
}
?>

注解

上面的代碼中我們使用了一個(gè) URL 輔助函數(shù),更多關(guān)于輔助函數(shù)的信息, 你可以閱讀 這里 。

服務(wù)端

使用文本編輯器創(chuàng)建一個(gè)控制器 Xmlrpc_server.php ,在這個(gè)控制器中, 粘貼以下的代碼并保存到 applications/controllers/ 目錄:

<?php

class Xmlrpc_server extends CI_Controller {

    public function index()
    {
        $this->load->library('xmlrpc');
        $this->load->library('xmlrpcs');

        $config['functions']['Greetings'] = array('function' => 'Xmlrpc_server.process');

        $this->xmlrpcs->initialize($config);
        $this->xmlrpcs->serve();
    }

    public function process($request)
    {
        $parameters = $request->output_parameters();

        $response = array(
            array(
                'you_said'  => $parameters[0],
                'i_respond' => 'Not bad at all.'
            ),
            'struct'
        );

        return $this->xmlrpc->send_response($response);
    }
}

嘗試一下

現(xiàn)在使用類似于下面這樣的鏈接訪問(wèn)你的站點(diǎn):

example.com/index.php/xmlrpc_client/

你應(yīng)該能看到你發(fā)送到服務(wù)端的信息,以及服務(wù)器返回的響應(yīng)信息。

在客戶端,你發(fā)送了一條消息("How's is going?")到服務(wù)端, 隨著一個(gè)請(qǐng)求發(fā)送到 "Greetings" 方法。服務(wù)端收到這個(gè)請(qǐng)求并映射到 "process" 函數(shù),然后返回響應(yīng)信息。

在請(qǐng)求參數(shù)中使用關(guān)聯(lián)數(shù)組

如果你希望在你的方法參數(shù)中使用關(guān)聯(lián)數(shù)組,那么你需要使用 struct 數(shù)據(jù)類型:

$request = array(
    array(
        // Param 0
        array('name' => 'John'),
        'struct'
    ),
    array(
        // Param 1
        array(
            'size' => 'large',
            'shape'=>'round'
        ),
        'struct'
    )
);

$this->xmlrpc->request($request);

你可以在服務(wù)端處理請(qǐng)求信息時(shí)獲取該關(guān)聯(lián)數(shù)組。

$parameters = $request->output_parameters();
$name = $parameters[0]['name'];
$size = $parameters[1]['size'];
$shape = $parameters[1]['shape'];

數(shù)據(jù)類型

根據(jù) XML-RPC 規(guī)范 一共有七種不同的數(shù)據(jù)類型可以在 XML-RPC 中使用:

  • int or i4
  • boolean
  • string
  • double
  • dateTime.iso8601
  • base64
  • struct (contains array of values)
  • array (contains array of values)

類參考

classCI_Xmlrpc

initialize([$config = array()])

參數(shù):

  • $config (array) -- Configuration data

返回類型: void

初始化 XML-RPC 類,接受一個(gè)包含你設(shè)置的參數(shù)的關(guān)聯(lián)數(shù)組。

server($url[, $port = 80[, $proxy = FALSE[, $proxy_port = 8080]]])

參數(shù):

  • $url (string) -- XML-RPC server URL
  • $port (int) -- Server port
  • $proxy (string) -- Optional proxy
  • $proxy_port (int) -- Proxy listening port

返回類型: void

用于設(shè)置 XML-RPC 服務(wù)器端的 URL 和端口:

$this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);

支持基本的 HTTP 身份認(rèn)證,只需簡(jiǎn)單的將其添加到 URL中:

$this->xmlrpc->server('http://user:pass@localhost/', 80);

timeout($seconds = 5)

參數(shù):

  • $seconds (int) -- Timeout in seconds

返回類型: void

設(shè)置一個(gè)超時(shí)時(shí)間(單位為秒),超過(guò)該時(shí)間,請(qǐng)求將被取消:

$this->xmlrpc->timeout(6);

method($function)

參數(shù):

  • $function (string) -- Method name

返回類型: void

設(shè)置 XML-RPC 服務(wù)器接受的請(qǐng)求方法:

$this->xmlrpc->method('method');

其中 method 參數(shù)為請(qǐng)求方法名。

request($incoming)

參數(shù):

  • $incoming (array) -- Request data

返回類型: void

接受一個(gè)數(shù)組參數(shù),并創(chuàng)建一個(gè)發(fā)送到 XML-RPC 服務(wù)器的請(qǐng)求:

$request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
$this->xmlrpc->request($request);

send_request()

返回: TRUE on success, FALSE on failure
返回類型: bool

發(fā)送請(qǐng)求的方法,成功返回 TRUE,失敗返回 FALSE ,可以用在條件判斷里。

display_error()

返回: Error message string
返回類型: string

當(dāng)請(qǐng)求失敗后,返回錯(cuò)誤信息。

echo $this->xmlrpc->display_error();

display_response()

返回: Response
返回類型: mixed

遠(yuǎn)程服務(wù)器接收請(qǐng)求后返回的響應(yīng),返回的數(shù)據(jù)通常是一個(gè)關(guān)聯(lián)數(shù)組。

$this->xmlrpc->display_response();

send_error_message($number, $message)

參數(shù):

  • $number (int) -- Error number
  • $message (string) -- Error message

返回: XML_RPC_Response instance

返回類型: XML_RPC_Response

這個(gè)方法允許你從服務(wù)器發(fā)送一個(gè)錯(cuò)誤消息到客戶端。 第一個(gè)參數(shù)是錯(cuò)誤編號(hào),第二個(gè)參數(shù)是錯(cuò)誤信息。

return $this->xmlrpc->send_error_message(123, 'Requested data not available');
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)