finalsa-common-http-client 0.0.4__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: finalsa-common-http-client
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: HTTP client library for common data types used in business applications
5
5
  Project-URL: Homepage, https://github.com/finalsa/finalsa-http-client
6
6
  Project-URL: Documentation, https://github.com/finalsa/finalsa-http-client#readme
@@ -2,8 +2,10 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Mapping
4
4
  from importlib import metadata
5
+ from typing import Any, Dict
5
6
  from urllib.parse import urljoin
6
7
 
8
+ from finalsa.common.models import BaseDomainException
7
9
  from finalsa.traceability import get_w3c_traceparent, get_w3c_tracestate
8
10
  from finalsa.traceability.functions import (
9
11
  HTTP_HEADER_TRACEPARENT,
@@ -13,6 +15,18 @@ from finalsa.traceability.functions import (
13
15
  Headers = Mapping[str, str]
14
16
 
15
17
 
18
+ class InternalHttpError(BaseDomainException):
19
+ """Exception raised when a service is unavailable."""
20
+ response_code = 500
21
+
22
+ def __init__(self, response_code: int | None = None):
23
+ super().__init__(
24
+ message="Internal HTTP error",
25
+ response_code=response_code or self.response_code,
26
+ name="InternalHttpError"
27
+ )
28
+
29
+
16
30
  def normalize_base_url(
17
31
  base_url: str | None,
18
32
  default_scheme: str,
@@ -92,3 +106,11 @@ def get_package_version(package_name: str = "finalsa-http-client") -> str:
92
106
  except metadata.PackageNotFoundError:
93
107
  return "0.0.0"
94
108
 
109
+
110
+ def raise_for_response(response: Dict[str, Any], status: int) -> None:
111
+ if response.get("message") and response.get("name"):
112
+ raise BaseDomainException(
113
+ message=response.get("message"),
114
+ response_code=status,
115
+ name=response.get("name")
116
+ )
@@ -4,8 +4,7 @@ from collections.abc import Mapping
4
4
  from typing import Any
5
5
 
6
6
  import aiohttp
7
- from aiohttp import ClientResponseError, ClientSession, ClientTimeout
8
- from finalsa.common.models import BaseDomainException
7
+ from aiohttp import ClientSession, ClientTimeout
9
8
 
10
9
  from finalsa.http import _shared as shared
11
10
 
@@ -27,14 +26,12 @@ class BaseAsyncHttpClient:
27
26
  default_scheme: str = "http",
28
27
  service_name: str = "finalsa-http-client",
29
28
  trust_env: bool = False,
30
- raise_for_status: bool = True,
31
29
  session: ClientSession | None = None,
32
30
  ) -> None:
33
31
  self._default_scheme = default_scheme
34
32
  self.base_url = shared.normalize_base_url(base_url, default_scheme)
35
33
  self._timeout = self._normalize_timeout(timeout)
36
34
  self._trust_env = trust_env
37
- self._raise_for_status = raise_for_status
38
35
  self._session = session
39
36
  self._owns_session = session is None
40
37
  self._default_headers = shared.build_default_headers(
@@ -76,6 +73,17 @@ class BaseAsyncHttpClient:
76
73
  default_scheme=self._default_scheme,
77
74
  )
78
75
 
76
+ async def raise_for_status(self, response: aiohttp.ClientResponse) -> None:
77
+ headers = response.headers if isinstance(
78
+ response.headers, Mapping) else response['headers']
79
+ if response.status < 400:
80
+ return
81
+ if "Content-Type" in headers and headers["Content-Type"] == "application/json":
82
+ data = await response.json()
83
+ shared.raise_for_response(data, response.status)
84
+ else:
85
+ raise shared.InternalHttpError(response.status)
86
+
79
87
  async def request(
80
88
  self,
81
89
  method: str,
@@ -102,31 +110,17 @@ class BaseAsyncHttpClient:
102
110
  )
103
111
  merged_headers = shared.merge_headers(self._default_headers, headers)
104
112
  request_timeout = self._normalize_timeout(timeout) or self._timeout
105
- response = None
106
- try:
107
-
108
- response = await session.request(
109
- method.upper(),
110
- resolved_url,
111
- headers=merged_headers,
112
- params=params,
113
- json=json,
114
- data=data,
115
- timeout=request_timeout,
116
- **kwargs,
117
- )
118
- response.raise_for_status()
119
- return response
120
- except Exception as e:
121
- if response is not None and "Content-Type" in response.headers and response.headers["Content-Type"] == "application/json":
122
- data = await response.json()
123
- if data.get("message") and data.get("name"):
124
- raise BaseDomainException(
125
- message=data.get("message"),
126
- response_code=response.status_code,
127
- name=data.get("name")
128
- ) from e
129
- raise e
113
+ response = await session.request(
114
+ method.upper(),
115
+ resolved_url,
116
+ headers=merged_headers,
117
+ params=params,
118
+ json=json,
119
+ data=data,
120
+ timeout=request_timeout,
121
+ **kwargs,
122
+ )
123
+ return response
130
124
 
131
125
  async def get(self, path: str, **kwargs: Any) -> aiohttp.ClientResponse:
132
126
  return await self.request("GET", path, **kwargs)
@@ -155,6 +149,7 @@ class BaseAsyncHttpClient:
155
149
  self._session = aiohttp.ClientSession(
156
150
  timeout=self._timeout,
157
151
  trust_env=self._trust_env,
152
+ raise_for_status=self.raise_for_status,
158
153
  )
159
154
  return self._session
160
155
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "finalsa-common-http-client"
3
- version = "0.0.4"
3
+ version = "0.0.5"
4
4
  description = "HTTP client library for common data types used in business applications"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -70,6 +70,7 @@ include = [
70
70
 
71
71
  [dependency-groups]
72
72
  test = [
73
+ "aioresponses>=0.7.8",
73
74
  "coverage>=7.9.2",
74
75
  "pytest>=8.3.4",
75
76
  "pytest-asyncio>=0.24.0",