xmlrpc.client — XML-RPC client access

Вихідний код: Lib/xmlrpc/client.py


XML-RPC — це метод віддаленого виклику процедури, який використовує XML, що передається через HTTP(S) як транспорт. З його допомогою клієнт може викликати методи з параметрами на віддаленому сервері (сервер має назву URI) і отримати назад структуровані дані. Цей модуль підтримує написання клієнтського коду XML-RPC; він обробляє всі деталі перекладу між відповідними об’єктами Python і XML на дроті.

Попередження

Модуль xmlrpc.client не захищений від зловмисно створених даних. Якщо вам потрібно проаналізувати ненадійні або неавтентифіковані дані, перегляньте Уразливості XML.

Змінено в версії 3.5: Для HTTPS URI xmlrpc.client тепер виконує всі необхідні перевірки сертифікатів і імен хостів за умовчанням.

Availability: not WASI.

This module does not work or is not available on WebAssembly. See WebAssembly platforms for more information.

class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None)

Екземпляр ServerProxy — це об’єкт, який керує зв’язком із віддаленим сервером XML-RPC. Обов’язковим першим аргументом є URI (уніфікований індикатор ресурсу), і зазвичай це URL-адреса сервера. Необов’язковий другий аргумент - екземпляр транспортної фабрики; за замовчуванням це внутрішній екземпляр SafeTransport для https: URL-адрес і внутрішній екземпляр HTTP Transport в інших випадках. Необов’язковий третій аргумент – це кодування, за умовчанням UTF-8. Необов’язковий четвертий аргумент - це позначка налагодження.

The following parameters govern the use of the returned proxy instance. If allow_none is true, the Python constant None will be translated into XML; the default behaviour is for None to raise a TypeError. This is a commonly used extension to the XML-RPC specification, but isn’t supported by all clients and servers; see http://ontosys.com/xml-rpc/extensions.php for a description. The use_builtin_types flag can be used to cause date/time values to be presented as datetime.datetime objects and binary data to be presented as bytes objects; this flag is false by default. datetime.datetime, bytes and bytearray objects may be passed to calls. The headers parameter is an optional sequence of HTTP headers to send with each request, expressed as a sequence of 2-tuples representing the header name and value. (e.g. [('Header-Name', 'value')]). If an HTTPS URL is provided, context may be ssl.SSLContext and configures the SSL settings of the underlying HTTPS connection. The obsolete use_datetime flag is similar to use_builtin_types but it applies only to date/time values.

Змінено в версії 3.3: Додано прапорець use_builtin_types.

Змінено в версії 3.8: Додано параметр headers.

Both the HTTP and HTTPS transports support the URL syntax extension for HTTP Basic Authentication: http://user:pass@host:port/path. The user:pass portion will be base64-encoded as an HTTP „Authorization“ header, and sent to the remote server as part of the connection process when invoking an XML-RPC method. You only need to use this if the remote server requires a Basic Authentication user and password.

Повернений екземпляр — це проксі-об’єкт із методами, які можна використовувати для виклику відповідних викликів RPC на віддаленому сервері. Якщо віддалений сервер підтримує API інтроспекції, проксі також можна використовувати для запиту віддаленого сервера щодо методів, які він підтримує (виявлення служби), і отримання інших пов’язаних із сервером метаданих.

Типи, які є сумісними (наприклад, які можна маршалізувати через XML), включають наступне (і, якщо не зазначено, вони не маршалізуються як той самий тип Python):

Тип XML-RPC

Тип Python

логічний

bool

int, i1, i2, i4, i8 або biginteger

int в діапазоні від -2147483648 до 2147483647. Значення отримують тег <int>.

double або float

float. Значення отримують тег <double>.

рядок

str

array

list або tuple, що містять відповідні елементи. Масиви повертаються як lists.

структура

dict. Ключі мають бути рядками, значення можуть мати будь-який відповідний тип. Можна передати об’єкти визначених користувачем класів; передається лише їхній атрибут __dict__.

dateTime.iso8601

DateTime або datetime.datetime. Повернений тип залежить від значень прапорців use_builtin_types і use_datetime.

base64

Binary, bytes або bytearray. Повернений тип залежить від значення прапорця use_builtin_types.

