Skip to content

Commit a6da09a

Browse files
committed
openapi - OpenAPI.raise_on_http_status allows customizing behaviour
1 parent 83dece7 commit a6da09a

File tree

5 files changed

+23
-21
lines changed

5 files changed

+23
-21
lines changed

aiopenapi3/errors.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,23 +189,27 @@ def __str__(self):
189189
{self.missing}>"""
190190

191191

192+
@dataclasses.dataclass(repr=False)
192193
class HTTPStatusIndicatedError(HTTPError):
193194
"""The HTTP Status is 4xx or 5xx"""
194195

195-
pass
196+
status_code: int
197+
headers: dict[str, str]
198+
data: pydantic.BaseModel
199+
200+
def __str__(self):
201+
return f"""<{self.__class__.__name__} {self.status_code} {self.data} {self.headers}>"""
196202

197203

198204
@dataclasses.dataclass(repr=False)
199205
class HttpClientError(HTTPStatusIndicatedError):
200206
"""response code 4xx"""
201207

202-
headers: dict[str, str]
203-
data: pydantic.BaseModel
208+
pass
204209

205210

206211
@dataclasses.dataclass(repr=False)
207212
class HttpServerError(HTTPStatusIndicatedError):
208213
"""response code 5xx"""
209214

210-
headers: dict[str, str]
211-
data: pydantic.BaseModel
215+
pass

aiopenapi3/openapi.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from . import v31
2929
from . import log
3030
from .request import OperationIndex, HTTP_METHODS
31-
from .errors import ReferenceResolutionError
31+
from .errors import ReferenceResolutionError, HttpClientError, HttpServerError
3232
from .loader import Loader, NullLoader
3333
from .plugin import Plugin, Plugins
3434
from .base import RootBase, ReferenceBase, SchemaBase, OperationBase, DiscriminatorBase
@@ -232,7 +232,6 @@ def __init__(
232232
loader: Optional[Loader] = None,
233233
plugins: Optional[list[Plugin]] = None,
234234
use_operation_tags: bool = True,
235-
raise_on_error: bool = True,
236235
) -> None:
237236
"""
238237
Creates a new OpenAPI document from a loaded spec file. This is
@@ -245,7 +244,6 @@ def __init__(
245244
:param loader: the Loader for the description document(s)
246245
:param plugins: list of plugins
247246
:param use_operation_tags: honor tags
248-
:param raise_on_error: raise an exception if the http status code indicates error
249247
"""
250248
self._base_url: yarl.URL = yarl.URL(url)
251249

@@ -268,9 +266,12 @@ def __init__(
268266
Maximum Content-Length in Responses - default to 8 MBytes
269267
"""
270268

271-
self._raise_on_error = raise_on_error
269+
self.raise_on_http_status: list[tuple[type[Exception], tuple[int, int]]] = [
270+
(HttpClientError, (400, 499)),
271+
(HttpServerError, (500, 599)),
272+
]
272273
"""
273-
Raise for http status code 400-599
274+
Raise for http status code
274275
"""
275276

276277
self._security: dict[str, tuple[str]] = dict()

aiopenapi3/request.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,10 @@ def _build_req(self, session: Union[httpx.Client, httpx.AsyncClient]) -> httpx.R
217217
)
218218
return req
219219

220-
def _raise_on_error(self, result: httpx.Response, headers: dict[str, str], data: Union[pydantic.BaseModel, bytes]):
221-
if self.api._raise_on_error is False:
222-
return
223-
if 500 <= result.status_code <= 599:
224-
raise HttpServerError(headers, data)
225-
elif 400 <= result.status_code <= 499:
226-
raise HttpClientError(headers, data)
220+
def _raise_on_http_status(self, status_code: int, headers: dict[str, str], data: Union[pydantic.BaseModel, bytes]):
221+
for exc, (start, end) in self.api.raise_on_http_status:
222+
if start <= status_code <= end:
223+
raise exc(status_code, headers, data)
227224

228225
def request(
229226
self,

aiopenapi3/v20/glue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,11 @@ def _process_request(self, result: httpx.Response) -> tuple["ResponseHeadersType
350350
request=self, operationId=self.operation.operationId, unmarshalled=data
351351
).unmarshalled
352352

353-
self._raise_on_error(result, rheaders, data)
353+
self._raise_on_http_status(int(status_code), rheaders, data)
354354

355355
return rheaders, data
356356
elif self.operation.produces and content_type in self.operation.produces:
357-
self._raise_on_error(result, rheaders, ctx.received)
357+
self._raise_on_http_status(result.status_code, rheaders, ctx.received)
358358
return rheaders, ctx.received
359359
else:
360360
raise ContentTypeError(

aiopenapi3/v30/glue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ def _process_request(self, result: httpx.Response) -> tuple["ResponseHeadersType
577577
request=self, operationId=self.operation.operationId, unmarshalled=data
578578
).unmarshalled
579579

580-
self._raise_on_error(result, rheaders, data)
580+
self._raise_on_http_status(int(status_code), rheaders, data)
581581

582582
return rheaders, data
583583
else:
@@ -586,7 +586,7 @@ def _process_request(self, result: httpx.Response) -> tuple["ResponseHeadersType
586586
e.g. application/octet-stream
587587
but we can't validate it since it's not json.
588588
"""
589-
self._raise_on_error(result, rheaders, ctx.received)
589+
self._raise_on_http_status(result.status_code, rheaders, ctx.received)
590590

591591
return rheaders, ctx.received
592592

0 commit comments

Comments
 (0)