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

原始碼: Lib/xmlrpc/server.py


xmlrpc.server 模組為使用 Python 編寫的 XML-RPC 伺服器提供了一個基本的伺服器框架。伺服器可以使用 SimpleXMLRPCServer 獨立執行,也可以使用 CGIXMLRPCRequestHandler 嵌入在 CGI 環境中。

警告

xmlrpc.server 模組對於惡意構造的資料是不安全的。如果你需要解析不受信任或未經過身份驗證的資料,請參閱 XML 漏洞

可用性:非 WASI。

此模組在 WebAssembly 上無法工作或不可用。有關更多資訊,請參閱 WebAssembly 平臺

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 引數生效。

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 引數為 true,並且例項沒有 _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('https://: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("https://: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 獨立執行,也可以使用 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

建立新的請求處理程式例項。此請求處理程式支援 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 文件中使用的描述。此描述將作為段落出現在文件中的伺服器名稱下方。