xmlrpc.server — 基本的 XML-RPC 服务器 — Python 文档

来自菜鸟教程
Python/docs/3.10/library/xmlrpc.server
跳转至:导航、​搜索

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

源代码: :source:`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 为真(默认),请求将被记录; 将此参数设置为 false 将关闭日志记录。 allow_noneencoding 参数传递给 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_noneencoding 参数传递给 xmlrpc.client 并控制将从服务器返回的 XML-RPC 响应。 use_builtin_types 参数传递给 loads() 函数并控制接收日期/时间值或二进制数据时处理哪些类型; 它默认为 false。

3.3 版更改: 添加了 use_builtin_types 标志。

class xmlrpc.server.SimpleXMLRPCRequestHandler
创建一个新的请求处理程序实例。 此请求处理程序支持 [X30X] 请求并修改日志记录,以便支持 SimpleXMLRPCServer 构造函数参数的 logRequests 参数。

SimpleXMLRPCServer 对象

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

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

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

此方法也可以用作装饰器。 当用作装饰器时,name 只能作为关键字参数给出,以在 name 下注册 function。 如果没有给出 name,将使用 function.__name__

3.7 版更改: register_function() 可以用作装饰器。

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

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

register_function() 也可以用作装饰器。 前面的服务器示例可以以装饰器的方式注册函数:

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

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

CGIXMLRPCRequestHandler

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

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

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

此方法也可以用作装饰器。 当用作装饰器时,name 只能作为关键字参数给出,以在 name 下注册 function。 如果没有给出 name,将使用 function.__name__

3.7 版更改: register_function() 可以用作装饰器。

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

记录 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 参数得到遵守。


DocXMLRPCServer 对象

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 文档中使用的描述。 此描述将在文档中显示为位于服务器名称下方的段落。


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 文档中使用的描述。 此描述将在文档中显示为位于服务器名称下方的段落。