# `xmlrpc.client` — Client XML-RPC

Source code: Lib/xmlrpc/client.py

XML-RPC est une méthode d'appel de procédure distante qui utilise du XML transmis via HTTP(S) comme transport. Un client peut ainsi appeler des méthodes avec des paramètres sur un serveur distant (le serveur est nommé par un URI) et récupérer des données structurées. Ce module prend en charge l'écriture de code client XML-RPC ; il gère la traduction entre les objets Python et le XML sur le réseau.

Avertissement

Le module `xmlrpc.client` n'est pas sécurisé contre les données construites de façon malveillante. Si vous avez besoin d'analyser des données non sécurisées ou non authentifiées, voir XML security.

Modifié dans la version 3.5: pour les URI HTTPS, `xmlrpc.client` effectue désormais par défaut toutes les vérifications nécessaires des certificats et des noms d'hôtes.

Disponibilité: not WASI.

Ce module ne fonctionne pas, ou n'est pas disponible en WebAssembly. Voir Plateformes WebAssembly pour plus d'informations.

class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None)

  Une instance `ServerProxy` est un objet qui gère la communication avec un serveur XML-RPC distant. Le premier argument, requis, est un URI (Uniform Resource Identifier, litt. identifiant uniforme de ressource), et est normalement l'URL du serveur. Le deuxième argument, facultatif, est une instance de fabrique de transport ; par défaut, il s'agit d'une instance de `SafeTransport` pour les URL HTTPS sinon d'une instance de `Transport`. Le troisième argument , facultatif, est un encodage, par défaut UTF-8. Le quatrième argument, facultatif, est un indicateur de débogage.

  Les paramètres suivants régissent l'utilisation de l'instance de mandataire renvoyée. Si allow_none est vrai, la constante Python `None` est traduite en XML ; le comportement par défaut est que `None` lève une `TypeError`. Il s'agit d'une extension de la spécification XML-RPC couramment utilisée, mais elle n'est pas prise en charge par tous les clients et serveurs ; voir http://ontosys.com/xml-rpc/extensions.php. L'indicateur use_builtin_types peut être utilisé pour que les dates et heures soient présentées comme des objets `datetime.datetime` et que les données binaires soient présentées comme des objets `bytes` ; cet indicateur est faux par défaut. Les objets `datetime.datetime`, `bytes` et `bytearray` peuvent être transmis aux appels. Le paramètre headers est une séquence facultative d'en-têtes HTTP à envoyer avec chaque requête, exprimée sous la forme d'une séquence de paires représentant le nom et la valeur de l'en-tête (par exemple `[('Header-Name', 'value')]`). Si une l'URL utilise HTTPS, context peut-être fourni sous forme d'une `ssl.SSLContext` pour configurer les paramètres SSL de la connexion sous-jacente. L'indicateur obsolète use_datetime est similaire à use_builtin_types mais il s'applique uniquement aux valeurs de date et heure.

  Modifié dans la version 3.3: l'indicateur use_builtin_types a été ajouté.

  Modifié dans la version 3.8: le paramètre headers a été ajouté.

  Les transports HTTP et HTTPS prennent en charge l'extension de syntaxe URL pour l'authentification HTTP basique : `http://user:pass@host:port/path`. La partie `user:pass` est codée en base64 en tant qu'en-tête HTTP « Authorization » et envoyée au serveur distant lors de l'appel d'une méthode XML-RPC. Vous ne devez l'utiliser que si le serveur distant nécessite un utilisateur et un mot de passe (Basic Authentication).

  L'instance renvoyée est un objet mandataire avec des méthodes qui peuvent être utilisées pour effectuer les appels RPC correspondants sur le serveur distant. Si le serveur distant prend en charge l'API d'introspection, le mandataire peut également être utilisé pour interroger le serveur distant sur les méthodes qu'il prend en charge (découverte de services) et récupérer d'autres métadonnées associées au serveur.

  Les types conformes (qui peuvent être sérialisés via XML) sont les éléments suivants (et, sauf indication contraire, sont du même type Python une fois désérialisés) :

  Type XML-RPC | Type Python
  --- | ---
  `boolean` | `bool`
  `int`, `i1`, `i2`, `i4`, `i8` ou `biginteger` | `int` compris entre -2147483648 et 2147483647. Les valeurs sont marquées avec la balise `<int>`.
  `double` ou `float` | `float`. Les valeurs reçoivent la balise `<double>`.
  `string` | `str`
  `array` | `liste` ou `n-uplet` contenant des éléments conformes. Les tableaux sont renvoyés sous forme de `listes`.
  `struct` | `dict`. Les clés doivent être des chaînes, les valeurs peuvent être de n'importe quel type conforme. Des instances de classes définies par l'utilisateur peuvent être transmises ; seul leur attribut `__dict__` est transmis.
  `dateTime.iso8601` | `DateTime` ou `datetime.datetime`. Le type renvoyé dépend des valeurs des indicateurs use_builtin_types et use_datetime.
  `base64` | `Binary`, `bytes` ou `bytearray`. Le type renvoyé dépend de la valeur de l'indicateur use_builtin_types.
  `nil` | La constante `None`. Son utilisation n'est autorisée que si allow_none est vrai.
  `bigdecimal` | `decimal.Decimal`. Type renvoyé uniquement.

  Il s'agit de l'ensemble complet des types de données pris en charge par XML-RPC. Les appels de méthode peuvent également lever l'exception `Fault`, utilisée pour signaler les erreurs du serveur XML-RPC, ou l'exception `ProtocolError` utilisée pour signaler une erreur dans la couche de transport HTTP/HTTPS. `Fault` et `ProtocolError` dérivent d'une exception mère appelée `Error`. Notez que le module `xmlrpc.client` ne sérialise actuellement pas les instances de sous-classes de types natifs.

  Lors de la sérialisation de chaînes, les caractères spéciaux à XML tels que `<`, `>` et `&` sont automatiquement échappés. Cependant, il est de la responsabilité de l'appelant de s'assurer que la chaîne ne contient pas de caractères non autorisés en XML, tels que les caractères de contrôle avec des valeurs ASCII comprises entre 0 et 31 (sauf, bien sûr, la tabulation, la nouvelle ligne et le retour chariot) ; si vous ne le faites pas, vous obtiendrez une requête XML-RPC qui n'est pas du XML valide. Si vous devez transmettre des octets arbitraires via XML-RPC, utilisez les classes `bytes` ou `bytearray` ou la classe de surcouche `Binary` décrite ci-dessous.

  `Server` est conservé comme alias pour `ServerProxy` pour des raisons de compatibilité descendante. Le nouveau code doit utiliser `ServerProxy`.

  Modifié dans la version 3.5: ajout de l'argument context.

  Modifié dans la version 3.6: ajout du support des balises de type avec préfixes (par exemple `ex:nil`). Ajout de la prise en charge des types supplémentaires utilisés par l'implémentation Apache XML-RPC pour les valeurs numériques : `i1`, `i2`, `i8`, `biginteger`, `float` et `bigdecimal`. Voir https://ws.apache.org/xmlrpc/types.html pour une description.

