1- from collections import namedtuple
2- from collections .abc import Callable , Coroutine
31from types import TracebackType
4- from typing import Any , Optional , Type
52
63import aiohttp
74from aiohttp import ClientSession
85
9- from .response import Response
10- from ..errors .client_error import ClientError
116from ..errors .custom_error import CustomError
12- from ..errors .internal_error import InternalError
13- from ..errors .server_error import ServerError
147from ..util import url
158
16- Range = namedtuple ( 'Range' , 'lower, upper' )
17-
18-
19- class UninitializedError ( CustomError ):
20- pass
9+ from . execute_request import execute_request
10+ from . get_get_headers import get_get_headers
11+ from . get_post_headers import get_post_headers
12+ from . response import Response
13+ from . validate_response import validate_response
2114
2215
2316class HttpClient :
@@ -36,9 +29,9 @@ async def __aenter__(self):
3629
3730 async def __aexit__ (
3831 self ,
39- exc_type : Optional [ Type [ BaseException ]] ,
40- exc_val : Optional [ BaseException ] ,
41- exc_tb : Optional [ TracebackType ]
32+ exc_type : BaseException | None = None ,
33+ exc_val : BaseException | None = None ,
34+ exc_tb : TracebackType | None = None ,
4235 ) -> None :
4336 await self .close ()
4437
@@ -53,114 +46,67 @@ async def close(self):
5346 self .__session = None
5447 return None
5548
56- async def __execute_request (
57- self ,
58- execute_request : Callable [[], Coroutine [Any , Any , Response ]]
59- ) -> Response :
60- try :
61- result = await execute_request ()
62- return result
63- except CustomError as custom_error :
64- raise custom_error
65- except aiohttp .ClientError as request_error :
66- raise ServerError (str (request_error )) from request_error
67- except Exception as other_error :
68- raise InternalError (str (other_error )) from other_error
69-
70- @staticmethod
71- async def __get_error_message (response : Response ):
72- error_message = f'Request failed with status code \' { response .status_code } \' '
73-
74- # We want to purposefully ignore all errors here, as we're already error handling,
75- # and this function just tries to get more information on a best-effort basis.
76- try :
77- encoded_error_reason = await response .body .read ()
78- error_reason = encoded_error_reason .decode ('utf-8' )
79- error_message += f" { error_reason } "
80- finally :
81- pass
82-
83- error_message += '.'
84-
85- return error_message
86-
87- async def __validate_response (
88- self ,
89- response : Response
90- ) -> Response :
91- server_failure_range = Range (500 , 600 )
92- if server_failure_range .lower <= response .status_code < server_failure_range .upper :
93- raise ServerError (await self .__get_error_message (response ))
94-
95- client_failure_range = Range (400 , 500 )
96- if client_failure_range .lower <= response .status_code < client_failure_range .upper :
97- raise ClientError (await self .__get_error_message (response ))
98-
99- return response
100-
101- def __get_post_request_headers (self ) -> dict [str , str ]:
102- headers = {
103- 'Authorization' : f'Bearer { self .__api_token } ' ,
104- 'Content-Type' : 'application/json'
105- }
106-
107- return headers
108-
10949 async def post (self , path : str , request_body : str ) -> Response :
11050 if self .__session is None :
111- raise UninitializedError ()
51+ raise CustomError ()
11252
113- async def execute_request () -> Response :
53+ async def request_executor () -> Response :
54+ # Vorbereitung
55+ url_path = url .join_segments (self .__base_url , path )
56+ headers = get_post_headers (self .__api_token )
57+
58+ # Request ausführen
11459 async_response = await self .__session .post ( # type: ignore
115- url .join_segments (
116- self .__base_url ,
117- path
118- ),
60+ url_path ,
11961 data = request_body ,
120- headers = self . __get_post_request_headers () ,
62+ headers = headers ,
12163 )
12264
65+ # Response erstellen
12366 response = Response (async_response )
67+
68+ # Split try block to have only one statement
69+ validated_response = None
12470 try :
125- result = await self .__validate_response (response )
126- return result
71+ validated_response = await validate_response (response )
12772 except Exception as error :
12873 response .close ()
12974 raise error
13075
131- return await self . __execute_request ( execute_request )
76+ return validated_response
13277
133- def __get_get_request_headers (self , with_authorization : bool ) -> dict [str , str ]:
134- headers = {}
135-
136- if with_authorization :
137- headers ['Authorization' ] = f'Bearer { self .__api_token } '
138-
139- return headers
78+ return await execute_request (request_executor )
14079
14180 async def get (
14281 self ,
14382 path : str ,
14483 with_authorization : bool = True ,
14584 ) -> Response :
14685 if self .__session is None :
147- raise UninitializedError ()
86+ raise CustomError ()
87+
88+ async def request_executor () -> Response :
89+ # Vorbereitung
90+ url_path = url .join_segments (self .__base_url , path )
91+ headers = get_get_headers (self .__api_token , with_authorization )
14892
149- async def execute_request () -> Response :
93+ # Request ausführen
15094 async_response = await self .__session .get ( # type: ignore
151- url .join_segments (
152- self .__base_url ,
153- path
154- ),
155- headers = self .__get_get_request_headers (with_authorization ),
95+ url_path ,
96+ headers = headers ,
15697 )
15798
99+ # Response erstellen
158100 response = Response (async_response )
101+
102+ # Split try block to have only one statement
103+ validated_response = None
159104 try :
160- result = await self .__validate_response (response )
161- return result
105+ validated_response = await validate_response (response )
162106 except Exception as error :
163107 response .close ()
164108 raise error
165109
166- return await self .__execute_request (execute_request )
110+ return validated_response
111+
112+ return await execute_request (request_executor )
0 commit comments