20.24. SimpleXMLRPCServer —基本的 XML-RPC 服务器

Note

SimpleXMLRPCServer模块已在 Python 3 中合并到xmlrpc.server中。2to3工具在将源转换为 Python 3 时将自动适应导入。

2.2 版中的新Function。

源代码: Lib/SimpleXMLRPCServer.py


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

    • class * SimpleXMLRPCServer. SimpleXMLRPCServer(* addr [,requestHandler [,logRequests [,allow_none [,encoding [,bind_and_activate]]]] *))
    • 创建一个新的服务器实例。此类提供用于注册可以由 XML-RPC 协议调用的Function的方法。 * requestHandler *参数应该是请求处理程序实例的工厂;默认为SimpleXMLRPCRequestHandler。 * addr requestHandler 参数传递到SocketServer.TCPServer构造函数。如果 logRequests *为 true(默认值),则将记录请求;否则,将记录请求。将此参数设置为 false 将关闭日志记录。 * allow_none encoding *参数传递到xmlrpclib并控制将从服务器返回的 XML-RPC 响应。 * bind_and_activate 参数控制构造器是否立即调用server_bind()server_activate();它默认为 true。将其设置为 false 允许代码在绑定地址之前操纵 allow_reuse_address *类变量。

在版本 2.5 中更改:添加了* allow_none encoding *参数。

在 2.6 版中进行了更改:添加了* bind_and_activate *参数。

    • class * SimpleXMLRPCServer. CGIXMLRPCRequestHandler([* allow_none * [,* encoding *]])
    • 创建一个新实例以在 CGI 环境中处理 XML-RPC 请求。 * allow_none encoding *参数传递到xmlrpclib并控制将从服务器返回的 XML-RPC 响应。

2.3 版的新Function。

在版本 2.5 中更改:添加了* allow_none encoding *参数。

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

20.24.1. SimpleXMLRPCServer 对象

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

  • SimpleXMLRPCServer. register_function(* function * [,* name *])

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

    • 注册一个对象,该对象用于公开尚未使用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 *选项允许入侵者访问模块的全局变量,并且可以允许入侵者在计算机上执行任意代码。仅在安全,封闭的网络上使用此选项。

在版本 2.3.5 中进行了更改:2.4.1 已添加* allow_dotted_names *来填补安全漏洞;以前的版本不安全。

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

2.3 版的新Function。

  • SimpleXMLRPCServer. register_multicall_functions ( )

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

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

2.5 版的新Function。

  • SimpleXMLRPCRequestHandler. encode_threshold
    • 如果此属性不是None,则在 Client 端允许的情况下,大于此值的响应将使用* gzip *传输编码进行编码。默认值为1400,大致对应于一个 TCP 数据包。

2.7 版的新Function。

20.24.1.1. SimpleXMLRPCServer 示例

Server code:

from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer 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 'div').
class MyFuncs:
    def div(self, x, y):
        return x // y

server.register_instance(MyFuncs())

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

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

import xmlrpclib

s = xmlrpclib.ServerProxy('http://localhost:8000')
print s.pow(2,3)  # Returns 2**3 = 8
print s.add(2,3)  # Returns 5
print s.div(5,2)  # Returns 5//2 = 2

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

以下SimpleXMLRPCServer示例包含在模块 Lib/SimpleXMLRPCServer.py 中:

server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.register_multicall_functions()
server.serve_forever()

该演示服务器可以从命令行运行,如下所示:

python -m SimpleXMLRPCServer

与上述服务器通信的示例 Client 端代码包含在 Lib/xmlrpclib.py 中:

server = ServerProxy("http://localhost:8000")
print server
multi = MultiCall(server)
multi.pow(2, 9)
multi.add(5, 1)
multi.add(24, 11)
try:
    for response in multi():
        print response
except Error, v:
    print "ERROR", v

并且可以使用以下命令直接调用 Client 端:

python -m xmlrpclib

20.24.2. CGIXMLRPCRequestHandler

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

  • CGIXMLRPCRequestHandler. register_function(* function * [,* name *])

    • 注册一个可以响应 XML-RPC 请求的函数。如果给出* name ,它将是与 function 关联的方法名称,否则将使用 function .__ name __ *。 * name *可以是普通字符串或 Unicode 字符串,并且可能包含 Python 标识符中不合法的字符,包括句点字符。
  • 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 div(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()