Zend_XmlRpc_Server
Introduction
Zend_XmlRpc_Server fournit un serveur XML-RPC qui suit les spécifications dictées par www.xmlrpc.com. Il fournit aussi la méthode
system.multicall(), permettant le traitement de requêtes multiples.
Usage de base
Voici un exemple d'utilisation basique :
setClass('My_Service_Class');
echo $server->handle();
]]>
Structures du serveur
Zend_XmlRpc_Server se décompose en un objet serveur (lui-même), un objet requête, réponse, et
des objets d'erreurs.
Pour démarrer un serveur Zend_XmlRpc_Server, vous devez attacher une ou plusieurs classes ou
fonctions au serveur, grâce à setClass() et addFunction().
Lorsque c'est fait, vous pouvez passer un objet Zend_XmlRpc_Request à
Zend_XmlRpc_Server::handle(), sinon par défaut il utilisera un objet
Zend_XmlRpc_Request_Http qui récupérera la requête depuis php://input.
Zend_XmlRpc_Server::handle() va alors essayer de traiter la requête. Cette méthode retournera
un objet Zend_XmlRpc_Response ou Zend_XmlRpc_Server_Fault. Tous deux possèdent une
méthode __toString() qui crée une réponse XML valide XML-RPC.
Conventions
Zend_XmlRpc_Server permet d'attacher des classes et/ou des fonctions au serveur XML-RPC.
Grâce à Zend_Server_Reflection, l'introspection va utiliser les blocs de commentaires pour
déterminer les types d'arguments et de réponse de la fonction/classe.
Les types XML-RPC n'ont pas forcément de correspondance native vers un type PHP. Le code fera de son mieux
pour deviner le type de données approprié, en se basant sur les valeurs listées dans les balises @param et
@return. Certains types XML-RPC n'ont par contre pas d'équivalent PHP direct, ils devront alors être spécifiés
manuellement sous forme de balises phpdoc :
dateTime.iso8601, une chaîne formatée comme YYYYMMDDTHH:mm:ss
base64, données encodées en base64
struct, tableau associatif
Voici un exemple d'utilisation de type particulier:
PhpDocumentor ne vérifie (valide) pas les types des paramètres, mais les types sont obligatoires pour que
le serveur puisse lui, valider les paramètres passés aux appels des méthodes.
Il est parfaitement valide de spécifier plusieurs types pour les paramètres et les retours de méthodes. La
spécification XML-RPC suggère que system.methodSignature retourne un tableau des possibilités au regard des
paramètres d'entrée de la méthode, et de son type de sortie. Ceci ce fait grâce au caractère '|' de
PhpDocumentor
Attention toutefois, une signature multiple peut prêter à confusion au regard des personnes utilisant
votre service. En général une fonction ne devrait posséder qu'une seule signature.
Utiliser des espaces de noms (Namespaces)
XML-RPC accepte le concept d'espace de noms, ce qui permet de grouper les méthodes XML-RPC. Ceci aide à
prévenir les collisions de noms (deux fonctions avec le même nom), de différentes classes. Par exemple le
serveur XML-RPC sert des méthodes dans l'espace "system" :
system.listMethods
system.methodHelp
system.methodSignature
En interne la correspondance est faite avec les méthodes du même nom, de
Zend_XmlRpc_Server.
Si vous voulez ajouter un espace de noms aux méthodes que vous servez, procédez alors comme suit :
setClass('My_Service_Class', 'myservice');
// la fonction 'somefunc' sera accessible via funcs.somefunc
$server->addFunction('somefunc', 'funcs');
]]>
Requêtes personnalisées
La plupart du temps, vous utiliserez l'objet de requête par défaut Zend_XmlRpc_Request_Http,
sans vous en occuper. En revanche si vous avez un besoin spécifique, comme par exemple journaliser la requête,
traiter une requête CLI, GUI, ou autre environnement, vous devrez alors créer un objet étendant
Zend_XmlRpc_Request. Implémentez les méthodes getMethod() et getParams()
afin que le serveur puisse analyser ces informations pour traiter la requête.
Réponses personnalisées
Comme avec les objets de requête, Zend_XmlRpc_Server peut retourner des objets de réponse
personnalisés. Par défaut il s'agit d'objets Zend_XmlRpc_Response_Http qui envoient un en-tête HTTP
Content-Type HTTP pour XML-RPC. Vous pourriez utiliser des objets de réponse personnalisés pour par exemple
renvoyer les réponses vers STDOUT, ou les journaliser.
Pour utiliser une classe de réponse personnalisée, utilisez
Zend_XmlRpc_Server::setResponseClass() avant d'appeler handle().
Gérer les exceptions grâce aux erreurs (Faults)
Zend_XmlRpc_Server attrape les Exceptions générées par vos classes/fonctions, et génère une
réponse XML-RPC "fault" lorsqu'une exception a été rencontrée. Par défaut, les message et code des exceptions ne
sont pas attachés dans la réponse XML-RPC. Ceci est du au fait que de telles exceptions peuvent en dire trop, au
regard de la sécurité de votre application.
Des classes d'exception peuvent cependant être mises en liste blanche, et donc utilisées pour les réponses
d'erreur ("fault"). Utilisez simplement Zend_XmlRpc_Server_Fault::attachFaultException() en lui
passant une classe d'exception :
Si vous héritez correctement vos exceptions, vous pouvez alors passer en liste blanche l'exception de plus
bas niveau, et ainsi accepter plusieurs types d'exceptions qui en hériteront. Évidemment, les
Zend_XmlRpc_Server_Exceptions sont elles automatiquement mises en liste blanche, afin de pouvoir traiter les
requêtes vers des méthodes inexistantes, ou toute autre erreur "générique".
Toute exception rencontrée, mais non mise en liste blanche, donnera naissance à une réponse d'erreur avec
le code "404" et le message "Unknown error".
Cacher la définition du serveur entre les requêtes
Attacher beaucoup de classes au serveur XML-RPC peut consommer beaucoup de ressources, car l'introspection
de chaque classe/fonction est mise en place.
Pour améliorer les performances, Zend_XmlRpc_Server_Cache peut être utilisé pour mettre en
cache la définition d'un serveur. Combiné à __autoload(), ceci améliore grandement les
performances.
Un exemple d'utilisation :
setClass('My_Services_Glue', 'glue');
// espace de noms glue
$server->setClass('My_Services_Paste', 'paste');
// espace de noms paste
$server->setClass('My_Services_Tape', 'tape');
// espace de noms tape
Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
}
echo $server->handle();
]]>
L'exemple ci dessus essaye de récupérer la définition du serveur via le fichier
xmlrpc.cache. Si ceci échoue, alors les classes nécessaires au service sont chargées,
attachées au serveur, et une tentative de création de cache est lancée.
Exemples d'utilisation
Voici quelques exemples qui démontrent les diverses options disponibles pour un serveur XML-RPC.
Utilisation basique
L'exemple ci dessous attache une fonction au service XML-RPC.
addFunction('md5Value');
echo $server->handle();
]]>
Attacher une classe
L'exemple ci dessous montre comment attacher les méthodes publiques d'une classe en tant que méthodes
XML-RPC.
setClass('Services_Comb');
echo $server->handle();
]]>
Attacher plusieurs classes grâce aux espaces de noms
L'exemple ci dessous montre comment attacher plusieurs classes grâce aux espaces de noms.
setClass('Services_Comb', 'comb');
// méthodes appelées sous la forme comb.*
$server->setClass('Services_Brush', 'brush');
// méthodes appelées sous la forme brush.*
$server->setClass('Services_Pick', 'pick');
// méthodes appelées sous la forme pick.*
echo $server->handle();
]]>
Spécifier les exceptions à utiliser en cas d'erreurs dans les réponses XML-RPC
L'exemple ci dessous montre comment spécifier les exceptions à utiliser en cas d'erreurs dans les
réponses XML-RPC.
setClass('Services_Comb', 'comb');
// méthodes appelées sous la forme comb.*
$server->setClass('Services_Brush', 'brush');
// méthodes appelées sous la forme brush.*
$server->setClass('Services_Pick', 'pick');
// méthodes appelées sous la forme pick.*
echo $server->handle();
]]>
Utiliser un objet de requête personnalisé
L'exemple suivant montre comment utiliser un objet de requête personnalisé.
setClass('Services_Comb', 'comb');
// méthodes appelées sous la forme comb.*
$server->setClass('Services_Brush', 'brush');
// méthodes appelées sous la forme brush.*
$server->setClass('Services_Pick', 'pick');
// méthodes appelées sous la forme pick.*
// Crée un objet de requête
$request = new Services_Request();
echo $server->handle($request);
]]>
Utiliser un objet de réponse personnalisé
L'exemple suivant montre comment utiliser un objet de réponse personnalisé.
setClass('Services_Comb', 'comb');
// méthodes appelées sous la forme comb.*
$server->setClass('Services_Brush', 'brush');
// méthodes appelées sous la forme brush.*
$server->setClass('Services_Pick', 'pick');
// méthodes appelées sous la forme pick.*
// Crée un objet de requête
$request = new Services_Request();
// Utilise une réponse personnalisée
$server->setResponseClass('Services_Response');
echo $server->handle($request);
]]>
Cache entre les requêtes
Les exemples suivants montrent comment gérer une politique de cache inter-requêtes.
setClass('Services_Comb', 'comb');
// méthodes appelées sous la forme comb.*
$server->setClass('Services_Brush', 'brush');
// méthodes appelées sous la forme brush.*
$server->setClass('Services_Pick', 'pick');
// méthodes appelées sous la forme pick.*
// Sauve le cache
Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
}
// Crée un objet de requête
$request = new Services_Request();
// Utilise une réponse personnalisée
$server->setResponseClass('Services_Response');
echo $server->handle($request);
]]>