Skip to main content

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

源代码: Lib/xmlrpc/server.py


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

警告

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

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 参数应该是请求处理程序实例的工厂;它默认为 SimpleXMLRPCRequestHandleraddrrequestHandler 参数被传递给 socketserver.TCPServer 构造函数。如果 logRequests 为true(默认值),请求将被记录;将此参数设置为false将关闭日志记录。 allow_noneencoding 参数被传递到 xmlrpc.client 并控制将从服务器返回的XML-RPC响应。 bind_and_activate 参数控制构造函数是否立即调用 server_bind()server_activate();它默认为true。将其设置为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_noneencoding 参数传递给 xmlrpc.client 并控制将从服务器返回的XML-RPC响应。 use_builtin_types 参数传递给 loads() 函数,并控制在接收日期/时间值或二进制数据时处理哪些类型;它默认为false。

在 3.3 版更改: 已添加 use_builtin_types 标志。

class xmlrpc.server.SimpleXMLRPCRequestHandler

创建一个新的请求处理程序实例。此请求处理程序支持 POST 请求并修改日志记录,以使 SimpleXMLRPCServer 构造函数参数的 logRequests 参数受到支持。

21.27.1. SimpleXMLRPCServer对象

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

SimpleXMLRPCServer.register_function(function, name=None)

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

SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)

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

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

警告

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

SimpleXMLRPCServer.register_introspection_functions()

注册XML-RPC内省功能 system.listMethodssystem.methodHelpsystem.methodSignature

SimpleXMLRPCServer.register_multicall_functions()

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

SimpleXMLRPCRequestHandler.rpc_paths

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

21.27.1.1. SimpleXMLRPCServer示例

服务器代码:

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

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

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

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)

这个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,它将是与函数相关联的方法名称,否则将使用 function.__name__name 可以是正常字符串或Unicode字符串,并且可能包含Python标识符中不合法的字符,包括句点字符。

CGIXMLRPCRequestHandler.register_instance(instance)

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

CGIXMLRPCRequestHandler.register_introspection_functions()

注册XML-RPC内省函数 system.listMethodssystem.methodHelpsystem.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. 记录XMLRPC服务器

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

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

创建一个新的请求处理程序实例。此请求处理程序支持XML-RPC POST请求,记录GET请求,并修改日志记录,以便授予 DocXMLRPCServer 构造函数参数的 logRequests 参数。

21.27.4. DocXMLRPCServer对象

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

DocXMLRPCServer.set_server_title(server_title)

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

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“标题”元素中使用。

DocCGIXMLRPCRequestHandler.set_server_name(server_name)

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

DocCGIXMLRPCRequestHandler.set_server_documentation(server_documentation)

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