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

源代码: Lib/xmlrpc/server.py


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

Warning

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

在版本 3.3 中更改:添加了* use_builtin_types *标志。

  • 类别 xmlrpc.server. SimpleXMLRPCRequestHandler
    • 创建一个新的请求处理程序实例。该请求处理程序支持POST个请求并修改日志记录,以便遵守SimpleXMLRPCServer构造函数参数的* logRequests *参数。

SimpleXMLRPCServer Objects

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

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

此方法也可以用作装饰器。当用作装饰器时,只能将* 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()的返回值作为结果返回给 Client 端。如果 instance *没有_dispatch()方法,则在其中搜索与所请求方法名称匹配的属性。

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

Warning

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

  • SimpleXMLRPCServer. register_introspection_functions ( )

    • 注册 XML-RPC 自省Functionsystem.listMethodssystem.methodHelpsystem.methodSignature
  • SimpleXMLRPCServer. register_multicall_functions ( )

    • 注册 XML-RPC 多重调用函数 system.multicall。
  • SimpleXMLRPCRequestHandler. rpc_paths

    • 一个属性值,必须是一个 Tuples,列出接收 XML-RPC 请求的 URL 的有效路径部分。发布到其他路径的请求将导致 404“无此页面” HTTP 错误。如果该 Tuples 为空,则所有路径都将视为有效。默认值为('/', '/RPC2')

SimpleXMLRPCServer Example

Server code:

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

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

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()也可以用作装饰器。前面的服务器示例可以用修饰器方式注册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模块中包含的以下示例显示了一个服务器,该服务器允许使用点号命名并注册一个多重调用Function。

Warning

启用* 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

与上述服务器进行交互的 Client 端包含在 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 服务器交互的此 Client 端可以pass以下方式调用:

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 用作关键字参数,以将 function 注册在 name 下。如果没有给出名称*,将使用function.__name__

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

  • CGIXMLRPCRequestHandler. register_instance(* instance *)

    • 注册一个对象,该对象用于公开尚未使用register_function()注册的方法名称。如果 instance 包含_dispatch()方法,则使用请求的方法名称和请求中的参数调用该方法;返回值作为结果返回给 Client 端。如果 instance 没有_dispatch()方法,则在该实例中搜索与所请求方法名称匹配的属性;如果请求的方法名称包含句点,则将分别搜索方法名称的每个组成部分,从而执行简单的分层搜索。然后使用请求中的参数调用从此搜索中找到的值,并将返回值传递回 Client 端。
  • CGIXMLRPCRequestHandler. register_introspection_functions ( )

    • 注册 XML-RPC 自省Functionsystem.listMethodssystem.methodHelpsystem.methodSignature
  • CGIXMLRPCRequestHandler. register_multicall_functions ( )

    • 注册 XML-RPC 多重调用函数system.multicall
  • CGIXMLRPCRequestHandler. handle_request(* request_text = None *)

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

Example:

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独立安装,也可以使用DocCGIXMLRPCRequestHandler嵌入 CGI 环境中。

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

在版本 3.3 中更改:添加了* use_builtin_types *标志。

  • 类别 xmlrpc.server. DocCGIXMLRPCRequestHandler

    • 创建一个新实例以在 CGI 环境中处理 XML-RPC 请求。
  • 类别 xmlrpc.server. DocXMLRPCRequestHandler

    • 创建一个新的请求处理程序实例。该请求处理程序支持 XML-RPC POST 请求,文档 GET 请求,并修改日志记录,以便使用DocXMLRPCServer构造函数参数的* logRequests *参数。

DocXMLRPCServer Objects

DocXMLRPCServer类是从SimpleXMLRPCServer派生的,它提供了一种创建自文档的独立 XML-RPC 服务器的方法。 HTTP POST 请求作为 XML-RPC 方法调用处理。pass生成 pydoc 样式的 HTML 文档来处理 HTTP GET 请求。这允许服务器提供其自己的基于 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 方法调用处理。pass生成 pydoc 样式的 HTML 文档来处理 HTTP GET 请求。这允许服务器提供其自己的基于 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 文档中使用的描述。该说明将在文档中的服务器名称下方以一段显示。