нуль

Константа None. Передача дозволена, лише якщо allow_none має значення true.

великий десятковий

decimal.Decimal. Тільки повернутий тип.

Це повний набір типів даних, які підтримує XML-RPC. Виклики методів також можуть викликати спеціальний екземпляр Fault, який використовується для сигналізації про помилки сервера XML-RPC, або ProtocolError, який використовується для сигналізації про помилку на транспортному рівні HTTP/HTTPS. І Fault, і ProtocolError походять від базового класу під назвою Error. Зауважте, що клієнтський модуль xmlrpc наразі не маршалює екземпляри підкласів вбудованих типів.

Під час передачі рядків спеціальні символи XML, такі як <, > і &, будуть автоматично екрановані. Однак відповідальністю абонента є переконатися, що рядок вільний від символів, які не дозволені в XML, таких як контрольні символи зі значеннями ASCII від 0 до 31 (за винятком, звичайно, табуляції, нового рядка та повернення каретки); якщо цього не зробити, запит XML-RPC не є правильно сформованим XML. Якщо вам потрібно передати довільні байти через XML-RPC, використовуйте класи bytes або bytearray або клас-оболонку Binary, описаний нижче.

Server зберігається як псевдонім для ServerProxy для зворотної сумісності. Новий код має використовувати ServerProxy.

Змінено в версії 3.5: Додано аргумент контекст.

Змінено в версії 3.6: Added support of type tags with prefixes (e.g. ex:nil). Added support of unmarshalling additional types used by Apache XML-RPC implementation for numerics: i1, i2, i8, biginteger, float and bigdecimal. See https://ws.apache.org/xmlrpc/types.html for a description.

Дивись також

XML-RPC HOWTO

Гарний опис роботи XML-RPC і клієнтського програмного забезпечення кількома мовами. Містить практично все, що потрібно знати розробнику клієнта XML-RPC.

XML-RPC Introspection

Описує розширення протоколу XML-RPC для самоаналізу.

Специфікація XML-RPC

Офіційна специфікація.

Об’єкти ServerProxy

Екземпляр ServerProxy має метод, що відповідає кожному виклику віддаленої процедури, прийнятому сервером XML-RPC. Виклик методу виконує RPC, відправляється як за назвою, так і за підписом аргументу (наприклад, те саме ім’я методу може бути перевантажено декількома підписами аргументів). RPC завершується поверненням значення, яке може бути або повернутими даними відповідного типу, або об’єктом Fault чи ProtocolError, що вказує на помилку.

Сервери, які підтримують API інтроспекції XML, підтримують деякі загальні методи, згруповані в зарезервованому атрибуті system:

ServerProxy.system.listMethods()

Цей метод повертає список рядків, по одному для кожного (несистемного) методу, який підтримує сервер XML-RPC.

ServerProxy.system.methodSignature(name)

Цей метод приймає один параметр, назву методу, реалізованого сервером XML-RPC. Він повертає масив можливих підписів для цього методу. Підпис — це масив типів. Перший із цих типів є типом повернення методу, решта є параметрами.

Оскільки дозволено кілька підписів (тобто перевантаження), цей метод повертає список підписів, а не одиночний.

Самі підписи обмежені параметрами верхнього рівня, очікуваними методом. Наприклад, якщо метод очікує один масив структур як параметр і повертає рядок, його підпис буде просто «рядок, масив». Якщо він очікує три цілі числа та повертає рядок, його підписом є «рядок, int, int, int».

Якщо для методу не визначено підпису, повертається немасивне значення. У Python це означає, що типом поверненого значення буде щось інше, ніж список.

ServerProxy.system.methodHelp(name)

Цей метод приймає один параметр, назву методу, реалізованого сервером XML-RPC. Він повертає рядок документації, що описує використання цього методу. Якщо такий рядок недоступний, повертається порожній рядок. Рядок документації може містити розмітку HTML.

Змінено в версії 3.5: Екземпляри ServerProxy підтримують протокол context manager для закриття основного транспорту.

Нижче наведено робочий приклад. Код сервера:

from xmlrpc.server import SimpleXMLRPCServer

def is_even(n):
    return n % 2 == 0

