blob: 91d832ff60c18f5326ae1ba4d321b43056aa2596 [file] [log] [blame]
Derek Jones8ede1a22011-10-05 13:34:52 -05001##################################
2XML-RPC and XML-RPC Server Classes
3##################################
4
5CodeIgniter's XML-RPC classes permit you to send requests to another
6server, or set up your own XML-RPC server to receive requests.
7
Andrey Andreevd8afb982013-09-23 16:01:46 +03008.. contents::
Andrey Andreevcc042092014-01-03 17:08:27 +02009 :local:
Andrey Andreevd8afb982013-09-23 16:01:46 +030010
11.. raw:: html
12
Andrey Andreevcc042092014-01-03 17:08:27 +020013 <div class="custom-index container"></div>
Andrey Andreevd8afb982013-09-23 16:01:46 +030014
Derek Jones8ede1a22011-10-05 13:34:52 -050015****************
16What is XML-RPC?
17****************
18
19Quite simply it is a way for two computers to communicate over the
20internet using XML. One computer, which we will call the client, sends
21an XML-RPC **request** to another computer, which we will call the
22server. Once the server receives and processes the request it will send
23back a **response** to the client.
24
25For example, using the MetaWeblog API, an XML-RPC Client (usually a
26desktop publishing tool) will send a request to an XML-RPC Server
27running on your site. This request might be a new weblog entry being
28sent for publication, or it could be a request for an existing entry for
29editing. When the XML-RPC Server receives this request it will examine
30it to determine which class/method should be called to process the
31request. Once processed, the server will then send back a response
32message.
33
Andrey Andreevd8afb982013-09-23 16:01:46 +030034For detailed specifications, you can visit the `XML-RPC <http://www.xmlrpc.com/>`_ site.
35
36***********************
37Using the XML-RPC Class
38***********************
Derek Jones8ede1a22011-10-05 13:34:52 -050039
40Initializing the Class
41======================
42
43Like most other classes in CodeIgniter, the XML-RPC and XML-RPCS classes
44are initialized in your controller using the $this->load->library
45function:
46
47To load the XML-RPC class you will use::
48
49 $this->load->library('xmlrpc');
50
51Once loaded, the xml-rpc library object will be available using:
52$this->xmlrpc
53
54To load the XML-RPC Server class you will use::
55
Derek Jones92763a52011-10-05 15:28:52 -050056 $this->load->library('xmlrpc');
57 $this->load->library('xmlrpcs');
Derek Jones8ede1a22011-10-05 13:34:52 -050058
59Once loaded, the xml-rpcs library object will be available using:
60$this->xmlrpcs
61
62.. note:: When using the XML-RPC Server class you must load BOTH the
63 XML-RPC class and the XML-RPC Server class.
64
65Sending XML-RPC Requests
66========================
67
68To send a request to an XML-RPC server you must specify the following
69information:
70
71- The URL of the server
72- The method on the server you wish to call
73- The *request* data (explained below).
74
75Here is a basic example that sends a simple Weblogs.com ping to the
76`Ping-o-Matic <http://pingomatic.com/>`_
77
78::
79
Derek Jones92763a52011-10-05 15:28:52 -050080 $this->load->library('xmlrpc');
81
82 $this->xmlrpc->server('http://rpc.pingomatic.com/', 80);
83 $this->xmlrpc->method('weblogUpdates.ping');
84
85 $request = array('My Photoblog', 'http://www.my-site.com/photoblog/');
86 $this->xmlrpc->request($request);
87
88 if ( ! $this->xmlrpc->send_request())
89 {
90 echo $this->xmlrpc->display_error();
91 }
Derek Jones8ede1a22011-10-05 13:34:52 -050092
93Explanation
94-----------
95
96The above code initializes the XML-RPC class, sets the server URL and
97method to be called (weblogUpdates.ping). The request (in this case, the
98title and URL of your site) is placed into an array for transportation,
99and compiled using the request() function. Lastly, the full request is
100sent. If the send_request() method returns false we will display the
101error message sent back from the XML-RPC Server.
102
103Anatomy of a Request
104====================
105
106An XML-RPC request is simply the data you are sending to the XML-RPC
107server. Each piece of data in a request is referred to as a request
108parameter. The above example has two parameters: The URL and title of
109your site. When the XML-RPC server receives your request, it will look
110for parameters it requires.
111
112Request parameters must be placed into an array for transportation, and
113each parameter can be one of seven data types (strings, numbers, dates,
114etc.). If your parameters are something other than strings you will have
115to include the data type in the request array.
116
117Here is an example of a simple array with three parameters::
118
Derek Jones92763a52011-10-05 15:28:52 -0500119 $request = array('John', 'Doe', 'www.some-site.com');
120 $this->xmlrpc->request($request);
Derek Jones8ede1a22011-10-05 13:34:52 -0500121
122If you use data types other than strings, or if you have several
123different data types, you will place each parameter into its own array,
124with the data type in the second position::
125
Derek Jones92763a52011-10-05 15:28:52 -0500126 $request = array (
127 array('John', 'string'),
128 array('Doe', 'string'),
129 array(FALSE, 'boolean'),
130 array(12345, 'int')
131 );
132 $this->xmlrpc->request($request);
Derek Jones8ede1a22011-10-05 13:34:52 -0500133
134The `Data Types <#datatypes>`_ section below has a full list of data
135types.
Andrey Andreevd8afb982013-09-23 16:01:46 +0300136
Derek Jones8ede1a22011-10-05 13:34:52 -0500137Creating an XML-RPC Server
138==========================
139
140An XML-RPC Server acts as a traffic cop of sorts, waiting for incoming
141requests and redirecting them to the appropriate functions for
142processing.
143
144To create your own XML-RPC server involves initializing the XML-RPC
145Server class in your controller where you expect the incoming request to
146appear, then setting up an array with mapping instructions so that
147incoming requests can be sent to the appropriate class and method for
148processing.
149
150Here is an example to illustrate::
151
Derek Jones92763a52011-10-05 15:28:52 -0500152 $this->load->library('xmlrpc');
153 $this->load->library('xmlrpcs');
154
155 $config['functions']['new_post'] = array('function' => 'My_blog.new_entry'),
156 $config['functions']['update_post'] = array('function' => 'My_blog.update_entry');
157 $config['object'] = $this;
158
159 $this->xmlrpcs->initialize($config);
160 $this->xmlrpcs->serve();
Derek Jones8ede1a22011-10-05 13:34:52 -0500161
162The above example contains an array specifying two method requests that
163the Server allows. The allowed methods are on the left side of the
164array. When either of those are received, they will be mapped to the
165class and method on the right.
166
167The 'object' key is a special key that you pass an instantiated class
168object with, which is necessary when the method you are mapping to is
169not part of the CodeIgniter super object.
170
171In other words, if an XML-RPC Client sends a request for the new_post
172method, your server will load the My_blog class and call the new_entry
173function. If the request is for the update_post method, your server
174will load the My_blog class and call the update_entry function.
175
176The function names in the above example are arbitrary. You'll decide
177what they should be called on your server, or if you are using
178standardized APIs, like the Blogger or MetaWeblog API, you'll use their
179function names.
180
181There are two additional configuration keys you may make use of when
182initializing the server class: debug can be set to TRUE in order to
183enable debugging, and xss_clean may be set to FALSE to prevent sending
184data through the Security library's xss_clean function.
185
186Processing Server Requests
187==========================
188
189When the XML-RPC Server receives a request and loads the class/method
190for processing, it will pass an object to that method containing the
191data sent by the client.
192
193Using the above example, if the new_post method is requested, the
194server will expect a class to exist with this prototype::
195
Derek Jones92763a52011-10-05 15:28:52 -0500196 class My_blog extends CI_Controller {
197
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300198 public function new_post($request)
199 {
Derek Jones92763a52011-10-05 15:28:52 -0500200
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300201 }
Derek Jones92763a52011-10-05 15:28:52 -0500202 }
Derek Jones8ede1a22011-10-05 13:34:52 -0500203
204The $request variable is an object compiled by the Server, which
205contains the data sent by the XML-RPC Client. Using this object you will
206have access to the *request parameters* enabling you to process the
207request. When you are done you will send a Response back to the Client.
208
209Below is a real-world example, using the Blogger API. One of the methods
210in the Blogger API is getUserInfo(). Using this method, an XML-RPC
211Client can send the Server a username and password, in return the Server
212sends back information about that particular user (nickname, user ID,
213email address, etc.). Here is how the processing function might look::
214
Derek Jones92763a52011-10-05 15:28:52 -0500215 class My_blog extends CI_Controller {
216
217 function getUserInfo($request)
218 {
219 $username = 'smitty';
220 $password = 'secretsmittypass';
221
222 $this->load->library('xmlrpc');
223
224 $parameters = $request->output_parameters();
225
226 if ($parameters['1'] != $username AND $parameters['2'] != $password)
227 {
228 return $this->xmlrpc->send_error_message('100', 'Invalid Access');
229 }
230
231 $response = array(array('nickname' => array('Smitty','string'),
232 'userid' => array('99','string'),
233 'url' => array('http://yoursite.com','string'),
234 'email' => array('jsmith@yoursite.com','string'),
235 'lastname' => array('Smith','string'),
236 'firstname' => array('John','string')
237 ),
238 'struct');
239
240 return $this->xmlrpc->send_response($response);
241 }
242 }
Derek Jones8ede1a22011-10-05 13:34:52 -0500243
244Notes:
245------
246
247The output_parameters() function retrieves an indexed array
248corresponding to the request parameters sent by the client. In the above
249example, the output parameters will be the username and password.
250
251If the username and password sent by the client were not valid, and
252error message is returned using send_error_message().
253
254If the operation was successful, the client will be sent back a response
255array containing the user's info.
256
257Formatting a Response
258=====================
259
260Similar to *Requests*, *Responses* must be formatted as an array.
261However, unlike requests, a response is an array **that contains a
262single item**. This item can be an array with several additional arrays,
263but there can be only one primary array index. In other words, the basic
264prototype is this::
265
266 $response = array('Response data', 'array');
267
268Responses, however, usually contain multiple pieces of information. In
269order to accomplish this we must put the response into its own array so
270that the primary array continues to contain a single piece of data.
271Here's an example showing how this might be accomplished::
272
Derek Jones92763a52011-10-05 15:28:52 -0500273 $response = array (
274 array(
275 'first_name' => array('John', 'string'),
276 'last_name' => array('Doe', 'string'),
277 'member_id' => array(123435, 'int'),
278 'todo_list' => array(array('clean house', 'call mom', 'water plants'), 'array'),
279 ),
280 'struct'
281 );
Derek Jones8ede1a22011-10-05 13:34:52 -0500282
283Notice that the above array is formatted as a struct. This is the most
284common data type for responses.
285
286As with Requests, a response can be one of the seven data types listed
287in the `Data Types <#datatypes>`_ section.
288
289Sending an Error Response
290=========================
291
292If you need to send the client an error response you will use the
293following::
294
295 return $this->xmlrpc->send_error_message('123', 'Requested data not available');
296
297The first parameter is the error number while the second parameter is
298the error message.
299
300Creating Your Own Client and Server
301===================================
302
303To help you understand everything we've covered thus far, let's create a
304couple controllers that act as XML-RPC Client and Server. You'll use the
305Client to send a request to the Server and receive a response.
306
307The Client
308----------
309
310Using a text editor, create a controller called xmlrpc_client.php. In
Alan Jenkinsa51f8ec2012-11-19 10:29:52 +0000311it, place this code and save it to your application/controllers/
Derek Jones92763a52011-10-05 15:28:52 -0500312folder::
Derek Jones8ede1a22011-10-05 13:34:52 -0500313
Derek Jones92763a52011-10-05 15:28:52 -0500314 <?php
Derek Jones8ede1a22011-10-05 13:34:52 -0500315
Derek Jones92763a52011-10-05 15:28:52 -0500316 class Xmlrpc_client extends CI_Controller {
Derek Jones8ede1a22011-10-05 13:34:52 -0500317
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300318 public function index()
Derek Jones92763a52011-10-05 15:28:52 -0500319 {
320 $this->load->helper('url');
321 $server_url = site_url('xmlrpc_server');
322
323 $this->load->library('xmlrpc');
324
325 $this->xmlrpc->server($server_url, 80);
326 $this->xmlrpc->method('Greetings');
327
328 $request = array('How is it going?');
329 $this->xmlrpc->request($request);
330
331 if ( ! $this->xmlrpc->send_request())
332 {
333 echo $this->xmlrpc->display_error();
334 }
335 else
336 {
337 echo '<pre>';
338 print_r($this->xmlrpc->display_response());
339 echo '</pre>';
340 }
341 }
342 }
343 ?>
344
345.. note:: In the above code we are using a "url helper". You can find more
346 information in the :doc:`Helpers Functions <../general/helpers>` page.
Derek Jones8ede1a22011-10-05 13:34:52 -0500347
348The Server
349----------
350
351Using a text editor, create a controller called xmlrpc_server.php. In
Alan Jenkinsa51f8ec2012-11-19 10:29:52 +0000352it, place this code and save it to your application/controllers/
Derek Jones92763a52011-10-05 15:28:52 -0500353folder::
Derek Jones8ede1a22011-10-05 13:34:52 -0500354
Derek Jones92763a52011-10-05 15:28:52 -0500355 <?php
356
357 class Xmlrpc_server extends CI_Controller {
358
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300359 public function index()
Derek Jones92763a52011-10-05 15:28:52 -0500360 {
361 $this->load->library('xmlrpc');
362 $this->load->library('xmlrpcs');
363
364 $config['functions']['Greetings'] = array('function' => 'Xmlrpc_server.process');
365
366 $this->xmlrpcs->initialize($config);
367 $this->xmlrpcs->serve();
368 }
369
370
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300371 public function process($request)
Derek Jones92763a52011-10-05 15:28:52 -0500372 {
373 $parameters = $request->output_parameters();
374
375 $response = array(
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300376 array(
377 'you_said' => $parameters[0],
378 'i_respond' => 'Not bad at all.'
379 ),
380 'struct'
381 );
Derek Jones92763a52011-10-05 15:28:52 -0500382
383 return $this->xmlrpc->send_response($response);
384 }
385 }
386 ?>
387
388
Derek Jones8ede1a22011-10-05 13:34:52 -0500389Try it!
390-------
391
392Now visit the your site using a URL similar to this::
393
394 example.com/index.php/xmlrpc_client/
395
396You should now see the message you sent to the server, and its response
397back to you.
398
399The client you created sends a message ("How's is going?") to the
400server, along with a request for the "Greetings" method. The Server
401receives the request and maps it to the "process" function, where a
402response is sent back.
403
404Using Associative Arrays In a Request Parameter
405===============================================
406
407If you wish to use an associative array in your method parameters you
408will need to use a struct datatype::
409
Derek Jones92763a52011-10-05 15:28:52 -0500410 $request = array(
411 array(
412 // Param 0
413 array(
414 'name'=>'John'
415 ),
416 'struct'
417 ),
418 array(
419 // Param 1
420 array(
421 'size'=>'large',
422 'shape'=>'round'
423 ),
424 'struct'
425 )
426 );
427 $this->xmlrpc->request($request);
Derek Jones8ede1a22011-10-05 13:34:52 -0500428
429You can retrieve the associative array when processing the request in
430the Server.
431
432::
433
Derek Jones92763a52011-10-05 15:28:52 -0500434 $parameters = $request->output_parameters();
Andrey Andreevd8e1ac72012-03-26 22:22:37 +0300435 $name = $parameters[0]['name'];
436 $size = $parameters[1]['size'];
Michael Zimmerd6b7cde2013-06-20 11:54:07 +0200437 $shape = $parameters[1]['shape'];
Derek Jones8ede1a22011-10-05 13:34:52 -0500438
Derek Jones8ede1a22011-10-05 13:34:52 -0500439Data Types
440==========
441
442According to the `XML-RPC spec <http://www.xmlrpc.com/spec>`_ there are
443seven types of values that you can send via XML-RPC:
444
445- *int* or *i4*
446- *boolean*
447- *string*
448- *double*
449- *dateTime.iso8601*
450- *base64*
451- *struct* (contains array of values)
452- *array* (contains array of values)
453
Andrey Andreevd8afb982013-09-23 16:01:46 +0300454***************
455Class Reference
456***************
457
458.. class:: CI_Xmlrpc
459
460 .. method:: initialize([$config = array()])
461
462 :param array $config: configuration data
463 :returns: void
464
465 Initializes the XML-RPC library. Accepts an associative array containing your settings.
466
467 .. method:: server($url[, $port = 80[, $proxy = FALSE[, $proxy_port = 8080]]])
468
469 :param string $url: XML-RPC server URL
470 :param int $port: server port
471 :param string $proxy: optional proxy
472 :param int $proxy_port: proxy listening port
473 :returns: void
474
475 Sets the URL and port number of the server to which a request is to be sent::
476
477 $this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);
478
Andrey Andreevd1929532014-01-07 12:16:16 +0200479 Basic HTTP authentication is also supported, simply add it to the server URL::
480
481 $this->xmlrpc->server('http://user:pass@localhost/', 80);
482
Andrey Andreevd8afb982013-09-23 16:01:46 +0300483 .. method:: timeout($seconds = 5)
484
485 :param int $seconds: timeout in seconds
486 :returns: void
487
488 Set a time out period (in seconds) after which the request will be canceled::
489
490 $this->xmlrpc->timeout(6);
491
492 .. method:: method($function)
493
494 :param string $function: method name
495 :returns: void
496
497 Sets the method that will be requested from the XML-RPC server::
498
499 $this->xmlrpc->method('method');
500
501 Where method is the name of the method.
502
503 .. method:: request($incoming)
504
505 :param array $incoming: request data
506 :returns: void
507
508 Takes an array of data and builds request to be sent to XML-RPC server::
509
510 $request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
511 $this->xmlrpc->request($request);
512
513 .. method:: send_request()
514
515 :returns: bool
516
517 The request sending method. Returns boolean TRUE or FALSE based on success for failure, enabling it to be used conditionally.
518
519 .. method set_debug($flag = TRUE)
520
521 :param bool $flag: debug status flag
522 :returns: void
523
524 Enables or disables debugging, which will display a variety of information and error data helpful during development.
525
526 .. method:: display_error()
527
528 :returns: string
529
530 Returns an error message as a string if your request failed for some reason.
531 ::
532
533 echo $this->xmlrpc->display_error();
534
535 .. method:: display_response()
536
537 :returns: mixed
538
539 Returns the response from the remote server once request is received. The response will typically be an associative array.
540 ::
541
542 $this->xmlrpc->display_response();
543
544 .. method:: send_error_message($number, $message)
545
546 :param int $number: error number
547 :param string $message: error message
548 :returns: object
549
550 This method lets you send an error message from your server to the client.
551 First parameter is the error number while the second parameter is the error message.
552 ::
553
554 return $this->xmlrpc->send_error_message(123, 'Requested data not available');
555
556 .. method send_response($response)
557
558 :param array $response: response data
559 :returns: object
560
561 Lets you send the response from your server to the client. An array of valid data values must be sent with this method.
562 ::
563
564 $response = array(
565 array(
566 'flerror' => array(FALSE, 'boolean'),
567 'message' => "Thanks for the ping!"
568 ),
569 'struct'
570 );
571
572 return $this->xmlrpc->send_response($response);