[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:
@@ -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')
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user