server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(is_even, "is_even")
server.serve_forever()

Код клієнта для попереднього сервера:

import xmlrpc.client

with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
    print("3 is even: %s" % str(proxy.is_even(3)))
    print("100 is even: %s" % str(proxy.is_even(100)))

Об’єкти DateTime

class xmlrpc.client.DateTime

Цей клас може бути ініціалізований секундами з епохи, кортежем часу, рядком часу/дати ISO 8601 або екземпляром datetime.datetime. Він має такі методи, які підтримуються головним чином для внутрішнього використання кодом маршалінгу/демаршалінгу:

decode(string)

Прийняти рядок як нове значення часу екземпляра.

encode(out)

Запишіть кодування XML-RPC цього елемента DateTime в об’єкт потоку out.

It also supports certain of Python’s built-in operators through rich comparison and __repr__() methods.

Нижче наведено робочий приклад. Код сервера:

import datetime
from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client

def today():
    today = datetime.datetime.today()
    return xmlrpc.client.DateTime(today)

server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(today, "today")
server.serve_forever()

Код клієнта для попереднього сервера:

import xmlrpc.client
import datetime

proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")

today = proxy.today()
# convert the ISO8601 string to a datetime object
converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M"))

Двійкові об’єкти

class xmlrpc.client.Binary

Цей клас може бути ініціалізований з даних байтів (які можуть включати NUL). Основний доступ до вмісту об’єкта Binary забезпечується атрибутом:

data

Двійкові дані, інкапсульовані екземпляром Binary. Дані надаються як об’єкт bytes.

Binary об’єкти мають такі методи, які підтримуються переважно для внутрішнього використання кодом маршалінгу/демаршалінгу:

decode(bytes)

Прийміть об’єкт base64 bytes і декодуйте його як нові дані екземпляра.

encode(out)

Запишіть кодування XML-RPC base 64 цього бінарного елемента в об’єкт потоку out.

Закодовані дані матимуть символи нового рядка через кожні 76 символів відповідно до RFC 2045, розділ 6.8, який був де-факто стандартною специфікацією base64 на момент написання специфікації XML-RPC.

It also supports certain of Python’s built-in operators through __eq__() and __ne__() methods.

Приклад використання бінарних об’єктів. Ми збираємося передати зображення через XMLRPC:

from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client

def python_logo():
    with open("python_logo.jpg", "rb") as handle:
        return xmlrpc.client.Binary(handle.read())

server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(python_logo, 'python_logo')

server.serve_forever()

Клієнт отримує зображення та зберігає його у файл:

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
with open("fetched_python_logo.jpg", "wb") as handle:
    handle.write(proxy.python_logo().data)

Об’єкти несправності

class xmlrpc.client.Fault

Об’єкт Fault інкапсулює вміст тегу помилки XML-RPC. Об’єкти несправностей мають такі атрибути:

faultCode

Int, що вказує на тип помилки.

faultString

Рядок, що містить діагностичне повідомлення, пов’язане з несправністю.

У наступному прикладі ми навмисно спричинимо Fault, повернувши об’єкт складного типу. Код сервера:

from xmlrpc.server import SimpleXMLRPCServer

# A marshalling error is going to occur because we're returning a
# complex number
def add(x, y):
    return x+y+0j

server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(add, 'add')

server.serve_forever()

Код клієнта для попереднього сервера:

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
try:
    proxy.add(2, 5)
except xmlrpc.client.Fault as err:
    print("A fault occurred")
    print("Fault code: %d" % err.faultCode)
    print("Fault string: %s" % err.faultString)

Об’єкти ProtocolError

class xmlrpc.client.ProtocolError

Об’єкт ProtocolError описує помилку протоколу на базовому транспортному рівні (наприклад, помилку 404 «не знайдено», якщо сервер, названий URI, не існує). Він має такі атрибути:

url

URI або URL-адреса, яка викликала помилку.

errcode

Код помилки.

errmsg

Повідомлення про помилку або діагностичний рядок.

headers

Dict, що містить заголовки запиту HTTP/HTTPS, який викликав помилку.

У наступному прикладі ми навмисно спричинимо ProtocolError, вказавши недійсний URI:

import xmlrpc.client

