Files
odoo_source/odoo/addons/base/controllers/rpc.py
T
Adrian Torres 2693918903 [FIX] xmlrpc: properly marshall date & datetime objects
Before this revision, trying to read a Date field using xmlrpc would
result in a marshalling error.

This is due to the fact that 960360afe4
changed the internal value of Date/Datetime fields to hold
datetime.date/datetime objects.

The xmlrpc layer is capable of converting datetimes to the XML
datetime representation, but this is not possible for datetime.date
objects.

In order to solve this, the Marshaller class used by python's
xmlrpc.client is overridden and monkey-patched, allowing to convert
datetime.date / datetime.datetime objects into properly formatted
strings.

opw-1896364

closes odoo/odoo#28022
2018-10-22 12:22:59 +00:00

72 lines
2.4 KiB
Python

from datetime import date, datetime
from xmlrpc.client import dumps, loads
import xmlrpc.client
from werkzeug.wrappers import Response
from odoo.http import Controller, dispatch_rpc, request, route
from odoo.service import wsgi_server
from odoo.fields import Date, Datetime
class OdooMarshaller(xmlrpc.client.Marshaller):
"""
XMLRPC Marshaller that converts date(time) objects to strings in iso8061 format.
"""
dispatch = dict(xmlrpc.client.Marshaller.dispatch)
def dump_datetime(self, value, write):
# override to marshall as a string for backwards compatibility
value = Datetime.to_string(value)
self.dump_unicode(value, write)
dispatch[datetime] = dump_datetime
def dump_date(self, value, write):
value = Date.to_string(value)
self.dump_unicode(value, write)
dispatch[date] = dump_date
# monkey-patch xmlrpc.client's marshaller
xmlrpc.client.Marshaller = OdooMarshaller
class RPC(Controller):
"""Handle RPC connections."""
def _xmlrpc(self, service):
"""Common method to handle an XML-RPC request."""
data = request.httprequest.get_data()
params, method = loads(data)
result = dispatch_rpc(service, method, params)
return dumps((result,), methodresponse=1, allow_none=False)
@route("/xmlrpc/<service>", auth="none", method="POST", csrf=False, save_session=False)
def xmlrpc_1(self, service):
"""XML-RPC service that returns faultCode as strings.
This entrypoint is historical and non-compliant, but kept for
backwards-compatibility.
"""
try:
response = self._xmlrpc(service)
except Exception as error:
response = wsgi_server.xmlrpc_handle_exception_string(error)
return Response(response=response, mimetype='text/xml')
@route("/xmlrpc/2/<service>", auth="none", method="POST", csrf=False, save_session=False)
def xmlrpc_2(self, service):
"""XML-RPC service that returns faultCode as int."""
try:
response = self._xmlrpc(service)
except Exception as error:
response = wsgi_server.xmlrpc_handle_exception_int(error)
return Response(response=response, mimetype='text/xml')
@route('/jsonrpc', type='json', auth="none", save_session=False)
def jsonrpc(self, service, method, args):
""" Method used by client APIs to contact OpenERP. """
return dispatch_rpc(service, method, args)