diff --git a/odoo/addons/base/controllers/rpc.py b/odoo/addons/base/controllers/rpc.py index e883d1c0fd2..1b608130f3f 100644 --- a/odoo/addons/base/controllers/rpc.py +++ b/odoo/addons/base/controllers/rpc.py @@ -8,7 +8,7 @@ from markupsafe import Markup from werkzeug.wrappers import Response import odoo -from odoo.http import Controller, request, route +from odoo.http import Controller, borrow_request, route from odoo.fields import Date, Datetime, Command from odoo.service import dispatch_rpc from odoo.tools import lazy, ustr @@ -125,9 +125,10 @@ class RPC(Controller): def _xmlrpc(self, service): """Common method to handle an XML-RPC request.""" - data = request.httprequest.get_data() - params, method = xmlrpc.client.loads(data) - result = dispatch_rpc(service, method, params) + with borrow_request() as request: + data = request.httprequest.get_data() + params, method = xmlrpc.client.loads(data) + result = dispatch_rpc(service, method, params) return xmlrpc.client.dumps((result,), methodresponse=1, allow_none=False) @route("/xmlrpc/", auth="none", methods=["POST"], csrf=False, save_session=False) @@ -155,4 +156,5 @@ class RPC(Controller): @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) + with borrow_request(): + return dispatch_rpc(service, method, args) diff --git a/odoo/addons/test_http/models.py b/odoo/addons/test_http/models.py index 21f548ccff2..c3bcef1aafb 100644 --- a/odoo/addons/test_http/models.py +++ b/odoo/addons/test_http/models.py @@ -56,4 +56,10 @@ class Galaxy(models.Model): _name = 'test_http.galaxy' _description = 'Galaxy' - name = fields.Char(required=True) + name = fields.Char(required=True, help='The galaxy common name.') + + @api.model + def render(self, galaxy_id): + return self.env['ir.qweb']._render('test_http.tmpl_galaxy', { + 'galaxy': self.browse([galaxy_id]) + }) diff --git a/odoo/addons/test_http/tests/test_misc.py b/odoo/addons/test_http/tests/test_misc.py index 855968d5f0a..749983e1436 100644 --- a/odoo/addons/test_http/tests/test_misc.py +++ b/odoo/addons/test_http/tests/test_misc.py @@ -8,7 +8,7 @@ from urllib.parse import urlparse import odoo from odoo.http import root from odoo.tests import tagged -from odoo.tests.common import HOST +from odoo.tests.common import HOST, new_test_user, get_db_name from odoo.tools import config, file_path from odoo.addons.test_http.controllers import CT_JSON @@ -75,6 +75,23 @@ class TestHttpMisc(TestHttpBase): self.assertIsNone(root.get_static_file(f'odoo.com/{uri}'), "No host allowed") self.assertIsNone(root.get_static_file(f'http://odoo.com/{uri}'), "No host allowed") + def test_misc4_rpc_qweb(self): + jack = new_test_user(self.env, 'jackoneill', context={'lang': 'en_US'}) + milky_way = self.env.ref('test_http.milky_way') + + payload = json.dumps({'jsonrpc': '2.0', 'method': 'call', 'id': None, 'params': { + 'service': 'object', 'method': 'execute', 'args': [ + get_db_name(), jack.id, 'jackoneill', 'test_http.galaxy', 'render', milky_way.id + ] + }}) + + res = self.nodb_url_open('/jsonrpc', data=payload, headers=CT_JSON) + res.raise_for_status() + + res_rpc = res.json() + self.assertNotIn('error', res_rpc.keys(), res_rpc.get('error', {}).get('data', {}).get('message')) + self.assertIn(milky_way.name, res_rpc['result'], "QWeb template was correctly rendered") + @tagged('post_install', '-at_install') class TestHttpCors(TestHttpBase): diff --git a/odoo/http.py b/odoo/http.py index e34dbf4783a..a7f5b19847a 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -975,6 +975,15 @@ class Session(collections.abc.MutableMapping): _request_stack = werkzeug.local.LocalStack() request = _request_stack() +@contextlib.contextmanager +def borrow_request(): + """ Get the current request and unexpose it from the local stack. """ + req = _request_stack.pop() + try: + yield req + finally: + _request_stack.push(req) + class Response(werkzeug.wrappers.Response): """