[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:
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from . import rpc
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user