XML-RPC 和 XML-RPC 服務(wù)器類
CodeIgniter 的 XML-RPC? 類允許你發(fā)送請(qǐng)求到另一個(gè)服務(wù)器, 或者建立一個(gè)你自己的XML-RPC服務(wù)器來(lái)接受請(qǐng)求.
什么是XML-RPC?
這是一個(gè)非常簡(jiǎn)單的兩臺(tái)計(jì)算機(jī)使用XML通過(guò)互聯(lián)網(wǎng)進(jìn)行通信的方法. 一臺(tái)計(jì)算機(jī) , 我們稱之為 客戶端 , 發(fā)送一個(gè)XML-RPC 請(qǐng)求 給另外一臺(tái)計(jì)算機(jī) , 我們稱之為 服務(wù)器. 當(dāng)服務(wù)器收到請(qǐng)求并加以處理,然后將 結(jié)果 返回給客戶端.
例如,使用 MetaWeblog 的 API(應(yīng)用程序接口) , 一個(gè)XML-RPC客戶端(通常是桌面發(fā)布工具)會(huì)發(fā)送一個(gè)請(qǐng)求到運(yùn)行在你網(wǎng)站的XML-RPC服務(wù)端. 這個(gè)請(qǐng)求有可能是要發(fā)布一篇新的網(wǎng)志,或者是要修改已存在的網(wǎng)志. 當(dāng)XML-RPC服務(wù)器接收到請(qǐng)求,將檢驗(yàn)請(qǐng)求并且決定調(diào)用何種類/方法來(lái)處理請(qǐng)求.一旦處理完畢,服務(wù)器將返回一個(gè)響應(yīng)信息.
如果要查看更詳細(xì)的規(guī)范,你可以瀏覽 XML-RPC 網(wǎng)站.
初始化類
像CodeIgniter的大多數(shù)類一樣, XML-RPC 和 XML-RPCS 類 在你的控制器中調(diào)用 $this->load->library 方法來(lái)進(jìn)行初始化:
使用以下代碼載入XML-RPC類庫(kù):
$this->load->library('xmlrpc');
一旦XML-RPC類被載入, XML-RPC 庫(kù)的對(duì)象就可以使用了: $this->xmlrpc
使用下面的方法載入 XML-RPC 服務(wù)器類:
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
一旦加入,可以通過(guò) $this->xmlrpcs 使用 xml-rpcs 庫(kù)對(duì)象: $this->xmlrpcs
注意:? 使用 XML-RPC 服務(wù)器,必須同時(shí)載入 XML-RPC 類和 XML-RPC 服務(wù)器類。
發(fā)送 XML-RPC 請(qǐng)求
發(fā)送一個(gè)請(qǐng)求到 XML-RPC 服務(wù)器,需指定如下信息:
- 服務(wù)器的 URL
- 你要調(diào)用的服務(wù)器上的方法。
- The 請(qǐng)求 數(shù)據(jù) (說(shuō)明見下面).
下面是一個(gè)簡(jiǎn)單的例子,它發(fā)送一個(gè)簡(jiǎn)單的 Weblogs.com ping 到Ping-o-Matic
$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();
}
說(shuō)明
以上代碼初始化XML-RPC類,設(shè)置了服務(wù)器的URL和要調(diào)用的方法(weblogUpdates.ping). 請(qǐng)求(在此例中為你網(wǎng)站的標(biāo)題和URL)被放在一個(gè)數(shù)組中使用 request() 函數(shù)傳輸、編譯。最后,整個(gè)請(qǐng)求發(fā)出,如果send_request()方法返回 false,我們將顯示XML-RPC 服務(wù)器發(fā)回的錯(cuò)誤信息。
請(qǐng)求剖析
一個(gè) 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)求,服務(wù)器會(huì)尋找請(qǐng)求參數(shù)。
請(qǐng)求參數(shù)必須放在數(shù)組中傳輸,每個(gè)參數(shù)可以是七種數(shù)據(jù)類型中的任一種(字符串,數(shù)字,日期,等等)。如果你的參數(shù)是字符串外的其它類型,則必須在請(qǐng)求數(shù)組中包含數(shù)據(jù)類型。
下面是一個(gè)包含三個(gè)參數(shù)的簡(jiǎn)單數(shù)組示例:
$request = array('John', 'Doe', 'www.some-site.com');
$this->xmlrpc->request($request);
如果你使用除字符串以外的其它類型,或有幾種不同的數(shù)據(jù)類型,你需要將每個(gè)參數(shù)單獨(dú)放到一個(gè)數(shù)組中,并在數(shù)組第二個(gè)位置給出數(shù)據(jù)類型。
$request = array (
???????????????????array('John', 'string'),
???????????????????array('Doe', 'string'),
???????????????????array(FALSE, 'boolean'),
???????????????????array(12345, 'int')
?????????????????);
$this->xmlrpc->request($request);
數(shù)據(jù)類型 中包括完成的數(shù)據(jù)類型列表。
創(chuàng)建 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ù)器,包括在接受請(qǐng)求的控制器中初始化 XML-RPC 服務(wù)器類,然后設(shè)置一個(gè)指向映射數(shù)組以便收到的請(qǐng)求可以被發(fā)送到恰當(dāng)?shù)念惻c方法來(lái)處理。
下面用一個(gè)例子來(lái)說(shuō)明:
$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è)包含兩個(gè)服務(wù)器允許的特定請(qǐng)求方法的數(shù)組。這些被允許的方法在數(shù)組的左邊,當(dāng)收到其中任何一個(gè)方法時(shí),它會(huì)被立刻映射到數(shù)組右邊所列出的類與方法。
'Object'是一個(gè)特殊的鍵,它是你傳遞的類的實(shí)例,這個(gè)鍵是必要的,尤其是當(dāng)你映射到的方法不是 Codeigniter 超類的一部分。
換句話說(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ù)名是任意的。你可以決定這些函數(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í),服務(wù)器會(huì)傳遞一個(gè)包含客戶端發(fā)送數(shù)據(jù)的對(duì)象到指定的方法。
在上面的例子中,如果請(qǐng)求的是 new_post 方法,服務(wù)器請(qǐng)求的類與方法會(huì)像這樣:
class My_blog extends CI_Controller {
????function new_post($request)
????{
????}
}
$request 變量是一個(gè)由服務(wù)端匯集的對(duì)象,包含由 XML-RPC 客戶端發(fā)送來(lái)的數(shù)據(jù)。使用該對(duì)象可以讓你訪問(wèn)到 request parameters 以便處理請(qǐng)求。請(qǐng)求處理完成后,發(fā)送一個(gè) Response 返回給客戶端。
下面是一個(gè)較為實(shí)際的例子,使用 Blogger 的 API。Blogger API 中的一個(gè)方法是 getUserInfo(),使用該方法 XML-RPC 客戶端可以發(fā)送用戶名和密碼到服務(wù)器,在服務(wù)器返回的數(shù)據(jù)會(huì)包含該特定用戶的信息(昵稱,用戶 ID,Email 地址等等)。下面是處理函數(shù)可能的樣子:
class My_blog extends CI_Controller {
????function getUserInfo($request)
????{
????????$username = 'smitty';
????????$password = 'secretsmittypass';
????????$this->load->library('xmlrpc');
????
????????$parameters?=?$request->output_parameters();
????
????????if?($parameters['1'] != $username AND $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ù)會(huì)檢索一個(gè)由相應(yīng)客戶端發(fā)送的索引過(guò)的請(qǐng)求參數(shù)數(shù)組。上面的例子中輸出參數(shù)將會(huì)是用戶名和密碼。
如果客戶端發(fā)送的用戶名和密碼無(wú)效的話,錯(cuò)誤信息會(huì)通過(guò) send_error_message() 函數(shù)返回。
如果操作成功,客戶端會(huì)收到包含用戶信息的反饋數(shù)組。
格式化反饋信息
就像 Requests, Responses 必須被格式化為數(shù)組。然而不同于請(qǐng)求信息,反饋信息是只包含一個(gè)項(xiàng)的數(shù)組。該項(xiàng)可以是一個(gè)包含很多其他數(shù)組的的數(shù)組,但是只有一個(gè)主數(shù)組索引,下面是一個(gè)反饋信息大概的樣子:
$response = array('Response data', 'array');
但是反饋信息通常包含多個(gè)分塊信息。要做到這樣,我們必須把各分塊信息放到他們自己的數(shù)組中,這樣主數(shù)組就始終只有一個(gè)數(shù)據(jù)項(xiàng)。這里是一個(gè)例子來(lái)展示如何達(dá)成這樣的效果:
$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,這是反饋信息最常見的數(shù)據(jù)類型。
如同請(qǐng)求信息一樣,反饋信息可以是七種數(shù)據(jù)類型中的一種,參見 數(shù)據(jù)類型 一節(jié)。
發(fā)送出錯(cuò)反饋
如果你需要發(fā)送給客戶端一個(gè)出錯(cuò)反饋,你會(huì)使用到下面的代碼:
return $this->xmlrpc->send_error_message('123', 'Requested data not available');
第一個(gè)參數(shù)是出錯(cuò)編號(hào),第二個(gè)參數(shù)是出錯(cuò)信息。
創(chuàng)建你自己的客戶端與服務(wù)端
為了幫助理解這些,讓我們創(chuàng)建兩個(gè)控制器來(lái)演示 XML-RPC 的客戶端和服務(wù)端。你將用客戶端來(lái)發(fā)送一個(gè)請(qǐng)求到服務(wù)端并從服務(wù)端收到一個(gè)反饋。
客戶端
使用編輯器創(chuàng)建一個(gè)控制器,起名為 xmlrpc_client.php。在這個(gè)控制器中,粘貼以下的代碼并保存到 applications/controllers/ 目錄:
注意:在上面的代碼中我們使用了 "url" 輔助函數(shù),你可以在輔助函數(shù)頁(yè)面找到更多信息。
服務(wù)端
使用編輯器創(chuàng)建一個(gè)控制器,起名為 xmlrpc_server.php。在這個(gè)控制器中,粘貼一下代碼并保存到 applications/controllers/ 目錄:
試試吧!
現(xiàn)在像下面的鏈接這樣訪問(wèn)你的站點(diǎn):
example.com/index.php/xmlrpc_client/
現(xiàn)在你應(yīng)該能看到你發(fā)送到服務(wù)端的信息,并且被返回給了你。
在客戶端,你發(fā)送了一條消息 ("How's is going?") 到服務(wù)端,隨著一個(gè)請(qǐng)求發(fā)送到 "Greetings" 方法。服務(wù)端收到這個(gè)請(qǐng)求并映射到 "process" 函數(shù),然后把反饋信息返回。
在請(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'];
$size = $parameters['1']['shape'];
XML-RPC Function Reference
$this->xmlrpc->server()
Sets the URL and port number of the server to which a request is to be sent:
$this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);
$this->xmlrpc->timeout()
Set a time out period (in seconds) after which the request will be canceled:
$this->xmlrpc->timeout(6);
$this->xmlrpc->method()
Sets the method that will be requested from the XML-RPC server:
$this->xmlrpc->method('method');
Where method is the name of the method.
$this->xmlrpc->request()
Takes an array of data and builds request to be sent to XML-RPC server:
$request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
$this->xmlrpc->request($request);
$this->xmlrpc->send_request()
The request sending function. Returns boolean TRUE or FALSE based on success for failure, enabling it to be used conditionally.
$this->xmlrpc->set_debug(TRUE);
Enables debugging, which will display a variety of information and error data helpful during development.
$this->xmlrpc->display_error()
Returns an error message as a string if your request failed for some reason.
echo $this->xmlrpc->display_error();
$this->xmlrpc->display_response()
Returns the response from the remote server once request is received. The response will typically be an associative array.
$this->xmlrpc->display_response();
$this->xmlrpc->send_error_message()
This function lets you send an error message from your server to the client. First parameter is the error number while the second parameter is the error message.
return $this->xmlrpc->send_error_message('123', 'Requested data not available');
$this->xmlrpc->send_response()
Lets you send the response from your server to the client. An array of valid data values must be sent with this method.
$response = array(
?????????????????array(
????????????????????????'flerror' => array(FALSE, 'boolean'),
????????????????????????'message' => "Thanks for the ping!"
?????????????????????)
?????????????????'struct');
return $this->xmlrpc->send_response($response);
數(shù)據(jù)類型
According to the XML-RPC spec there are seven types of values that you can send via XML-RPC:
- int or i4
- boolean
- string
- double
- dateTime.iso8601
- base64
- struct (contains array of values)
- array (contains array of values)
?