# `xmlrpc.server` — Serveurs XML-RPC de base

Code source : Lib/xmlrpc/server.py

Le module `xmlrpc.server` fournit un cadriciel basique pour les serveurs XML-RPC écrits en Python. Les serveurs peuvent être soit autonomes, en utilisant `SimpleXMLRPCServer`, soit intégrés dans un environnement CGI, en utilisant `CGIXMLRPCRequestHandler`.

Avertissement

Le module `xmlrpc.server` 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.

Disponibilité: not WASI.

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

class xmlrpc.server.SimpleXMLRPCServer(addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=False)

  Crée une nouvelle instance de serveur. Cette classe fournit des méthodes d'enregistrement des fonctions pouvant être appelées par le protocole XML-RPC. Le paramètre requestHandler doit être une fabrique pour les instances de gestionnaire de requêtes ; sa valeur par défaut est `SimpleXMLRPCRequestHandler`. Les paramètres addr et requestHandler sont passés au constructeur `socketserver.TCPServer`. Si logRequests est vrai (valeur par défaut), les requêtes sont enregistrées ; définir ce paramètre sur faux désactive la journalisation. Les paramètres allow_none et encoding sont transmis à `xmlrpc.client` et contrôlent les réponses XML-RPC qui sont renvoyées par le serveur. Le paramètre bind_and_activate contrôle si `server_bind()` et `server_activate()` sont appelés immédiatement par le constructeur ; la valeur par défaut est vraie. Le définir sur faux permet au code de manipuler la variable de classe allow_reuse_address avant que l'adresse ne soit liée. Le paramètre use_builtin_types est transmis à la fonction `loads()` et contrôle quels types sont traités lorsque des valeurs temporelles ou des données binaires sont reçues ; la valeur par défaut est faux.

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

class xmlrpc.server.CGIXMLRPCRequestHandler(allow_none=False, encoding=None, use_builtin_types=False)

  Crée une nouvelle instance pour gérer les requêtes XML-RPC dans un environnement CGI. Les paramètres allow_none et encoding sont transmis à `xmlrpc.client` et contrôlent les réponses XML-RPC qui sont renvoyées par le serveur. Le paramètre use_builtin_types est transmis à la fonction `loads()` et contrôle quels types sont traités lorsque des valeurs temporelles ou des données binaires sont reçues ; la valeur par défaut est faux.

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

class xmlrpc.server.SimpleXMLRPCRequestHandler

  Crée une nouvelle instance de gestionnaire de requêtes. Ce gestionnaire de requêtes prend en charge les requêtes `POST` et modifie la journalisation afin que le paramètre logRequests du paramètre du constructeur `SimpleXMLRPCServer` soit honoré.

## Objets SimpleXMLRPCServer

La classe `SimpleXMLRPCServer` dérive de `socketserver.TCPServer` et fournit un moyen de créer des serveurs XML-RPC simples et autonomes.

SimpleXMLRPCServer.register_function(function=None, name=None)

  Enregistre une fonction pouvant répondre aux requêtes XML-RPC. Si name est donné, c'est le nom de la méthode associée à function, sinon `function.__name__` est utilisé. name est une chaîne et peut contenir des caractères non légaux dans les identifiants Python, y compris le point.

  Cette méthode peut également être utilisée en tant que décorateur. Lorsqu'elle est utilisée comme décorateur, name ne peut être donné que comme argument nommé pour enregistrer function sous le nom name. Si name n'est pas donné, `function.__name__` est utilisé.

  Modifié dans la version 3.7: `register_function()` peut être utilisée comme décorateur.

SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)

  Enregistre un objet utilisé pour exposer des noms de méthodes qui n'ont pas été enregistrés à l'aide de `register_function()`. Si instance contient une méthode `_dispatch()`, elle est appelée avec le nom de la méthode demandée et les paramètres de la requête. Son prototype est `def _dispatch(self, method, params)` (notez que params ne représente pas une liste d'arguments variables). Si elle appelle une fonction sous-jacente pour effectuer sa tâche, cette fonction est appelée avec `func(*params)`, dépaquetant ainsi la liste des paramètres. La valeur de retour de `_dispatch()` est renvoyée au client comme résultat. Si instance n'a pas de méthode `_dispatch()`, un attribut correspondant au nom de la méthode demandée est recherché.

  Si l'argument facultatif allow_dotted_names est vrai et que l'instance n'a pas de méthode `_dispatch()`, alors si le nom de méthode demandé contient des points, chaque composant du nom de méthode est recherché individuellement, avec pour effet qu'une simple recherche hiérarchique est effectuée. La valeur trouvée lors de cette recherche est ensuite appelée avec les paramètres de la requête et la valeur de retour est renvoyée au client.

  Avertissement

  l'activation de l'option allow_dotted_names permet aux clients malveillants d'accéder aux variables globales de votre module et peut permettre aux clients malveillants d'exécuter du code arbitraire sur votre machine. Utilisez cette option uniquement sur un réseau sécurisé et fermé.

SimpleXMLRPCServer.register_introspection_functions()

  Enregistre les fonctions d'introspection XML-RPC `system.listMethods`, `system.methodHelp` et `system.methodSignature`.

SimpleXMLRPCServer.register_multicall_functions()

  Enregistre la fonction multi-appels XML-RPC `system.multicall`.

SimpleXMLRPCRequestHandler.rpc_paths

  La valeur de cet attribut doit être un n-uplet contenant les parties de chemin d'URL valides pour recevoir les requêtes XML-RPC. Les requêtes effectuées sur d’autres chemins entraînent une erreur HTTP 404 « No such page ». Si ce n-uplet est vide, tous les chemins sont considérés comme valides. La valeur par défaut est `('/', '/RPC2')`.

### Exemple SimpleXMLRPCServer

Code du serveur :

    from xmlrpc.server import SimpleXMLRPCServer
    from xmlrpc.server import SimpleXMLRPCRequestHandler

    # Restrict to a particular path.
    class RequestHandler(SimpleXMLRPCRequestHandler):
        rpc_paths = ('/RPC2',)

    # Create server
    with SimpleXMLRPCServer(('localhost', 8000),
                            requestHandler=RequestHandler) as server:
        server.register_introspection_functions()

        # Register pow() function; this will use the value of
        # pow.__name__ as the name, which is just 'pow'.
        server.register_function(pow)

        # Register a function under a different name
        def adder_function(x, y):
            return x + y
        server.register_function(adder_function, 'add')

        # Register an instance; all the methods of the instance are
        # published as XML-RPC methods (in this case, just 'mul').
        class MyFuncs:
            def mul(self, x, y):
                return x * y

        server.register_instance(MyFuncs())

        # Run the server's main loop
        server.serve_forever()

Le code client suivant appelle les méthodes mises à disposition par le serveur précédent :

    import xmlrpc.client

    s = xmlrpc.client.ServerProxy('http://localhost:8000')
    print(s.pow(2,3))  # Returns 2**3 = 8
    print(s.add(2,3))  # Returns 5
    print(s.mul(5,2))  # Returns 5*2 = 10

    # Print list of available methods
    print(s.system.listMethods())

`register_function()` peut également être utilisée comme décorateur, voici l'équivalent du serveur précédent :

    from xmlrpc.server import SimpleXMLRPCServer
    from xmlrpc.server import SimpleXMLRPCRequestHandler

    class RequestHandler(SimpleXMLRPCRequestHandler):
        rpc_paths = ('/RPC2',)

    with SimpleXMLRPCServer(('localhost', 8000),
                            requestHandler=RequestHandler) as server:
        server.register_introspection_functions()

        # Register pow() function; this will use the value of
        # pow.__name__ as the name, which is just 'pow'.
        server.register_function(pow)

        # Register a function under a different name, using
        # register_function as a decorator. *name* can only be given
        # as a keyword argument.
        @server.register_function(name='add')
        def adder_function(x, y):
            return x + y

        # Register a function under function.__name__.
        @server.register_function
        def mul(x, y):
            return x * y

        server.serve_forever()

L'exemple suivant inclus dans le module `Lib/xmlrpc/server.py` montre un serveur autorisant les noms pointés et enregistrant une fonction multicall.

Avertissement

l'activation de l'option allow_dotted_names permet aux clients malveillants d'accéder aux variables globales de votre module et peut permettre aux clients malveillants d'exécuter du code arbitraire sur votre machine. N'utilisez cet exemple que dans un réseau sécurisé et fermé.

    import datetime

    class ExampleService:
        def getData(self):
            return '42'

        class currentTime:
            @staticmethod
            def getCurrentTime():
                return datetime.datetime.now()

    with SimpleXMLRPCServer(("localhost", 8000)) as server:
        server.register_function(pow)
        server.register_function(lambda x,y: x+y, 'add')
        server.register_instance(ExampleService(), allow_dotted_names=True)
        server.register_multicall_functions()
        print('Serving XML-RPC on localhost port 8000')
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            print("\nKeyboard interrupt received, exiting.")
            sys.exit(0)

Cette démonstration d'ExempleService peut être invoquée à partir de la ligne de commande suivante :

    python -m xmlrpc.server

Le client qui interagit avec le serveur ci-dessus est inclus dans `Lib/xmlrpc/client.py` :

    server = ServerProxy("http://localhost:8000")

    try:
        print(server.currentTime.getCurrentTime())
    except Error as v:
        print("ERROR", v)

    multi = MultiCall(server)
    multi.getData()
    multi.pow(2,9)
    multi.add(1,2)
    try:
        for response in multi():
            print(response)
    except Error as v:
        print("ERROR", v)

Ce client qui interagit avec le serveur de démonstration XMLRPC peut être appelé comme ci :

    python -m xmlrpc.client

## CGIXMLRPCRequestHandler

La classe `CGIXMLRPCRequestHandler` peut être utilisée pour gérer les requêtes XML-RPC envoyées aux scripts Python CGI.

CGIXMLRPCRequestHandler.register_function(function=None, name=None)

  Enregistre une fonction pouvant répondre aux requêtes XML-RPC. Si name est donné, c'est le nom de la méthode associée à function, sinon `function.__name__` est utilisé. name est une chaîne et peut contenir des caractères non légaux dans les identifiants Python, y compris le point.

  Cette méthode peut également être utilisée en tant que décorateur. Lorsqu'elle est utilisée comme décorateur, name ne peut être donné que comme argument nommé pour enregistrer function sous le nom name. Si name n'est pas donné, `function.__name__` est utilisé.

  Modifié dans la version 3.7: `register_function()` peut être utilisée comme décorateur.

CGIXMLRPCRequestHandler.register_instance(instance)

  Enregistre un objet utilisé pour exposer des noms de méthodes qui n'ont pas été enregistrées à l'aide de `register_function()`. Si l'instance contient une méthode `_dispatch()`, elle est appelée avec le nom de la méthode demandée et les paramètres de la requête ; la valeur de retour est renvoyée au client comme résultat. Si l'instance n'a pas de méthode `_dispatch()`, elle recherche un attribut correspondant au nom de la méthode demandée ; si le nom de méthode demandée contient des points, chaque composant du nom de méthode est recherché individuellement, avec pour effet qu'une simple recherche hiérarchique est effectuée. La valeur trouvée lors de cette recherche est ensuite appelée avec les paramètres de la requête et la valeur de retour est renvoyée au client.

CGIXMLRPCRequestHandler.register_introspection_functions()

  Enregistre les fonctions d'introspection XML-RPC `system.listMethods`, `system.methodHelp` et `system.methodSignature`.

CGIXMLRPCRequestHandler.register_multicall_functions()

  Enregistre la fonction multi-appels XML-RPC `system.multicall`.

CGIXMLRPCRequestHandler.handle_request(request_text=None)

  Gère une requête XML-RPC. Si request_text est donné, il doit s'agir des données POST fournies par le serveur HTTP, sinon le contenu de stdin est utilisé.

Exemple :

    class MyFuncs:
        def mul(self, x, y):
            return x * y

    handler = CGIXMLRPCRequestHandler()
    handler.register_function(pow)
    handler.register_function(lambda x,y: x+y, 'add')
    handler.register_introspection_functions()
    handler.register_instance(MyFuncs())
    handler.handle_request()

## Documentation du serveur XMLRPC

Ces classes étendent les classes ci-dessus pour servir la documentation HTML en réponse aux requêtes HTTP GET. Les serveurs peuvent être soit autonomes, en utilisant `DocXMLRPCServer`, soit intégrés dans un environnement CGI, en utilisant `DocCGIXMLRPCRequestHandler`.

class xmlrpc.server.DocXMLRPCServer(addr, requestHandler=DocXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=True)

  Crée une nouvelle instance de serveur. Tous les paramètres ont la même signification que pour `SimpleXMLRPCServer` ; requestHandler est par défaut `DocXMLRPCRequestHandler`.

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

class xmlrpc.server.DocCGIXMLRPCRequestHandler

  Crée une nouvelle instance pour gérer les requêtes XML-RPC dans un environnement CGI.

class xmlrpc.server.DocXMLRPCRequestHandler

  Crée une nouvelle instance de gestionnaire de requêtes. Ce gestionnaire de requêtes prend en charge les requêtes XML-RPC POST, les requêtes GET de documentation et modifie la journalisation afin que le paramètre logRequests du paramètre de constructeur `DocXMLRPCServer` soit honoré.

## Objets DocXMLRPCServer

La classe `DocXMLRPCServer` dérive de `SimpleXMLRPCServer` et fournit un moyen de créer des serveurs XML-RPC autonomes et auto-documentés. Les requêtes HTTP POST sont traitées comme des appels de méthode XML-RPC. Les requêtes HTTP GET sont gérées en générant une documentation HTML de style pydoc. Cela permet à un serveur de fournir sa propre documentation Web.

DocXMLRPCServer.set_server_title(server_title)

  Définit le titre utilisé dans la documentation HTML générée. Ce titre est utilisé à l'intérieur de l'élément HTML `title`.

DocXMLRPCServer.set_server_name(server_name)

  Définit le nom utilisé dans la documentation HTML générée. Ce nom apparaît en haut de la documentation générée à l'intérieur d'un élément `h1`.

DocXMLRPCServer.set_server_documentation(server_documentation)

  Définit la description utilisée dans la documentation HTML générée. Cette description apparaît sous forme de paragraphe, sous le nom du serveur, dans la documentation.

## DocCGIXMLRPCRequestHandler

La classe `DocCGIXMLRPCRequestHandler` dérive de `CGIXMLRPCRequestHandler` et fournit un moyen de créer des scripts CGI XML-RPC auto-documentés. Les requêtes HTTP POST sont traitées comme des appels de méthode XML-RPC. Les requêtes HTTP GET sont gérées en générant une documentation HTML de style pydoc. Cela permet à un serveur de fournir sa propre documentation Web.

DocCGIXMLRPCRequestHandler.set_server_title(server_title)

  Définit le titre utilisé dans la documentation HTML générée. Ce titre est utilisé à l'intérieur de l'élément HTML `title`.

DocCGIXMLRPCRequestHandler.set_server_name(server_name)

  Définit le nom utilisé dans la documentation HTML générée. Ce nom apparaît en haut de la documentation générée à l'intérieur d'un élément `h1`.

DocCGIXMLRPCRequestHandler.set_server_documentation(server_documentation)

  Définit la description utilisée dans la documentation HTML générée. Cette description apparaît sous forme de paragraphe, sous le nom du serveur, dans la documentation.