Skip to content

Commit 1fdcfbe

Browse files
committed
Proper error management for JSON-2 API
1 parent 41b7f77 commit 1fdcfbe

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Changelog
1111
* Consider users with restricted rights. Since Odoo 15, most
1212
users don't have access to ``ir.model``.
1313

14+
* Enhance error management for JSON-2 API with Odoo >= 19.
15+
1416

1517
2.4.6 (2025-10-31)
1618
~~~~~~~~~~~~~~~~~~

odooly.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ def request(self, url, *, method='POST', data=None, json=None, headers=None, **k
144144
resp.raise_for_status()
145145
return resp if method == 'HEAD' else resp.text if json is None else resp.json()
146146

147+
def _parse_error(self, error):
148+
return error.response.status_code, error.response.json()
149+
147150
else: # urllib.request
148151
def __init__(self):
149152
self._session = build_opener(HTTPCookieProcessor(), HTTPSHandler(context=http_context))
@@ -160,6 +163,9 @@ def request(self, url, *, method='POST', data=None, json=None, headers=None, _js
160163
with self._session.open(request) as resp:
161164
return resp if method == 'HEAD' else resp.read().decode() if json is None else _json.load(resp)
162165

166+
def _parse_error(self, error):
167+
return error.code, json.load(error)
168+
163169

164170
def _memoize(inst, attr, value, doc_values=None):
165171
if hasattr(value, '__get__') and not hasattr(value, '__self__'):
@@ -551,7 +557,7 @@ class Json2:
551557
_doc_endpoint = '/doc-bearer'
552558

553559
def __init__(self, client, database, api_key):
554-
self._req = HTTPSession().request
560+
self._http = HTTPSession()
555561
self._server = urljoin(client._server, '/')
556562
self._headers = {
557563
'Authorization': f'Bearer {api_key}',
@@ -594,10 +600,19 @@ def __call__(self, model, method, args, kw=None):
594600
def __repr__(self):
595601
return f"<Json2 '{self._server[:-1]}{self._endpoint}'>"
596602

603+
def _req(self, url, json, headers, method):
604+
try:
605+
return self._http.request(url, method=method, json=json, headers=headers)
606+
except OSError as exc:
607+
status_code, result = self._http._parse_error(exc)
608+
if status_code == 422: # UnprocessableEntity
609+
raise ServerError({'code': status_code, 'data': result})
610+
raise
611+
597612
def _check(self, uid=None):
598613
url = urljoin(self._server, f'{self._endpoint}/res.users/context_get')
599614
try:
600-
context = self._req(url, json={}, headers=self._headers)
615+
context = self._http.request(url, json={}, headers=self._headers, method='POST')
601616
except (OSError, ServerError):
602617
return False
603618
return self if (not uid or uid == context['uid']) else False

0 commit comments

Comments
 (0)