[FIX] core: skip debugger for JSON-RPC in --dev=werkzeug

When started with the CLI option --dev=werkzeug, errors in controllers
are caught by a friendly web debugger. This debugger should not be
started in case of error in a JSON-RPC controller.

closes odoo/odoo#90420

Task: 2837457
X-original-commit: 711a29e76f55e87d73dad89ddbef889dd5c7af10
Signed-off-by: Julien Castiaux <juc@odoo.com>
This commit is contained in:
Julien Castiaux
2022-05-04 10:55:55 +02:00
parent b6e08d662d
commit d9608b1932
3 changed files with 67 additions and 2 deletions
+7
View File
@@ -141,3 +141,10 @@ class TestHttp(http.Controller):
def touch(self):
request.session.touch()
return ''
# =====================================================
# Errors
# =====================================================
@http.route('/test_http/json_value_error', type='json', auth='none')
def json_value_error(self):
raise ValueError('Unknown destination')
+58
View File
@@ -572,3 +572,61 @@ class TestHttpSession(TestHttpBase):
res.raise_for_status()
self.assertEqual(res.text, str(GEOIP_ODOO_FARM_2))
mock_resolve.assert_called_once()
class TestHttpJsonError(TestHttpBase):
jsonrpc_error_structure = {
'error': {
'code': ...,
'data': {
'arguments': ...,
'context': ...,
'debug': ...,
'message': ...,
'name': ...,
},
'message': ...,
},
'id': ...,
'jsonrpc': ...,
}
def assertIsErrorPayload(self, payload):
self.assertEqual(
set(payload),
set(self.jsonrpc_error_structure),
)
self.assertEqual(
set(payload['error']),
set(self.jsonrpc_error_structure['error']),
)
self.assertEqual(
set(payload['error']['data']),
set(self.jsonrpc_error_structure['error']['data']),
)
@mute_logger('odoo.http')
def test_errorjson0_value_error(self):
res = self.db_url_open('/test_http/json_value_error',
data=json.dumps({'jsonrpc': '2.0', 'id': 1234, 'params': {}}),
headers=CT_JSON
)
res.raise_for_status()
self.assertEqual(res.status_code, 200)
self.assertEqual(res.headers.get('Content-Type', ''), 'application/json; charset=utf-8')
payload = res.json()
self.assertIsErrorPayload(payload)
error_data = payload['error']['data']
self.assertEqual(error_data['name'], 'builtins.ValueError')
self.assertEqual(error_data['message'], 'Unknown destination')
self.assertEqual(error_data['arguments'], ['Unknown destination'])
self.assertEqual(error_data['context'], {})
@mute_logger('odoo.http')
def test_errorjson1_dev_mode_werkzeug(self):
with patch.object(config, 'options', {**config.options, 'dev_mode': 'werkzeug'}):
self.test_errorjson0_value_error()
+2 -2
View File
@@ -1382,7 +1382,7 @@ class Request:
except Exception as exc:
if isinstance(exc, HTTPException) and exc.code is None:
raise # bubble up to odoo.http.Application.__call__
if 'werkzeug' in config['dev_mode']:
if 'werkzeug' in config['dev_mode'] and self.dispatcher.routing_type != 'json':
raise # bubble up to werkzeug.debug.DebuggedApplication
exc.error_response = self.registry['ir.http']._handle_error(exc)
raise
@@ -1793,7 +1793,7 @@ class Application:
# Server is running with --dev=werkzeug, bubble the error up
# to werkzeug so he can fire up a debugger.
if 'werkzeug' in config['dev_mode']:
if 'werkzeug' in config['dev_mode'] and request.dispatcher.routing_type != 'json':
raise
# Ensure there is always a Response attached to the exception.