Voir aussi

Guide pratique XML-RPC

  Une bonne description du fonctionnement de XML-RPC et du logiciel client pour plusieurs langages. Contient à peu près tout ce qu'un développeur de client XML-RPC doit savoir.

Introspection de XML-RPC

  Décrit l'extension du protocole XML-RPC pour l'introspection.

Spécification XML-RPC

  La spécification officielle.

## Objets ServerProxy

Un `ServerProxy` possède une méthode correspondant à chaque procédure distante acceptée par le serveur XML-RPC. L'appel de la méthode effectue un appel distant (RPC) en fonction du nom et de la signature des arguments (le même nom de méthode pouvant être surchargé avec plusieurs signatures d'arguments). L'appel termine soit en renvoyant une valeur dans un type conforme, soit en levant une `Fault` ou une `ProtocolError` indiquant une erreur.

Les serveurs qui prennent en charge l'API d'introspection XML prennent en charge certaines méthodes courantes regroupées sous l'attribut réservé `system` :

ServerProxy.system.listMethods()

  Cette méthode renvoie une liste de chaînes, une pour chaque méthode (non système) prise en charge par le serveur XML-RPC.

ServerProxy.system.methodSignature(name)

  Cette méthode prend un paramètre, le nom d'une méthode implémentée par le serveur XML-RPC. Elle renvoie une liste de signatures possibles pour cette méthode. Une signature est une liste de types. Le premier de ces types est le type de retour de la méthode, les autres sont des paramètres.

  Étant donné que plusieurs signatures (c'est-à-dire surcharges) sont autorisées, cette méthode renvoie une liste de signatures.

  Les signatures elles-mêmes sont limitées aux paramètres de niveau supérieur attendus par une méthode. Par exemple, si une méthode attend un tableau de structures comme paramètre et qu'elle renvoie une chaîne, sa signature est simplement `[str, list]`. Si elle attend trois entiers et renvoie une chaîne, sa signature est `[str, int, int, int]`.

  Si aucune signature n'est définie pour la méthode, le type de la valeur renvoyée est autre chose qu'une liste.

ServerProxy.system.methodHelp(name)

  Cette méthode prend un paramètre, le nom d'une méthode implémentée par le serveur XML-RPC. Elle renvoie une chaîne de documentation décrivant l'utilisation de cette méthode. Si aucune chaîne de ce type n'est disponible, une chaîne vide est renvoyée. La chaîne de documentation peut contenir un balisage HTML.

Modifié dans la version 3.5: les instances de `ServerProxy` prennent en charge le protocole context manager pour fermer le transport sous-jacent.

Voici un exemple concret. Le code du serveur :

    from xmlrpc.server import SimpleXMLRPCServer

    def is_even(n):
        return n % 2 == 0

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(is_even, "is_even")
    server.serve_forever()

Le code client correspondant au serveur précédent :

    import xmlrpc.client

    with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
        print("3 is even: %s" % str(proxy.is_even(3)))
        print("100 is even: %s" % str(proxy.is_even(100)))

## Objets `DateTime`

class xmlrpc.client.DateTime

  Cette classe peut être initialisée avec les secondes écoulées depuis epoch, un n-uplet temporel (semblable à un `time.struct_time`), une chaîne au format ISO 8601 ou une instance de `datetime.datetime`. Elle dispose des méthodes suivantes, prises en charge principalement pour un usage interne par le code de sérialisation-désérialisation :

  decode(string)

    Accepte une chaîne comme nouvelle valeur temporelle de l'instance.

  encode(out)

    Sérialise ce `DateTime` au format attendu par XML-RPC et l'écrit dans l'objet de flux out.

  Elle prend également en charge certains opérateurs natifs de Python via les `méthodes de comparaison riches` et `__repr__()`.

Voici un exemple concret. Le code du serveur :

    import datetime
    from xmlrpc.server import SimpleXMLRPCServer
    import xmlrpc.client

    def today():
        today = datetime.datetime.today()
        return xmlrpc.client.DateTime(today)

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(today, "today")
    server.serve_forever()

Le code client correspondant au serveur précédent :

    import xmlrpc.client
    import datetime

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")

    today = proxy.today()
    # convert the ISO8601 string to a datetime object
    converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
    print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M"))

## Objets binaires

class xmlrpc.client.Binary

  Cette classe peut être initialisée à partir d'instances de `bytes` (qui peuvent inclure des NUL). L'accès principal au contenu d'un objet `Binary` est fourni par un attribut :

  data

    Données binaires encapsulées par l'instance `Binary`. Les données sont fournies sous forme d'objet `bytes`.

  Les objets `Binary` ont les méthodes suivantes, prises en charge principalement pour un usage interne par le code de sérialisation-désérialisation :

  decode(bytes)

    Accepte un objet `bytes` encodant de la donnée en base64 et le décode comme les nouvelles données de l'instance.

  encode(out)

    Sérialise cette instance en base 64 tel qu'attendu par XML-RPC dans l'objet de flux out.

    Les données encodées sont découpées en lignes de 76 caractères conformément à la RFC 2045 section 6.8, qui était la spécification base64 standard de facto lorsque la spécification XML-RPC a été écrite.

  Elle prend également en charge certains opérateurs natifs de Python via les méthodes `__eq__()` et `__ne__()`.

Exemple d'utilisation des objets binaires. Nous allons transférer une image via XMLRPC :

    from xmlrpc.server import SimpleXMLRPCServer
    import xmlrpc.client

    def python_logo():
        with open("python_logo.jpg", "rb") as handle:
            return xmlrpc.client.Binary(handle.read())

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(python_logo, 'python_logo')

    server.serve_forever()

Le client récupère l'image et l'enregistre dans un fichier :

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    with open("fetched_python_logo.jpg", "wb") as handle:
        handle.write(proxy.python_logo().data)

## Objets Fault

class xmlrpc.client.Fault

  Un objet `Fault` encapsule le contenu d'une balise d'erreur XML-RPC. Les objets d'erreurs ont les attributs suivants :

  faultCode

    Entier indiquant le type d'erreur.

  faultString

    Chaîne contenant un message de diagnostic associé à l'erreur.

Dans l'exemple suivant, nous allons provoquer intentionnellement une `Fault` en renvoyant un objet de type complexe. Le code du serveur :

    from xmlrpc.server import SimpleXMLRPCServer

    # A marshalling error is going to occur because we're returning a
    # complex number
    def add(x, y):
        return x+y+0j

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(add, 'add')

    server.serve_forever()

Le code client correspondant au serveur précédent :

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    try:
        proxy.add(2, 5)
    except xmlrpc.client.Fault as err:
        print("A fault occurred")
        print("Fault code: %d" % err.faultCode)
        print("Fault string: %s" % err.faultString)

## Objets ProtocolError

class xmlrpc.client.ProtocolError

  Un objet `ProtocolError` décrit une erreur de protocole dans la couche de transport sous-jacente (telle qu'une erreur 404 « not found » si le serveur nommé par l'URI n'existe pas). Il possède les attributs suivants :

  url

    URI ou URL qui a déclenché l'erreur.

  errcode

    Code d'erreur.

  errmsg

    Message d'erreur ou chaîne de diagnostic.

  headers

    Dictionnaire contenant les en-têtes de la requête HTTP/HTTPS qui a déclenché l'erreur.

Dans l'exemple suivant, nous allons intentionnellement provoquer une `ProtocolError` en fournissant un URI non valide :

    import xmlrpc.client

    # create a ServerProxy with a URI that doesn't respond to XMLRPC requests
    proxy = xmlrpc.client.ServerProxy("http://google.com/")

    try:
        proxy.some_method()
    except xmlrpc.client.ProtocolError as err:
        print("A protocol error occurred")
        print("URL: %s" % err.url)
        print("HTTP/HTTPS headers: %s" % err.headers)
        print("Error code: %d" % err.errcode)
        print("Error message: %s" % err.errmsg)

## Objets `MultiCall`

L'objet `MultiCall` fournit un moyen d'encapsuler plusieurs appels vers un serveur distant dans une seule requête [1].

class xmlrpc.client.MultiCall(server)

  Crée un objet utilisé pour regrouper plusieurs appels de méthode. server est la cible de l'appel. Appeler des méthodes sur une instance de `MultiCall` ne fait que stocker le nom de la méthode et ses arguments, l'appel renvoie immédiatement `None` . Appeler l'objet lui-même entraîne la transmission de tous les appels stockés sous la forme d'une seule requête `system.multicall`. Le résultat de cet appel est un générateur ; itérer sur ce générateur donne les résultats individuels.

Voici un exemple d'utilisation de cette classe. Le code du serveur :

    from xmlrpc.server import SimpleXMLRPCServer

    def add(x, y):
        return x + y

    def subtract(x, y):
        return x - y

    def multiply(x, y):
        return x * y

    def divide(x, y):
        return x // y

    # A simple server with simple arithmetic functions
    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_multicall_functions()
    server.register_function(add, 'add')
    server.register_function(subtract, 'subtract')
    server.register_function(multiply, 'multiply')
    server.register_function(divide, 'divide')
    server.serve_forever()

Le code client correspondant au serveur précédent :

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    multicall = xmlrpc.client.MultiCall(proxy)
    multicall.add(7, 3)
    multicall.subtract(7, 3)
    multicall.multiply(7, 3)
    multicall.divide(7, 3)
    result = multicall()

    print("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))

## Fonctions utilitaires

xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)

  Convert params into an XML-RPC request, or into a response if methodresponse is true. params can be either a tuple of arguments or an instance of the `Fault` exception class. If methodresponse is true, only a single value can be returned, meaning that params must be of length 1. encoding, if supplied, is the encoding to use in the generated XML; the default is UTF-8. Python's `None` value cannot be used in standard XML-RPC; to allow using it via an extension, provide a true value for allow_none.

xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)

  Convertit une requête ou une réponse XML-RPC en une paire `(params, methodname)`. params est un n-uplet d'arguments ; methodname est une chaîne, ou `None` si aucun nom de méthode n'est présent dans le paquet. Si le paquet XML-RPC représente une erreur, cette fonction lève une exception `Fault`. L'indicateur use_builtin_types peut être utilisé pour que les valeurs temporelles soient converties en objets `datetime.datetime` et que les données binaires soient présentées comme des objets `bytes` ; cet indicateur est faux par défaut.

  L'indicateur obsolète use_datetime est similaire à use_builtin_types mais il s'applique uniquement aux valeurs temporelles.

  Modifié dans la version 3.3: l'indicateur use_builtin_types a été ajouté.

## Exemple d'utilisation du client

    # simple test program (from the XML-RPC specification)
    from xmlrpc.client import ServerProxy, Error

    # server = ServerProxy("http://localhost:8000") # local server
    with ServerProxy("http://betty.userland.com") as proxy:

        print(proxy)

        try:
            print(proxy.examples.getStateName(41))
        except Error as v:
            print("ERROR", v)

Pour accéder à un serveur XML-RPC via un mandataire HTTP, vous devez définir un transport personnalisé. L'exemple suivant montre comment faire :

    import http.client
    import xmlrpc.client

    class ProxiedTransport(xmlrpc.client.Transport):

        def set_proxy(self, host, port=None, headers=None):
            self.proxy = host, port
            self.proxy_headers = headers

        def make_connection(self, host):
            connection = http.client.HTTPConnection(*self.proxy)
            connection.set_tunnel(host, headers=self.proxy_headers)
            self._connection = host, connection
            return connection

    transport = ProxiedTransport()
    transport.set_proxy('proxy-server', 8080)
    server = xmlrpc.client.ServerProxy('http://betty.userland.com', transport=transport)
    print(server.examples.getStateName(41))

## Exemple d'utilisation du client et du serveur

Voir Exemple SimpleXMLRPCServer.

Notes

[1]

Cette approche a été présentée pour la première fois dans une discussion sur xmlrpc.com .