[IMP] Handle XMLRPC calls from standard controllers

This way, XMLRPC calls can get request details form the standard
`odoo.http.request` system.

Move jsonrpc to the same controller while at it, for coherence.

Fix #24183
This commit is contained in:
Jairo Llopis
2018-05-09 09:46:15 +02:00
committed by xmo-odoo
parent e9e8fd24cf
commit 285ead28e3
5 changed files with 49 additions and 46 deletions
+1
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
from . import report
from . import wizard
+1
View File
@@ -0,0 +1 @@
from . import rpc
+44
View File
@@ -0,0 +1,44 @@
from xmlrpc.client import dumps, loads
from werkzeug.wrappers import Response
from odoo.http import Controller, dispatch_rpc, request, route
from odoo.service import wsgi_server
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)
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)
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")
def jsonrpc(self, service, method, args):
""" Method used by client APIs to contact OpenERP. """
return dispatch_rpc(service, method, args)
-5
View File
@@ -1634,11 +1634,6 @@ def content_disposition(filename):
#----------------------------------------------------------
class CommonController(Controller):
@route('/jsonrpc', type='json', auth="none")
def jsonrpc(self, service, method, args):
""" Method used by client APIs to contact OpenERP. """
return dispatch_rpc(service, method, args)
@route('/gen_session_id', type='json', auth="none")
def gen_session_id(self):
nsession = root.session_store.new()
+3 -41
View File
@@ -99,48 +99,13 @@ def _patch_xmlrpc_marshaller():
xmlrpclib.Marshaller.dispatch[bytes] = dump_bytes
def wsgi_xmlrpc(environ, start_response):
""" Two routes are available for XML-RPC
/xmlrpc/<service> route returns faultCode as strings. This is a historic
violation of the protocol kept for compatibility.
/xmlrpc/2/<service> is a new route that returns faultCode as int and is
therefore fully compliant.
"""
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'):
length = int(environ['CONTENT_LENGTH'])
data = environ['wsgi.input'].read(length)
# Distinguish betweed the 2 faultCode modes
string_faultcode = True
service = environ['PATH_INFO'][len('/xmlrpc/'):]
if environ['PATH_INFO'].startswith('/xmlrpc/2/'):
service = service[len('2/'):]
string_faultcode = False
params, method = xmlrpclib.loads(data)
try:
result = odoo.http.dispatch_rpc(service, method, params)
response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False)
except Exception as e:
if string_faultcode:
response = xmlrpc_handle_exception_string(e)
else:
response = xmlrpc_handle_exception_int(e)
return werkzeug.wrappers.Response(
response=response,
mimetype='text/xml',
)(environ, start_response)
def application_unproxied(environ, start_response):
""" WSGI entry point."""
# cleanup db/uid trackers - they're set at HTTP dispatch in
# web.session.OpenERPSession.send() and at RPC dispatch in
# odoo.service.web_services.objects_proxy.dispatch().
# /!\ The cleanup cannot be done at the end of this `application`
# method because werkzeug still produces relevant logging afterwards
# method because werkzeug still produces relevant logging afterwards
if hasattr(threading.current_thread(), 'uid'):
del threading.current_thread().uid
if hasattr(threading.current_thread(), 'dbname'):
@@ -149,11 +114,8 @@ def application_unproxied(environ, start_response):
del threading.current_thread().url
with odoo.api.Environment.manage():
# Try all handlers until one returns some result (i.e. not None).
for handler in [wsgi_xmlrpc, odoo.http.root]:
result = handler(environ, start_response)
if result is None:
continue
result = odoo.http.root(environ, start_response)
if result is not None:
return result
# We never returned from the loop.