# 21.27. `xmlrpc.server` - 基本XML-RPC服务器

源代码： Lib / xmlrpc / server.py

`xmlrpc.server`模块为使用Python编写的XML-RPC服务器提供了一个基本的服务器框架。服务器可以使用`SimpleXMLRPCServer`独立运行，也可以使用`CGIXMLRPCRequestHandler`嵌入CGI环境中。

警告

`xmlrpc.server`模块对于恶意构造的数据不安全。如果需要解析不受信任或未经身份验证的数据，请参阅XML vulnerabilities。

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

  创建新服务器实例。此类提供了可以由XML-RPC协议调用的函数的注册方法。requestHandler参数应该是请求处理程序实例的工厂；它默认为`SimpleXMLRPCRequestHandler`。addr和requestHandler参数传递给`socketserver.TCPServer`构造函数。如果logRequests为true（默认值），则会记录请求；将此参数设置为false将关闭日志记录。allow_none和编码参数传递到`xmlrpc.client`，并控制将从服务器返回的XML-RPC响应。bind_and_activate参数控制是否由构造函数立即调用`server_bind()`和`server_activate()`将其设置为false允许代码在绑定地址之前操作allow_reuse_address类变量。use_builtin_types参数传递到`loads()`函数，并控制在接收到日期/时间值或二进制数据时处理的类型；它默认为false。

  在版本3.3中已更改：添加了use_builtin_types标志。

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

  创建一个新的实例来处理CGI环境中的XML-RPC请求。allow_none和编码参数传递到`xmlrpc.client`，并控制将从服务器返回的XML-RPC响应。use_builtin_types参数传递到`loads()`函数，并控制在接收到日期/时间值或二进制数据时处理的类型；它默认为false。

  在版本3.3中已更改：添加了use_builtin_types标志。

class `xmlrpc.server.``SimpleXMLRPCRequestHandler`

  创建一个新的请求处理程序实例。此请求处理程序支持`POST`请求并修改日志记录，以便将logRequests参数指向`SimpleXMLRPCServer`构造函数参数。

## 21.27.1. SimpleXMLRPCServer Objects

`SimpleXMLRPCServer`类基于`socketserver.TCPServer`，并提供了创建简单的独立XML-RPC服务器的方法。

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

  注册可以响应XML-RPC请求的函数。如果给定name，则将是与函数相关联的方法名称，否则将使用`function.__name__`。名称可以是正常字符串或Unicode字符串，并且可能包含Python标识符中不合法的字符，包括句点字符。

`SimpleXMLRPCServer.``register_instance`(instance, allow_dotted_names=False)

  注册用于公开未使用`register_function()`注册的方法名称的对象。如果实例包含`_dispatch()`方法，则使用请求的方法名称和请求中的参数调用它。其API为`def _dispatch（self， 方法， params）` params不表示可变参数列表）。如果它调用一个底层函数来执行它的任务，该函数被称为`func(*params)`，扩展参数列表。来自`_dispatch()`的返回值作为结果返回到客户端。如果实例没有`_dispatch()`方法，则搜索与所请求方法的名称匹配的属性。

  如果可选的allow_dotted_names参数为真，且实例没有`_dispatch()`方法，则如果请求的方法名称包含句点，则搜索方法名称的每个组件单独地，具有执行简单的分层搜索的效果。然后使用来自请求的参数调用从此搜索中找到的值，并将返回值传递回客户端。

  警告

  启用allow_dotted_names选项允许入侵者访问您模块的全局变量，并允许入侵者在您的机器上执行任意代码。仅在安全，封闭的网络上使用此选项。

`SimpleXMLRPCServer.``register_introspection_functions`()

  注册XML-RPC内省函数`system.listMethods`，`system.methodHelp`和`system.methodSignature`。

`SimpleXMLRPCServer.``register_multicall_functions`()

  注册XML-RPC多元函数system.multicall。

`SimpleXMLRPCRequestHandler.``rpc_paths`

  属性值，必须是列出用于接收XML-RPC请求的URL的有效路径部分的元组。发布到其他路径的请求将导致404“无此类网页”HTTP错误。如果此元组为空，所有路径将被视为有效。默认值为`（'/'， '/ RPC2'）`。

### 21.27.1.1. SimpleXMLRPCServer Example

服务器代码：

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

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

    # Create server
    server = SimpleXMLRPCServer(("localhost", 8000),
                                requestHandler=RequestHandler)
    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()

以下客户端代码将调用前面的服务器提供的方法：

    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())

包含在`Lib/xmlrpc/server.py`模块中的以下示例显示允许点名称和注册多元函数的服务器。

警告