# create a ServerProxy with a URI that doesn't respond to XMLRPC requests
proxy = xmlrpc.client.ServerProxy("http://google.com/")

try:
    proxy.some_method()
except xmlrpc.client.ProtocolError as err:
    print("A protocol error occurred")
    print("URL: %s" % err.url)
    print("HTTP/HTTPS headers: %s" % err.headers)
    print("Error code: %d" % err.errcode)
    print("Error message: %s" % err.errmsg)

Об’єкти MultiCall

Об’єкт MultiCall забезпечує спосіб інкапсулювати кілька викликів до віддаленого сервера в один запит [1].

class xmlrpc.client.MultiCall(server)

Створіть об’єкт, який використовується для викликів методу boxcar. сервер є кінцевою метою виклику. Виклики можна здійснювати до об’єкта результату, але вони негайно повертатимуть None і зберігають лише назву виклику та параметри в об’єкті MultiCall. Виклик самого об’єкта призводить до того, що всі збережені виклики передаються як єдиний запит system.multicall. Результатом цього виклику є generator; ітерація по цьому генератору дає окремі результати.

Нижче наведено приклад використання цього класу. Код сервера:

from xmlrpc.server import SimpleXMLRPCServer

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    return x // y

# A simple server with simple arithmetic functions
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_multicall_functions()
server.register_function(add, 'add')
server.register_function(subtract, 'subtract')
server.register_function(multiply, 'multiply')
server.register_function(divide, 'divide')
server.serve_forever()

Код клієнта для попереднього сервера:

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
multicall = xmlrpc.client.MultiCall(proxy)
multicall.add(7, 3)
multicall.subtract(7, 3)
multicall.multiply(7, 3)
multicall.divide(7, 3)
result = multicall()

print("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))

Функції зручності

xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)

Перетворіть params на запит XML-RPC. або у відповідь, якщо methodresponse має значення true. params може бути або кортежем аргументів, або екземпляром класу винятків Fault. Якщо methodresponse має значення true, можна повернути лише одне значення, тобто params має мати довжину 1. encoding, якщо вказано, це кодування, яке буде використовуватися у створеному XML; типовим є UTF-8. Значення Python None не можна використовувати в стандартному XML-RPC; щоб дозволити використовувати його через розширення, надайте справжнє значення allow_none.

xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)

Перетворення запиту чи відповіді XML-RPC на об’єкти Python, (params, methodname). params — це кортеж аргументів; methodname — це рядок або None, якщо в пакеті немає імені методу. Якщо пакет XML-RPC представляє стан помилки, ця функція викличе виняток Fault. Прапор use_builtin_types можна використовувати, щоб значення дати/часу відображалися як об’єкти datetime.datetime, а двійкові дані — як об’єкти bytes; цей прапор за замовчуванням false.

Застарілий прапор use_datetime подібний до use_builtin_types, але він застосовується лише до значень дати/часу.

Змінено в версії 3.3: Додано прапорець use_builtin_types.

Приклад використання клієнта

# simple test program (from the XML-RPC specification)
from xmlrpc.client import ServerProxy, Error

# server = ServerProxy("http://localhost:8000") # local server
with ServerProxy("http://betty.userland.com") as proxy:

    print(proxy)

    try:
        print(proxy.examples.getStateName(41))
    except Error as v:
        print("ERROR", v)

Щоб отримати доступ до сервера XML-RPC через проксі-сервер HTTP, вам потрібно визначити настроюваний транспорт. У наступному прикладі показано, як:

import http.client
import xmlrpc.client

class ProxiedTransport(xmlrpc.client.Transport):

    def set_proxy(self, host, port=None, headers=None):
        self.proxy = host, port
        self.proxy_headers = headers

    def make_connection(self, host):
        connection = http.client.HTTPConnection(*self.proxy)
        connection.set_tunnel(host, headers=self.proxy_headers)
        self._connection = host, connection
        return connection

transport = ProxiedTransport()
transport.set_proxy('proxy-server', 8080)
server = xmlrpc.client.ServerProxy('http://betty.userland.com', transport=transport)
print(server.examples.getStateName(41))

Приклад використання клієнта та сервера

Див. Приклад SimpleXMLRPCServer.

Виноски