| [2] | 1 | :mod:`xmlrpclib` --- XML-RPC client access
|
|---|
| 2 | ==========================================
|
|---|
| 3 |
|
|---|
| 4 | .. module:: xmlrpclib
|
|---|
| 5 | :synopsis: XML-RPC client access.
|
|---|
| 6 | .. moduleauthor:: Fredrik Lundh <fredrik@pythonware.com>
|
|---|
| 7 | .. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
|
|---|
| 8 |
|
|---|
| 9 | .. note::
|
|---|
| 10 | The :mod:`xmlrpclib` module has been renamed to :mod:`xmlrpc.client` in
|
|---|
| [391] | 11 | Python 3. The :term:`2to3` tool will automatically adapt imports when
|
|---|
| 12 | converting your sources to Python 3.
|
|---|
| [2] | 13 |
|
|---|
| 14 |
|
|---|
| 15 | .. XXX Not everything is documented yet. It might be good to describe
|
|---|
| 16 | Marshaller, Unmarshaller, getparser, dumps, loads, and Transport.
|
|---|
| 17 |
|
|---|
| 18 | .. versionadded:: 2.2
|
|---|
| 19 |
|
|---|
| [391] | 20 | **Source code:** :source:`Lib/xmlrpclib.py`
|
|---|
| 21 |
|
|---|
| 22 | --------------
|
|---|
| 23 |
|
|---|
| [2] | 24 | XML-RPC is a Remote Procedure Call method that uses XML passed via HTTP as a
|
|---|
| 25 | transport. With it, a client can call methods with parameters on a remote
|
|---|
| 26 | server (the server is named by a URI) and get back structured data. This module
|
|---|
| 27 | supports writing XML-RPC client code; it handles all the details of translating
|
|---|
| 28 | between conformable Python objects and XML on the wire.
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| [391] | 31 | .. warning::
|
|---|
| 32 |
|
|---|
| 33 | The :mod:`xmlrpclib` module is not secure against maliciously
|
|---|
| 34 | constructed data. If you need to parse untrusted or unauthenticated data see
|
|---|
| 35 | :ref:`xml-vulnerabilities`.
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| [2] | 38 | .. class:: ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime]]]]])
|
|---|
| 39 |
|
|---|
| 40 | A :class:`ServerProxy` instance is an object that manages communication with a
|
|---|
| 41 | remote XML-RPC server. The required first argument is a URI (Uniform Resource
|
|---|
| 42 | Indicator), and will normally be the URL of the server. The optional second
|
|---|
| 43 | argument is a transport factory instance; by default it is an internal
|
|---|
| 44 | :class:`SafeTransport` instance for https: URLs and an internal HTTP
|
|---|
| 45 | :class:`Transport` instance otherwise. The optional third argument is an
|
|---|
| 46 | encoding, by default UTF-8. The optional fourth argument is a debugging flag.
|
|---|
| 47 | If *allow_none* is true, the Python constant ``None`` will be translated into
|
|---|
| 48 | XML; the default behaviour is for ``None`` to raise a :exc:`TypeError`. This is
|
|---|
| 49 | a commonly-used extension to the XML-RPC specification, but isn't supported by
|
|---|
| 50 | all clients and servers; see http://ontosys.com/xml-rpc/extensions.php for a
|
|---|
| 51 | description. The *use_datetime* flag can be used to cause date/time values to
|
|---|
| 52 | be presented as :class:`datetime.datetime` objects; this is false by default.
|
|---|
| 53 | :class:`datetime.datetime` objects may be passed to calls.
|
|---|
| 54 |
|
|---|
| 55 | Both the HTTP and HTTPS transports support the URL syntax extension for HTTP
|
|---|
| 56 | Basic Authentication: ``http://user:pass@host:port/path``. The ``user:pass``
|
|---|
| 57 | portion will be base64-encoded as an HTTP 'Authorization' header, and sent to
|
|---|
| 58 | the remote server as part of the connection process when invoking an XML-RPC
|
|---|
| 59 | method. You only need to use this if the remote server requires a Basic
|
|---|
| 60 | Authentication user and password.
|
|---|
| 61 |
|
|---|
| 62 | The returned instance is a proxy object with methods that can be used to invoke
|
|---|
| 63 | corresponding RPC calls on the remote server. If the remote server supports the
|
|---|
| 64 | introspection API, the proxy can also be used to query the remote server for the
|
|---|
| 65 | methods it supports (service discovery) and fetch other server-associated
|
|---|
| 66 | metadata.
|
|---|
| 67 |
|
|---|
| 68 | :class:`ServerProxy` instance methods take Python basic types and objects as
|
|---|
| 69 | arguments and return Python basic types and classes. Types that are conformable
|
|---|
| 70 | (e.g. that can be marshalled through XML), include the following (and except
|
|---|
| 71 | where noted, they are unmarshalled as the same Python type):
|
|---|
| 72 |
|
|---|
| 73 | +---------------------------------+---------------------------------------------+
|
|---|
| 74 | | Name | Meaning |
|
|---|
| 75 | +=================================+=============================================+
|
|---|
| 76 | | :const:`boolean` | The :const:`True` and :const:`False` |
|
|---|
| 77 | | | constants |
|
|---|
| 78 | +---------------------------------+---------------------------------------------+
|
|---|
| 79 | | :const:`integers` | Pass in directly |
|
|---|
| 80 | +---------------------------------+---------------------------------------------+
|
|---|
| 81 | | :const:`floating-point numbers` | Pass in directly |
|
|---|
| 82 | +---------------------------------+---------------------------------------------+
|
|---|
| 83 | | :const:`strings` | Pass in directly |
|
|---|
| 84 | +---------------------------------+---------------------------------------------+
|
|---|
| 85 | | :const:`arrays` | Any Python sequence type containing |
|
|---|
| 86 | | | conformable elements. Arrays are returned |
|
|---|
| 87 | | | as lists |
|
|---|
| 88 | +---------------------------------+---------------------------------------------+
|
|---|
| 89 | | :const:`structures` | A Python dictionary. Keys must be strings, |
|
|---|
| 90 | | | values may be any conformable type. Objects |
|
|---|
| 91 | | | of user-defined classes can be passed in; |
|
|---|
| 92 | | | only their *__dict__* attribute is |
|
|---|
| 93 | | | transmitted. |
|
|---|
| 94 | +---------------------------------+---------------------------------------------+
|
|---|
| 95 | | :const:`dates` | in seconds since the epoch (pass in an |
|
|---|
| 96 | | | instance of the :class:`DateTime` class) or |
|
|---|
| 97 | | | a :class:`datetime.datetime` instance. |
|
|---|
| 98 | +---------------------------------+---------------------------------------------+
|
|---|
| 99 | | :const:`binary data` | pass in an instance of the :class:`Binary` |
|
|---|
| 100 | | | wrapper class |
|
|---|
| 101 | +---------------------------------+---------------------------------------------+
|
|---|
| 102 |
|
|---|
| 103 | This is the full set of data types supported by XML-RPC. Method calls may also
|
|---|
| 104 | raise a special :exc:`Fault` instance, used to signal XML-RPC server errors, or
|
|---|
| 105 | :exc:`ProtocolError` used to signal an error in the HTTP/HTTPS transport layer.
|
|---|
| 106 | Both :exc:`Fault` and :exc:`ProtocolError` derive from a base class called
|
|---|
| 107 | :exc:`Error`. Note that even though starting with Python 2.2 you can subclass
|
|---|
| 108 | built-in types, the xmlrpclib module currently does not marshal instances of such
|
|---|
| 109 | subclasses.
|
|---|
| 110 |
|
|---|
| 111 | When passing strings, characters special to XML such as ``<``, ``>``, and ``&``
|
|---|
| 112 | will be automatically escaped. However, it's the caller's responsibility to
|
|---|
| 113 | ensure that the string is free of characters that aren't allowed in XML, such as
|
|---|
| 114 | the control characters with ASCII values between 0 and 31 (except, of course,
|
|---|
| 115 | tab, newline and carriage return); failing to do this will result in an XML-RPC
|
|---|
| 116 | request that isn't well-formed XML. If you have to pass arbitrary strings via
|
|---|
| 117 | XML-RPC, use the :class:`Binary` wrapper class described below.
|
|---|
| 118 |
|
|---|
| 119 | :class:`Server` is retained as an alias for :class:`ServerProxy` for backwards
|
|---|
| 120 | compatibility. New code should use :class:`ServerProxy`.
|
|---|
| 121 |
|
|---|
| 122 | .. versionchanged:: 2.5
|
|---|
| 123 | The *use_datetime* flag was added.
|
|---|
| 124 |
|
|---|
| 125 | .. versionchanged:: 2.6
|
|---|
| 126 | Instances of :term:`new-style class`\es can be passed in if they have an
|
|---|
| 127 | *__dict__* attribute and don't have a base class that is marshalled in a
|
|---|
| 128 | special way.
|
|---|
| 129 |
|
|---|
| 130 |
|
|---|
| 131 | .. seealso::
|
|---|
| 132 |
|
|---|
| 133 | `XML-RPC HOWTO <http://www.tldp.org/HOWTO/XML-RPC-HOWTO/index.html>`_
|
|---|
| 134 | A good description of XML-RPC operation and client software in several languages.
|
|---|
| 135 | Contains pretty much everything an XML-RPC client developer needs to know.
|
|---|
| 136 |
|
|---|
| 137 | `XML-RPC Introspection <http://xmlrpc-c.sourceforge.net/introspection.html>`_
|
|---|
| 138 | Describes the XML-RPC protocol extension for introspection.
|
|---|
| 139 |
|
|---|
| 140 | `XML-RPC Specification <http://www.xmlrpc.com/spec>`_
|
|---|
| 141 | The official specification.
|
|---|
| 142 |
|
|---|
| 143 | `Unofficial XML-RPC Errata <http://effbot.org/zone/xmlrpc-errata.htm>`_
|
|---|
| 144 | Fredrik Lundh's "unofficial errata, intended to clarify certain
|
|---|
| 145 | details in the XML-RPC specification, as well as hint at
|
|---|
| 146 | 'best practices' to use when designing your own XML-RPC
|
|---|
| 147 | implementations."
|
|---|
| 148 |
|
|---|
| 149 | .. _serverproxy-objects:
|
|---|
| 150 |
|
|---|
| 151 | ServerProxy Objects
|
|---|
| 152 | -------------------
|
|---|
| 153 |
|
|---|
| 154 | A :class:`ServerProxy` instance has a method corresponding to each remote
|
|---|
| 155 | procedure call accepted by the XML-RPC server. Calling the method performs an
|
|---|
| 156 | RPC, dispatched by both name and argument signature (e.g. the same method name
|
|---|
| 157 | can be overloaded with multiple argument signatures). The RPC finishes by
|
|---|
| 158 | returning a value, which may be either returned data in a conformant type or a
|
|---|
| 159 | :class:`Fault` or :class:`ProtocolError` object indicating an error.
|
|---|
| 160 |
|
|---|
| 161 | Servers that support the XML introspection API support some common methods
|
|---|
| [391] | 162 | grouped under the reserved :attr:`system` attribute:
|
|---|
| [2] | 163 |
|
|---|
| 164 |
|
|---|
| 165 | .. method:: ServerProxy.system.listMethods()
|
|---|
| 166 |
|
|---|
| 167 | This method returns a list of strings, one for each (non-system) method
|
|---|
| 168 | supported by the XML-RPC server.
|
|---|
| 169 |
|
|---|
| 170 |
|
|---|
| 171 | .. method:: ServerProxy.system.methodSignature(name)
|
|---|
| 172 |
|
|---|
| 173 | This method takes one parameter, the name of a method implemented by the XML-RPC
|
|---|
| 174 | server. It returns an array of possible signatures for this method. A signature
|
|---|
| 175 | is an array of types. The first of these types is the return type of the method,
|
|---|
| 176 | the rest are parameters.
|
|---|
| 177 |
|
|---|
| 178 | Because multiple signatures (ie. overloading) is permitted, this method returns
|
|---|
| 179 | a list of signatures rather than a singleton.
|
|---|
| 180 |
|
|---|
| 181 | Signatures themselves are restricted to the top level parameters expected by a
|
|---|
| 182 | method. For instance if a method expects one array of structs as a parameter,
|
|---|
| 183 | and it returns a string, its signature is simply "string, array". If it expects
|
|---|
| 184 | three integers and returns a string, its signature is "string, int, int, int".
|
|---|
| 185 |
|
|---|
| 186 | If no signature is defined for the method, a non-array value is returned. In
|
|---|
| 187 | Python this means that the type of the returned value will be something other
|
|---|
| 188 | than list.
|
|---|
| 189 |
|
|---|
| 190 |
|
|---|
| 191 | .. method:: ServerProxy.system.methodHelp(name)
|
|---|
| 192 |
|
|---|
| 193 | This method takes one parameter, the name of a method implemented by the XML-RPC
|
|---|
| 194 | server. It returns a documentation string describing the use of that method. If
|
|---|
| 195 | no such string is available, an empty string is returned. The documentation
|
|---|
| 196 | string may contain HTML markup.
|
|---|
| 197 |
|
|---|
| 198 |
|
|---|
| 199 | .. _boolean-objects:
|
|---|
| 200 |
|
|---|
| 201 | Boolean Objects
|
|---|
| 202 | ---------------
|
|---|
| 203 |
|
|---|
| 204 | This class may be initialized from any Python value; the instance returned
|
|---|
| 205 | depends only on its truth value. It supports various Python operators through
|
|---|
| 206 | :meth:`__cmp__`, :meth:`__repr__`, :meth:`__int__`, and :meth:`__nonzero__`
|
|---|
| 207 | methods, all implemented in the obvious ways.
|
|---|
| 208 |
|
|---|
| 209 | It also has the following method, supported mainly for internal use by the
|
|---|
| 210 | unmarshalling code:
|
|---|
| 211 |
|
|---|
| 212 |
|
|---|
| 213 | .. method:: Boolean.encode(out)
|
|---|
| 214 |
|
|---|
| 215 | Write the XML-RPC encoding of this Boolean item to the out stream object.
|
|---|
| 216 |
|
|---|
| 217 | A working example follows. The server code::
|
|---|
| 218 |
|
|---|
| 219 | import xmlrpclib
|
|---|
| 220 | from SimpleXMLRPCServer import SimpleXMLRPCServer
|
|---|
| 221 |
|
|---|
| 222 | def is_even(n):
|
|---|
| 223 | return n%2 == 0
|
|---|
| 224 |
|
|---|
| 225 | server = SimpleXMLRPCServer(("localhost", 8000))
|
|---|
| 226 | print "Listening on port 8000..."
|
|---|
| 227 | server.register_function(is_even, "is_even")
|
|---|
| 228 | server.serve_forever()
|
|---|
| 229 |
|
|---|
| 230 | The client code for the preceding server::
|
|---|
| 231 |
|
|---|
| 232 | import xmlrpclib
|
|---|
| 233 |
|
|---|
| 234 | proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
|
|---|
| 235 | print "3 is even: %s" % str(proxy.is_even(3))
|
|---|
| 236 | print "100 is even: %s" % str(proxy.is_even(100))
|
|---|
| 237 |
|
|---|
| 238 | .. _datetime-objects:
|
|---|
| 239 |
|
|---|
| 240 | DateTime Objects
|
|---|
| 241 | ----------------
|
|---|
| 242 |
|
|---|
| 243 | This class may be initialized with seconds since the epoch, a time
|
|---|
| 244 | tuple, an ISO 8601 time/date string, or a :class:`datetime.datetime`
|
|---|
| 245 | instance. It has the following methods, supported mainly for internal
|
|---|
| 246 | use by the marshalling/unmarshalling code:
|
|---|
| 247 |
|
|---|
| 248 |
|
|---|
| 249 | .. method:: DateTime.decode(string)
|
|---|
| 250 |
|
|---|
| 251 | Accept a string as the instance's new time value.
|
|---|
| 252 |
|
|---|
| 253 |
|
|---|
| 254 | .. method:: DateTime.encode(out)
|
|---|
| 255 |
|
|---|
| 256 | Write the XML-RPC encoding of this :class:`DateTime` item to the *out* stream
|
|---|
| 257 | object.
|
|---|
| 258 |
|
|---|
| 259 | It also supports certain of Python's built-in operators through :meth:`__cmp__`
|
|---|
| 260 | and :meth:`__repr__` methods.
|
|---|
| 261 |
|
|---|
| 262 | A working example follows. The server code::
|
|---|
| 263 |
|
|---|
| 264 | import datetime
|
|---|
| 265 | from SimpleXMLRPCServer import SimpleXMLRPCServer
|
|---|
| 266 | import xmlrpclib
|
|---|
| 267 |
|
|---|
| 268 | def today():
|
|---|
| 269 | today = datetime.datetime.today()
|
|---|
| 270 | return xmlrpclib.DateTime(today)
|
|---|
| 271 |
|
|---|
| 272 | server = SimpleXMLRPCServer(("localhost", 8000))
|
|---|
| 273 | print "Listening on port 8000..."
|
|---|
| 274 | server.register_function(today, "today")
|
|---|
| 275 | server.serve_forever()
|
|---|
| 276 |
|
|---|
| 277 | The client code for the preceding server::
|
|---|
| 278 |
|
|---|
| 279 | import xmlrpclib
|
|---|
| 280 | import datetime
|
|---|
| 281 |
|
|---|
| 282 | proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
|
|---|
| 283 |
|
|---|
| 284 | today = proxy.today()
|
|---|
| 285 | # convert the ISO8601 string to a datetime object
|
|---|
| 286 | converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
|
|---|
| 287 | print "Today: %s" % converted.strftime("%d.%m.%Y, %H:%M")
|
|---|
| 288 |
|
|---|
| 289 | .. _binary-objects:
|
|---|
| 290 |
|
|---|
| 291 | Binary Objects
|
|---|
| 292 | --------------
|
|---|
| 293 |
|
|---|
| 294 | This class may be initialized from string data (which may include NULs). The
|
|---|
| 295 | primary access to the content of a :class:`Binary` object is provided by an
|
|---|
| 296 | attribute:
|
|---|
| 297 |
|
|---|
| 298 |
|
|---|
| 299 | .. attribute:: Binary.data
|
|---|
| 300 |
|
|---|
| 301 | The binary data encapsulated by the :class:`Binary` instance. The data is
|
|---|
| 302 | provided as an 8-bit string.
|
|---|
| 303 |
|
|---|
| 304 | :class:`Binary` objects have the following methods, supported mainly for
|
|---|
| 305 | internal use by the marshalling/unmarshalling code:
|
|---|
| 306 |
|
|---|
| 307 |
|
|---|
| 308 | .. method:: Binary.decode(string)
|
|---|
| 309 |
|
|---|
| 310 | Accept a base64 string and decode it as the instance's new data.
|
|---|
| 311 |
|
|---|
| 312 |
|
|---|
| 313 | .. method:: Binary.encode(out)
|
|---|
| 314 |
|
|---|
| 315 | Write the XML-RPC base 64 encoding of this binary item to the out stream object.
|
|---|
| 316 |
|
|---|
| 317 | The encoded data will have newlines every 76 characters as per
|
|---|
| 318 | `RFC 2045 section 6.8 <http://tools.ietf.org/html/rfc2045#section-6.8>`_,
|
|---|
| 319 | which was the de facto standard base64 specification when the
|
|---|
| 320 | XML-RPC spec was written.
|
|---|
| 321 |
|
|---|
| 322 | It also supports certain of Python's built-in operators through a
|
|---|
| 323 | :meth:`__cmp__` method.
|
|---|
| 324 |
|
|---|
| 325 | Example usage of the binary objects. We're going to transfer an image over
|
|---|
| 326 | XMLRPC::
|
|---|
| 327 |
|
|---|
| 328 | from SimpleXMLRPCServer import SimpleXMLRPCServer
|
|---|
| 329 | import xmlrpclib
|
|---|
| 330 |
|
|---|
| 331 | def python_logo():
|
|---|
| 332 | with open("python_logo.jpg", "rb") as handle:
|
|---|
| 333 | return xmlrpclib.Binary(handle.read())
|
|---|
| 334 |
|
|---|
| 335 | server = SimpleXMLRPCServer(("localhost", 8000))
|
|---|
| 336 | print "Listening on port 8000..."
|
|---|
| 337 | server.register_function(python_logo, 'python_logo')
|
|---|
| 338 |
|
|---|
| 339 | server.serve_forever()
|
|---|
| 340 |
|
|---|
| 341 | The client gets the image and saves it to a file::
|
|---|
| 342 |
|
|---|
| 343 | import xmlrpclib
|
|---|
| 344 |
|
|---|
| 345 | proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
|
|---|
| 346 | with open("fetched_python_logo.jpg", "wb") as handle:
|
|---|
| 347 | handle.write(proxy.python_logo().data)
|
|---|
| 348 |
|
|---|
| 349 | .. _fault-objects:
|
|---|
| 350 |
|
|---|
| 351 | Fault Objects
|
|---|
| 352 | -------------
|
|---|
| 353 |
|
|---|
| 354 | A :class:`Fault` object encapsulates the content of an XML-RPC fault tag. Fault
|
|---|
| [391] | 355 | objects have the following attributes:
|
|---|
| [2] | 356 |
|
|---|
| 357 |
|
|---|
| 358 | .. attribute:: Fault.faultCode
|
|---|
| 359 |
|
|---|
| 360 | A string indicating the fault type.
|
|---|
| 361 |
|
|---|
| 362 |
|
|---|
| 363 | .. attribute:: Fault.faultString
|
|---|
| 364 |
|
|---|
| 365 | A string containing a diagnostic message associated with the fault.
|
|---|
| 366 |
|
|---|
| 367 | In the following example we're going to intentionally cause a :exc:`Fault` by
|
|---|
| 368 | returning a complex type object. The server code::
|
|---|
| 369 |
|
|---|
| 370 | from SimpleXMLRPCServer import SimpleXMLRPCServer
|
|---|
| 371 |
|
|---|
| 372 | # A marshalling error is going to occur because we're returning a
|
|---|
| 373 | # complex number
|
|---|
| 374 | def add(x,y):
|
|---|
| 375 | return x+y+0j
|
|---|
| 376 |
|
|---|
| 377 | server = SimpleXMLRPCServer(("localhost", 8000))
|
|---|
| 378 | print "Listening on port 8000..."
|
|---|
| 379 | server.register_function(add, 'add')
|
|---|
| 380 |
|
|---|
| 381 | server.serve_forever()
|
|---|
| 382 |
|
|---|
| 383 | The client code for the preceding server::
|
|---|
| 384 |
|
|---|
| 385 | import xmlrpclib
|
|---|
| 386 |
|
|---|
| 387 | proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
|
|---|
| 388 | try:
|
|---|
| 389 | proxy.add(2, 5)
|
|---|
| [391] | 390 | except xmlrpclib.Fault as err:
|
|---|
| [2] | 391 | print "A fault occurred"
|
|---|
| 392 | print "Fault code: %d" % err.faultCode
|
|---|
| 393 | print "Fault string: %s" % err.faultString
|
|---|
| 394 |
|
|---|
| 395 |
|
|---|
| 396 |
|
|---|
| 397 | .. _protocol-error-objects:
|
|---|
| 398 |
|
|---|
| 399 | ProtocolError Objects
|
|---|
| 400 | ---------------------
|
|---|
| 401 |
|
|---|
| 402 | A :class:`ProtocolError` object describes a protocol error in the underlying
|
|---|
| 403 | transport layer (such as a 404 'not found' error if the server named by the URI
|
|---|
| [391] | 404 | does not exist). It has the following attributes:
|
|---|
| [2] | 405 |
|
|---|
| 406 |
|
|---|
| 407 | .. attribute:: ProtocolError.url
|
|---|
| 408 |
|
|---|
| 409 | The URI or URL that triggered the error.
|
|---|
| 410 |
|
|---|
| 411 |
|
|---|
| 412 | .. attribute:: ProtocolError.errcode
|
|---|
| 413 |
|
|---|
| 414 | The error code.
|
|---|
| 415 |
|
|---|
| 416 |
|
|---|
| 417 | .. attribute:: ProtocolError.errmsg
|
|---|
| 418 |
|
|---|
| 419 | The error message or diagnostic string.
|
|---|
| 420 |
|
|---|
| 421 |
|
|---|
| 422 | .. attribute:: ProtocolError.headers
|
|---|
| 423 |
|
|---|
| 424 | A string containing the headers of the HTTP/HTTPS request that triggered the
|
|---|
| 425 | error.
|
|---|
| 426 |
|
|---|
| 427 | In the following example we're going to intentionally cause a :exc:`ProtocolError`
|
|---|
| [391] | 428 | by providing an URI that doesn't point to an XMLRPC server::
|
|---|
| [2] | 429 |
|
|---|
| 430 | import xmlrpclib
|
|---|
| 431 |
|
|---|
| [391] | 432 | # create a ServerProxy with an URI that doesn't respond to XMLRPC requests
|
|---|
| 433 | proxy = xmlrpclib.ServerProxy("http://www.google.com/")
|
|---|
| [2] | 434 |
|
|---|
| 435 | try:
|
|---|
| 436 | proxy.some_method()
|
|---|
| [391] | 437 | except xmlrpclib.ProtocolError as err:
|
|---|
| [2] | 438 | print "A protocol error occurred"
|
|---|
| 439 | print "URL: %s" % err.url
|
|---|
| 440 | print "HTTP/HTTPS headers: %s" % err.headers
|
|---|
| 441 | print "Error code: %d" % err.errcode
|
|---|
| 442 | print "Error message: %s" % err.errmsg
|
|---|
| 443 |
|
|---|
| 444 | MultiCall Objects
|
|---|
| 445 | -----------------
|
|---|
| 446 |
|
|---|
| 447 | .. versionadded:: 2.4
|
|---|
| 448 |
|
|---|
| [391] | 449 | The :class:`MultiCall` object provides a way to encapsulate multiple calls to a
|
|---|
| 450 | remote server into a single request [#]_.
|
|---|
| [2] | 451 |
|
|---|
| 452 |
|
|---|
| 453 | .. class:: MultiCall(server)
|
|---|
| 454 |
|
|---|
| 455 | Create an object used to boxcar method calls. *server* is the eventual target of
|
|---|
| 456 | the call. Calls can be made to the result object, but they will immediately
|
|---|
| 457 | return ``None``, and only store the call name and parameters in the
|
|---|
| 458 | :class:`MultiCall` object. Calling the object itself causes all stored calls to
|
|---|
| 459 | be transmitted as a single ``system.multicall`` request. The result of this call
|
|---|
| 460 | is a :term:`generator`; iterating over this generator yields the individual
|
|---|
| 461 | results.
|
|---|
| 462 |
|
|---|
| 463 | A usage example of this class follows. The server code ::
|
|---|
| 464 |
|
|---|
| 465 | from SimpleXMLRPCServer import SimpleXMLRPCServer
|
|---|
| 466 |
|
|---|
| 467 | def add(x,y):
|
|---|
| 468 | return x+y
|
|---|
| 469 |
|
|---|
| 470 | def subtract(x, y):
|
|---|
| 471 | return x-y
|
|---|
| 472 |
|
|---|
| 473 | def multiply(x, y):
|
|---|
| 474 | return x*y
|
|---|
| 475 |
|
|---|
| 476 | def divide(x, y):
|
|---|
| 477 | return x/y
|
|---|
| 478 |
|
|---|
| 479 | # A simple server with simple arithmetic functions
|
|---|
| 480 | server = SimpleXMLRPCServer(("localhost", 8000))
|
|---|
| 481 | print "Listening on port 8000..."
|
|---|
| 482 | server.register_multicall_functions()
|
|---|
| 483 | server.register_function(add, 'add')
|
|---|
| 484 | server.register_function(subtract, 'subtract')
|
|---|
| 485 | server.register_function(multiply, 'multiply')
|
|---|
| 486 | server.register_function(divide, 'divide')
|
|---|
| 487 | server.serve_forever()
|
|---|
| 488 |
|
|---|
| 489 | The client code for the preceding server::
|
|---|
| 490 |
|
|---|
| 491 | import xmlrpclib
|
|---|
| 492 |
|
|---|
| 493 | proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
|
|---|
| 494 | multicall = xmlrpclib.MultiCall(proxy)
|
|---|
| 495 | multicall.add(7,3)
|
|---|
| 496 | multicall.subtract(7,3)
|
|---|
| 497 | multicall.multiply(7,3)
|
|---|
| 498 | multicall.divide(7,3)
|
|---|
| 499 | result = multicall()
|
|---|
| 500 |
|
|---|
| 501 | print "7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)
|
|---|
| 502 |
|
|---|
| 503 |
|
|---|
| 504 | Convenience Functions
|
|---|
| 505 | ---------------------
|
|---|
| 506 |
|
|---|
| 507 |
|
|---|
| 508 | .. function:: boolean(value)
|
|---|
| 509 |
|
|---|
| 510 | Convert any Python value to one of the XML-RPC Boolean constants, ``True`` or
|
|---|
| 511 | ``False``.
|
|---|
| 512 |
|
|---|
| 513 |
|
|---|
| 514 | .. function:: dumps(params[, methodname[, methodresponse[, encoding[, allow_none]]]])
|
|---|
| 515 |
|
|---|
| 516 | Convert *params* into an XML-RPC request. or into a response if *methodresponse*
|
|---|
| 517 | is true. *params* can be either a tuple of arguments or an instance of the
|
|---|
| 518 | :exc:`Fault` exception class. If *methodresponse* is true, only a single value
|
|---|
| 519 | can be returned, meaning that *params* must be of length 1. *encoding*, if
|
|---|
| 520 | supplied, is the encoding to use in the generated XML; the default is UTF-8.
|
|---|
| 521 | Python's :const:`None` value cannot be used in standard XML-RPC; to allow using
|
|---|
| 522 | it via an extension, provide a true value for *allow_none*.
|
|---|
| 523 |
|
|---|
| 524 |
|
|---|
| 525 | .. function:: loads(data[, use_datetime])
|
|---|
| 526 |
|
|---|
| 527 | Convert an XML-RPC request or response into Python objects, a ``(params,
|
|---|
| 528 | methodname)``. *params* is a tuple of argument; *methodname* is a string, or
|
|---|
| 529 | ``None`` if no method name is present in the packet. If the XML-RPC packet
|
|---|
| 530 | represents a fault condition, this function will raise a :exc:`Fault` exception.
|
|---|
| 531 | The *use_datetime* flag can be used to cause date/time values to be presented as
|
|---|
| 532 | :class:`datetime.datetime` objects; this is false by default.
|
|---|
| 533 |
|
|---|
| 534 | .. versionchanged:: 2.5
|
|---|
| 535 | The *use_datetime* flag was added.
|
|---|
| 536 |
|
|---|
| 537 |
|
|---|
| 538 | .. _xmlrpc-client-example:
|
|---|
| 539 |
|
|---|
| 540 | Example of Client Usage
|
|---|
| 541 | -----------------------
|
|---|
| 542 |
|
|---|
| 543 | ::
|
|---|
| 544 |
|
|---|
| 545 | # simple test program (from the XML-RPC specification)
|
|---|
| 546 | from xmlrpclib import ServerProxy, Error
|
|---|
| 547 |
|
|---|
| 548 | # server = ServerProxy("http://localhost:8000") # local server
|
|---|
| 549 | server = ServerProxy("http://betty.userland.com")
|
|---|
| 550 |
|
|---|
| 551 | print server
|
|---|
| 552 |
|
|---|
| 553 | try:
|
|---|
| 554 | print server.examples.getStateName(41)
|
|---|
| [391] | 555 | except Error as v:
|
|---|
| [2] | 556 | print "ERROR", v
|
|---|
| 557 |
|
|---|
| 558 | To access an XML-RPC server through a proxy, you need to define a custom
|
|---|
| 559 | transport. The following example shows how:
|
|---|
| 560 |
|
|---|
| 561 | .. Example taken from http://lowlife.jp/nobonobo/wiki/xmlrpcwithproxy.html
|
|---|
| 562 |
|
|---|
| 563 | ::
|
|---|
| 564 |
|
|---|
| 565 | import xmlrpclib, httplib
|
|---|
| 566 |
|
|---|
| 567 | class ProxiedTransport(xmlrpclib.Transport):
|
|---|
| 568 | def set_proxy(self, proxy):
|
|---|
| 569 | self.proxy = proxy
|
|---|
| 570 | def make_connection(self, host):
|
|---|
| 571 | self.realhost = host
|
|---|
| 572 | h = httplib.HTTP(self.proxy)
|
|---|
| 573 | return h
|
|---|
| 574 | def send_request(self, connection, handler, request_body):
|
|---|
| 575 | connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
|
|---|
| 576 | def send_host(self, connection, host):
|
|---|
| 577 | connection.putheader('Host', self.realhost)
|
|---|
| 578 |
|
|---|
| 579 | p = ProxiedTransport()
|
|---|
| 580 | p.set_proxy('proxy-server:8080')
|
|---|
| 581 | server = xmlrpclib.Server('http://time.xmlrpc.com/RPC2', transport=p)
|
|---|
| 582 | print server.currentTime.getCurrentTime()
|
|---|
| 583 |
|
|---|
| 584 |
|
|---|
| 585 | Example of Client and Server Usage
|
|---|
| 586 | ----------------------------------
|
|---|
| 587 |
|
|---|
| 588 | See :ref:`simplexmlrpcserver-example`.
|
|---|
| 589 |
|
|---|
| 590 |
|
|---|
| [391] | 591 | .. rubric:: Footnotes
|
|---|
| 592 |
|
|---|
| 593 | .. [#] This approach has been first presented in `a discussion on xmlrpc.com
|
|---|
| 594 | <http://web.archive.org/web/20060624230303/http://www.xmlrpc.com/discuss/msgReader$1208?mode=topic>`_.
|
|---|
| 595 | .. the link now points to webarchive since the one at
|
|---|
| 596 | .. http://www.xmlrpc.com/discuss/msgReader%241208 is broken (and webadmin
|
|---|
| 597 | .. doesn't reply)
|
|---|