启用allow_dotted_names选项允许入侵者访问您模块的全局变量，并允许入侵者在您的机器上执行任意代码。仅在安全，封闭的网络中使用此示例。

    import datetime

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

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

    server = SimpleXMLRPCServer(("localhost", 8000))
    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.")
        server.server_close()
        sys.exit(0)

这个ExampleService演示可以从命令行调用：

    python -m xmlrpc.server

与上述服务器交互的客户端包含在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)

与演示XMLRPC服务器交互的此客户端可以调用：

    python -m xmlrpc.client

## 21.27.2. CGIXMLRPCRequestHandler

`CGIXMLRPCRequestHandler`类可用于处理发送到Python CGI脚本的XML-RPC请求。

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

  注册可以响应XML-RPC请求的函数。如果给定name，它将是与函数关联的方法名，否则将使用函数.__ name __。名称可以是正常字符串或Unicode字符串，并且可能包含Python标识符中不合法的字符，包括句点字符。

`CGIXMLRPCRequestHandler.``register_instance`(instance)

  注册用于公开未使用`register_function()`注册的方法名称的对象。如果实例包含`_dispatch()`方法，则使用请求的方法名称和请求中的参数调用它；返回值作为结果返回到客户端。如果实例没有`_dispatch()`方法，则搜索与所请求方法的名称匹配的属性；如果所请求的方法名称包含句点，则单独搜索方法名称的每个组件，其效果是执行简单的分层搜索。然后使用来自请求的参数调用从此搜索中找到的值，并将返回值传递回客户端。

`CGIXMLRPCRequestHandler.``register_introspection_functions`()

  注册XML-RPC内省功能`system.listMethods`，`system.methodHelp`和`system.methodSignature`。

`CGIXMLRPCRequestHandler.``register_multicall_functions`()

  注册XML-RPC多元函数`system.multicall`。

`CGIXMLRPCRequestHandler.``handle_request`(request_text=None)

  处理XML-RPC请求。如果给出request_text，它应该是HTTP服务器提供的POST数据，否则将使用stdin的内容。

例：

    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()

## 21.27.3. Documenting XMLRPC server

这些类扩展了上述类来响应HTTP GET请求来提供HTML文档。服务器可以使用`DocXMLRPCServer`独立运行，也可以使用`DocCGIXMLRPCRequestHandler`嵌入在CGI环境中。

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

  创建新服务器实例。所有参数的含义与`SimpleXMLRPCServer`相同； requestHandler默认为`DocXMLRPCRequestHandler`。

  在版本3.3中已更改：添加了use_builtin_types标志。

class `xmlrpc.server.``DocCGIXMLRPCRequestHandler`

  创建一个新的实例来处理CGI环境中的XML-RPC请求。

class `xmlrpc.server.``DocXMLRPCRequestHandler`

  创建一个新的请求处理程序实例。This request handler supports XML-RPC POST requests, documentation GET requests, and modifies logging so that the logRequests parameter to the `DocXMLRPCServer` constructor parameter is honored.

## 21.27.4. DocXMLRPCServer Objects

`DocXMLRPCServer`类派生自`SimpleXMLRPCServer`，并提供了创建自文档，独立XML-RPC服务器的方法。HTTP POST请求作为XML-RPC方法调用处理。HTTP GET请求通过生成pydoc风格的HTML文档来处理。这允许服务器提供其自己的基于Web的文档。

`DocXMLRPCServer.``set_server_title`(server_title)

  设置生成的HTML文档中使用的标题。此标题将在HTML“title”元素中使用。

`DocXMLRPCServer.``set_server_name`(server_name)

  设置生成的HTML文档中使用的名称。此名称将显示在生成的文档顶部的“h1”元素中。

`DocXMLRPCServer.``set_server_documentation`(server_documentation)

  设置生成的HTML文档中使用的描述。此描述将在文档中显示为服务器名称下面的段落。

## 21.27.5. DocCGIXMLRPCRequestHandler

`DocCGIXMLRPCRequestHandler`类派生自`CGIXMLRPCRequestHandler`，并提供了创建自文档，XML-RPC CGI脚本的方法。HTTP POST请求作为XML-RPC方法调用处理。HTTP GET请求通过生成pydoc风格的HTML文档来处理。这允许服务器提供其自己的基于Web的文档。

`DocCGIXMLRPCRequestHandler.``set_server_title`(server_title)

  设置生成的HTML文档中使用的标题。此标题将在HTML“title”元素中使用。

`DocCGIXMLRPCRequestHandler.``set_server_name`(server_name)

  设置生成的HTML文档中使用的名称。此名称将显示在生成的文档顶部的“h1”元素中。

`DocCGIXMLRPCRequestHandler.``set_server_documentation`(server_documentation)

  设置生成的HTML文档中使用的描述。此描述将在文档中显示为服务器名称下面的段落。