This repository has been archived on 2024-11-28. You can view files and clone it, but cannot push or open issues or pull requests.
Incam_SGD/thirdparty/xmlrpc-2.2/doc/ch07s05.html

115 lines
20 KiB
HTML

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;xmlrpc_server</title><link rel="stylesheet" href="html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><link rel="start" href="index.html" title="XML-RPC for PHP"><link rel="up" href="ch07.html" title="Chapter&nbsp;7.&nbsp;Class documentation"><link rel="prev" href="ch07s04.html" title="4.&nbsp;xmlrpcresp"><link rel="next" href="ch08.html" title="Chapter&nbsp;8.&nbsp;Global variables"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.&nbsp;xmlrpc_server</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch07s04.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;7.&nbsp;Class documentation</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ch08.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="xmlrpc-server"></a>5.&nbsp;xmlrpc_server</h2></div></div></div><p>The implementation of this class has been kept as simple to use as possible. The constructor for the server basically does all the work. Here's a minimal example:</p><pre class="programlisting">
function foo ($xmlrpcmsg) {
...
return new xmlrpcresp($some_xmlrpc_val);
}
class bar {
function foobar($xmlrpcmsg) {
...
return new xmlrpcresp($some_xmlrpc_val);
}
}
$s = new xmlrpc_server(
array(
"examples.myFunc1" =&gt; array("function" =&gt; "foo"),
"examples.myFunc2" =&gt; array("function" =&gt; "bar::foobar"),
));
</pre><p>This performs everything you need to do with a server. The single constructor argument is an associative array from xmlrpc method names to php function names. The incoming request is parsed and dispatched to the relevant php function, which is responsible for returning a <code class="classname">xmlrpcresp</code> object, that will be serialized back to the caller.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2386"></a>5.1.&nbsp;Method handler functions</h3></div></div></div><p>Both php functions and class methods can be registered as xmlrpc method handlers.</p><p>The synopsis of a method handler function is:</p><pre class="synopsis">xmlrpcresp $resp = function (xmlrpcmsg $msg)</pre><p>No text should be echoed 'to screen' by the handler function, or it will break the xml response sent back to the client. This applies also to error and warning messages that PHP prints to screen unless the appropriate parameters have been set in the php.in file. Another way to prevent echoing of errors inside the response and facilitate debugging is to use the server SetDebug method with debug level 3 (see below).</p><p>Note that if you implement a method with a name prefixed by <code class="code">system.</code> the handler function will be invoked by the server with two parameters, the first being the server itself and the second being the <code class="classname">xmlrpcmsg</code> object.</p><p>The same php function can be registered as handler of multiple xmlrpc methods.</p><p>Here is a more detailed example of what the handler function <code class="function">foo</code> may do:</p><pre class="programlisting">
function foo ($xmlrpcmsg) {
global $xmlrpcerruser; // import user errcode base value
$meth = $xmlrpcmsg-&gt;method(); // retrieve method name
$par = $xmlrpcmsg-&gt;getParam(0); // retrieve value of first parameter - assumes at least one param received
$val = $par-&gt;scalarval(); // decode value of first parameter - assumes it is a scalar value
...
if ($err) {
// this is an error condition
return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
"There's a problem, Captain");
} else {
// this is a successful value being returned
return new xmlrpcresp(new xmlrpcval("All's fine!", "string"));
}
}
</pre><p>See <code class="filename">server.php</code> in this distribution for more examples of how to do this.</p><p>Since release 2.0RC3 there is a new, even simpler way of registering php functions with the server. See section 5.7 below</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2422"></a>5.2.&nbsp;The dispatch map</h3></div></div></div><p>The first argument to the <code class="function">xmlrpc_server</code> constructor is an array, called the <span class="emphasis"><em>dispatch map</em></span>. In this array is the information the server needs to service the XML-RPC methods you define.</p><p>The dispatch map takes the form of an associative array of associative arrays: the outer array has one entry for each method, the key being the method name. The corresponding value is another associative array, which can have the following members:</p><div class="itemizedlist"><ul type="disc"><li><p><code class="function"><code class="literal">function</code></code> - this entry is mandatory. It must be either a name of a function in the global scope which services the XML-RPC method, or an array containing an instance of an object and a static method name (for static class methods the 'class::method' syntax is also supported).</p></li><li><p><code class="function"><code class="literal">signature</code></code> - this entry is an array containing the possible signatures (see <a href="ch07s05.html#signatures">Signatures</a>) for the method. If this entry is present then the server will check that the correct number and type of parameters have been sent for this method before dispatching it.</p></li><li><p><code class="function"><code class="literal">docstring</code></code> - this entry is a string containing documentation for the method. The documentation may contain HTML markup.</p></li><li><p><code class="literal">signature_docs</code> - this entry can be used to provide documentation for the single parameters. It must match in structure the 'signature' member. By default, only the <code class="classname">documenting_xmlrpc_server</code> class in the extras package will take advantage of this, since the "system.methodHelp" protocol does not support documenting method parameters individually.</p></li></ul></div><p>Look at the <code class="filename">server.php</code> example in the distribution to see what a dispatch map looks like.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="signatures"></a>5.3.&nbsp;Method signatures</h3></div></div></div><p>A signature is a description of a method's return type and its parameter types. A method may have more than one signature.</p><p>Within a server's dispatch map, each method has an array of possible signatures. Each signature is an array of types. The first entry is the return type. For instance, the method </p><pre class="programlisting">string examples.getStateName(int)
</pre><p> has the signature </p><pre class="programlisting">array($xmlrpcString, $xmlrpcInt)
</pre><p> and, assuming that it is the only possible signature for the method, it might be used like this in server creation: </p><pre class="programlisting">
$findstate_sig = array(array($xmlrpcString, $xmlrpcInt));
$findstate_doc = 'When passed an integer between 1 and 51 returns the
name of a US state, where the integer is the index of that state name
in an alphabetic order.';
$s = new xmlrpc_server( array(
"examples.getStateName" =&gt; array(
"function" =&gt; "findstate",
"signature" =&gt; $findstate_sig,
"docstring" =&gt; $findstate_doc
)));
</pre><p>Note that method signatures do not allow to check nested parameters, e.g. the number, names and types of the members of a struct param cannot be validated.</p><p>If a method that you want to expose has a definite number of parameters, but each of those parameters could reasonably be of multiple types, the array of acceptable signatures will easily grow into a combinatorial explosion. To avoid such a situation, the lib defines the global var <code class="varname">$xmlrpcValue</code>, which can be used in method signatures as a placeholder for 'any xmlrpc type':</p><pre class="programlisting">
$echoback_sig = array(array($xmlrpcValue, $xmlrpcValue));
$findstate_doc = 'Echoes back to the client the received value, regardless of its type';
$s = new xmlrpc_server( array(
"echoBack" =&gt; array(
"function" =&gt; "echoback",
"signature" =&gt; $echoback_sig, // this sig guarantees that the method handler will be called with one and only one parameter
"docstring" =&gt; $echoback_doc
)));
</pre><p>Methods <code class="methodname">system.listMethods</code>, <code class="methodname">system.methodHelp</code>, <code class="methodname">system.methodSignature</code> and <code class="methodname">system.multicall</code> are already defined by the server, and should not be reimplemented (see Reserved Methods below).</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2508"></a>5.4.&nbsp;Delaying the server response</h3></div></div></div><p>You may want to construct the server, but for some reason not fulfill the request immediately (security verification, for instance). If you omit to pass to the constructor the dispatch map or pass it a second argument of <code class="literal">0</code> this will have the desired effect. You can then use the <code class="function">service()</code> method of the server class to service the request. For example:</p><pre class="programlisting">
$s = new xmlrpc_server($myDispMap, 0); // second parameter = 0 prevents automatic servicing of request
// ... some code that does other stuff here
$s-&gt;service();
</pre><p>Note that the <code class="methodname">service</code> method will print the complete result payload to screen and send appropriate HTTP headers back to the client, but also return the response object. This permits further manipulation of the response.</p><p>To prevent the server from sending HTTP headers back to the client, you can pass a second parameter with a value of <code class="literal">TRUE</code> to the <code class="methodname">service</code> method. In this case, the response payload will be returned instead of the response object.</p><p>Xmlrpc requests retrieved by other means than HTTP POST bodies can also be processed. For example:</p><pre class="programlisting">
$s = new xmlrpc_server(); // not passing a dispatch map prevents automatic servicing of request
// ... some code that does other stuff here, including setting dispatch map into server object
$resp = $s-&gt;service($xmlrpc_request_body, true); // parse a variable instead of POST body, retrieve response payload
// ... some code that does other stuff with xml response $resp here
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2538"></a>5.5.&nbsp;Modifying the server behaviour</h3></div></div></div><p>A couple of methods / class variables are available to modify the behaviour of the server. The only way to take advantage of their existence is by usage of a delayed server response (see above)</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2543"></a>5.5.1.&nbsp;setDebug()</h4></div></div></div><p>This function controls weather the server is going to echo debugging messages back to the client as comments in response body. Valid values: 0,1,2,3, with 1 being the default. At level 0, no debug info is returned to the client. At level 2, the complete client request is added to the response, as part of the xml comments. At level 3, a new PHP error handler is set when executing user functions exposed as server methods, and all non-fatal errors are trapped and added as comments into the response.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2548"></a>5.5.2.&nbsp;allow_system_funcs</h4></div></div></div><p>Default_value: TRUE. When set to FALSE, disables support for <code class="methodname">System.xxx</code> functions in the server. It might be useful e.g. if you do not wish the server to respond to requests to <code class="methodname">System.ListMethods</code>.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2559"></a>5.5.3.&nbsp;compress_response</h4></div></div></div><p>When set to TRUE, enables the server to take advantage of HTTP compression, otherwise disables it. Responses will be transparently compressed, but only when an xmlrpc-client declares its support for compression in the HTTP headers of the request.</p><p>Note that the ZLIB php extension must be installed for this to work. If it is, <code class="varname">compress_response</code> will default to TRUE.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2569"></a>5.5.4.&nbsp;response_charset_encoding</h4></div></div></div><p>Charset encoding to be used for response (only affects string values).</p><p>If it can, the server will convert the generated response from internal_encoding to the intended one.</p><p>Valid values are: a supported xml encoding (only UTF-8 and ISO-8859-1 at present, unless mbstring is enabled), null (leave charset unspecified in response and convert output stream to US_ASCII), 'default' (use xmlrpc library default as specified in xmlrpc.inc, convert output stream if needed), or 'auto' (use client-specified charset encoding or same as request if request headers do not specify it (unless request is US-ASCII: then use library default anyway).</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2578"></a>5.6.&nbsp;Fault reporting</h3></div></div></div><p>Fault codes for your servers should start at the value indicated by the global <code class="literal">$xmlrpcerruser</code> + 1.</p><p>Standard errors returned by the server include:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">1</code> <span>Unknown method</span></span></dt><dd><p>Returned if the server was asked to dispatch a method it didn't know about</p></dd><dt><span class="term"><code class="literal">2</code> <span>Invalid return payload</span></span></dt><dd><p>This error is actually generated by the client, not server, code, but signifies that a server returned something it couldn't understand. A more detailed error report is sometimes added onto the end of the phrase above.</p></dd><dt><span class="term"><code class="literal">3</code> <span>Incorrect parameters</span></span></dt><dd><p>This error is generated when the server has signature(s) defined for a method, and the parameters passed by the client do not match any of signatures.</p></dd><dt><span class="term"><code class="literal">4</code> <span>Can't introspect: method unknown</span></span></dt><dd><p>This error is generated by the builtin <code class="function">system.*</code> methods when any kind of introspection is attempted on a method undefined by the server.</p></dd><dt><span class="term"><code class="literal">5</code> <span>Didn't receive 200 OK from remote server</span></span></dt><dd><p>This error is generated by the client when a remote server doesn't return HTTP/1.1 200 OK in response to a request. A more detailed error report is added onto the end of the phrase above.</p></dd><dt><span class="term"><code class="literal">6</code> <span>No data received from server</span></span></dt><dd><p>This error is generated by the client when a remote server returns HTTP/1.1 200 OK in response to a request, but no response body follows the HTTP headers.</p></dd><dt><span class="term"><code class="literal">7</code> <span>No SSL support compiled in</span></span></dt><dd><p>This error is generated by the client when trying to send a request with HTTPS and the CURL extension is not available to PHP.</p></dd><dt><span class="term"><code class="literal">8</code> <span>CURL error</span></span></dt><dd><p>This error is generated by the client when trying to send a request with HTTPS and the HTTPS communication fails.</p></dd><dt><span class="term"><code class="literal">9-14</code> <span>multicall errors</span></span></dt><dd><p>These errors are generated by the server when something fails inside a system.multicall request.</p></dd><dt><span class="term"><code class="literal">100-</code> <span>XML parse errors</span></span></dt><dd><p>Returns 100 plus the XML parser error code for the fault that occurred. The <code class="function">faultString</code> returned explains where the parse error was in the incoming XML stream.</p></dd></dl></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2695"></a>5.7.&nbsp;'New style' servers</h3></div></div></div><p>In the same spirit of simplification that inspired the <code class="varname">xmlrpc_client::return_type</code> class variable, a new class variable has been added to the server class: <code class="varname">functions_parameters_type</code>. When set to 'phpvals', the functions registered in the server dispatch map will be called with plain php values as parameters, instead of a single xmlrpcmsg instance parameter. The return value of those functions is expected to be a plain php value, too. An example is worth a thousand words:</p><pre class="programlisting">
function foo($usr_id, $out_lang='en') {
global $xmlrpcerruser;
...
if ($someErrorCondition)
return new xmlrpcresp(0, $xmlrpcerruser+1, 'DOH!');
else
return array(
'name' =&gt; 'Joe',
'age' =&gt; 27,
'picture' =&gt; new xmlrpcval(file_get_contents($picOfTheGuy), 'base64')
);
}
$s = new xmlrpc_server(
array(
"examples.myFunc" =&gt; array(
"function" =&gt; "bar::foobar",
"signature" =&gt; array(
array($xmlrpcString, $xmlrpcInt),
array($xmlrpcString, $xmlrpcInt, $xmlrpcString)
)
)
), false);
$s-&gt;functions_parameters_type = 'phpvals';
$s-&gt;service();
</pre><p>There are a few things to keep in mind when using this simplified syntax:</p><p>to return an xmlrpc error, the method handler function must return an instance of xmlrpcresp. There is no other way for the server to know when an error response should be served to the client;</p><p>to return a base64 value, the method handler function must encode it on its own, creating an instance of an xmlrpcval object;</p><p>the method handler function cannot determine the name of the xmlrpc method it is serving, unlike standard handler functions that can retrieve it from the message object;</p><p>when receiving nested parameters, the method handler function has no way to distinguish a php string that was sent as base64 value from one that was sent as a string value;</p><p>this has a direct consequence on the support of system.multicall: a method whose signature contains datetime or base64 values will not be available to multicall calls;</p><p>last but not least, the direct parsing of xml to php values is much faster than using xmlrpcvals, and allows the library to handle much bigger messages without allocating all available server memory or smashing PHP recursive call stack.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch07s04.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ch07.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ch08.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;xmlrpcresp&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;8.&nbsp;Global variables</td></tr></table></div></body></html>