2 File in charge of containing the boilerplate endpoint functions to make queries to the web.
5from typing
import Union, Mapping, Dict, Any
9from display_tty
import Disp, TOML_CONF, FILE_DESCRIPTOR, SAVE_TO_FILE, FILE_NAME
11from .
import constants
as ACONST
15 """Exception raised when the content type of the response is unknown."""
17 def __init__(self, message: str =
"No Content-Type found in the header") ->
None:
24 This is the class in charge of containing the boilerplate endpoint functions.
27 def __init__(self, host: str =
"http://127.0.0.1", port: Union[int,
None] = 6000, delay: int = 2, debug: bool =
False) ->
None:
29 Class in charge of containing the boilerplate endpoint functions to make queries to the web.
32 host (_type_, optional): _description_. Defaults to "http://127.0.0.1".
33 port (Union[int, None], optional): _description_. Defaults to 6000.
34 delay (int, optional): _description_. Defaults to 2.
35 debug (bool, optional): _description_. Defaults to False.
38 if host.startswith(
"http")
is False:
42 if self.
_host.endswith(
"/")
is True:
45 self.
_host += f
":{port}"
54 logger=self.__class__.__name__
57 def get_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
59 This function is in charge of sending a GET request to the server.
61 path (str): _description_: The path of the endpoint.
62 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
63 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
65 requests.Response: _description_: The response from the server.
67 title =
"get_endpoint"
68 if isinstance(path, str)
is False:
70 f
"Expected an input of type string but got {type(path)}"
74 final_path = f
"{self._host}/{path}"
75 self.
disp.log_debug(f
"final_path = {final_path}", title)
76 self.
disp.log_debug(f
"content = {content}", title)
77 self.
disp.log_debug(f
"header = {header}", title)
78 if content
is not None and header
is None:
79 return requests.get(final_path, json=content, timeout=self.
_delay)
80 if content
is None and header
is not None:
81 return requests.get(final_path, headers=header, timeout=self.
_delay)
82 if content
is not None and header
is not None:
83 return requests.get(final_path, json=content, headers=header, timeout=self.
_delay)
84 return requests.get(final_path, timeout=self.
_delay)
86 def post_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
88 This function is in charge of sending a POST request to the server.
90 path (str): _description_: The path of the endpoint.
91 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
92 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
94 requests.Response: _description_: The response from the server.
96 title =
"post_endpoint"
97 if isinstance(path, str)
is False:
99 f
"Expected an input of type string but got {type(path)}"
103 final_path = f
"{self._host}/{path}"
104 self.
disp.log_debug(f
"final_path = {final_path}", title)
105 self.
disp.log_debug(f
"content = {content}", title)
106 self.
disp.log_debug(f
"header = {header}", title)
107 if content
is not None and header
is None:
108 return requests.post(final_path, json=content, timeout=self.
_delay)
109 if content
is None and header
is not None:
110 return requests.post(final_path, headers=header, timeout=self.
_delay)
111 if content
is not None and header
is not None:
112 return requests.post(final_path, json=content, headers=header, timeout=self.
_delay)
113 return requests.post(final_path, timeout=self.
_delay)
115 def put_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
117 This function is in charge of sending a PUT request to the server.
119 path (str): _description_: The path of the endpoint.
120 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
121 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
123 requests.Response: _description_: The response from the server.
125 title =
"put_endpoint"
126 if isinstance(path, str)
is False:
128 f
"Expected an input of type string but got {type(path)}"
132 final_path = f
"{self._host}/{path}"
133 self.
disp.log_debug(f
"final_path = {final_path}", title)
134 self.
disp.log_debug(f
"content = {content}", title)
135 self.
disp.log_debug(f
"header = {header}", title)
136 if content
is not None and header
is None:
137 return requests.put(final_path, json=content, timeout=self.
_delay)
138 if content
is None and header
is not None:
139 return requests.put(final_path, headers=header, timeout=self.
_delay)
140 if content
is not None and header
is not None:
141 return requests.put(final_path, json=content, headers=header, timeout=self.
_delay)
142 return requests.put(final_path, timeout=self.
_delay)
144 def patch_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
146 This function is in charge of sending a PATCH request to the server.
148 path (str): _description_: The path of the endpoint.
149 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
150 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
152 requests.Response: _description_: The response from the server.
154 title =
"patch_endpoint"
155 if isinstance(path, str)
is False:
157 f
"Expected an input of type string but got {type(path)}"
161 final_path = f
"{self._host}/{path}"
162 self.
disp.log_debug(f
"final_path = {final_path}", title)
163 self.
disp.log_debug(f
"content = {content}", title)
164 self.
disp.log_debug(f
"header = {header}", title)
165 if content
is not None and header
is None:
166 return requests.patch(final_path, json=content, timeout=self.
_delay)
167 if content
is None and header
is not None:
168 return requests.patch(final_path, headers=header, timeout=self.
_delay)
169 if content
is not None and header
is not None:
170 return requests.patch(final_path, json=content, headers=header, timeout=self.
_delay)
171 return requests.patch(final_path, timeout=self.
_delay)
173 def delete_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
175 This function is in charge of sending a DELETE request to the server.
177 path (str): _description_: The path of the endpoint.
178 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
179 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
181 requests.Response: _description_: The response from the server.
183 title =
"delete_endpoint"
184 if isinstance(path, str)
is False:
186 f
"Expected an input of type string but got {type(path)}"
190 final_path = f
"{self._host}/{path}"
191 self.
disp.log_debug(f
"final_path = {final_path}", title)
192 self.
disp.log_debug(f
"content = {content}", title)
193 self.
disp.log_debug(f
"header = {header}", title)
194 if content
is not None and header
is None:
195 return requests.delete(final_path, json=content, timeout=self.
_delay)
196 if content
is None and header
is not None:
197 return requests.delete(final_path, headers=header, timeout=self.
_delay)
198 if content
is not None and header
is not None:
199 return requests.delete(final_path, json=content, headers=header, timeout=self.
_delay)
200 return requests.delete(final_path, timeout=self.
_delay)
202 def head_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
204 This function is in charge of sending a HEAD request to the server.
206 path (str): _description_: The path of the endpoint.
207 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
208 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
210 requests.Response: _description_: The response from the server.
212 title =
"head_endpoint"
213 if isinstance(path, str)
is False:
215 f
"Expected an input of type string but got {type(path)}"
219 final_path = f
"{self._host}/{path}"
220 self.
disp.log_debug(f
"final_path = {final_path}", title)
221 self.
disp.log_debug(f
"content = {content}", title)
222 self.
disp.log_debug(f
"header = {header}", title)
223 if content
is not None and header
is None:
224 return requests.head(final_path, json=content, timeout=self.
_delay)
225 if content
is None and header
is not None:
226 return requests.head(final_path, headers=header, timeout=self.
_delay)
227 if content
is not None and header
is not None:
228 return requests.head(final_path, json=content, headers=header, timeout=self.
_delay)
229 return requests.head(final_path, timeout=self.
_delay)
231 def options_endpoint(self, path: str, content: Union[Dict[str, Any],
None] =
None, header: Union[Mapping[str, str],
None] =
None) -> requests.Response:
233 This function is in charge of sending a OPTIONS request to the server.
235 path (str): _description_: The path of the endpoint.
236 content (Union[Dict[str, Any], None], optional): _description_: The content to be sent to the server.
237 header (Union[Mapping[str, str], None], optional): _description_: The header to be sent to the server. Defaults to None.
239 requests.Response: _description_: The response from the server.
241 title =
"options_endpoint"
242 if isinstance(path, str)
is False:
244 f
"Expected an input of type string but got {type(path)}"
248 final_path = f
"{self._host}/{path}"
249 self.
disp.log_debug(f
"final_path = {final_path}", title)
250 self.
disp.log_debug(f
"content = {content}", title)
251 self.
disp.log_debug(f
"header = {header}", title)
252 if content
is not None and header
is None:
253 return requests.options(final_path, json=content, timeout=self.
_delay)
254 if content
is None and header
is not None:
255 return requests.options(final_path, headers=header, timeout=self.
_delay)
256 if content
is not None and header
is not None:
257 return requests.options(final_path, json=content, headers=header, timeout=self.
_delay)
258 return requests.options(final_path, timeout=self.
_delay)
262 This function is in charge of getting the status code from the response.
264 response (requests.Response): _description_: The response from the server.
266 int: _description_: The status code from the response.
268 return response.status_code
272 This function is in charge of getting the content type from the response.
275 response (requests.Response): _description_: The response from the server.
278 UnknownContentTypeError: _description_: If no content type is found in the header.
281 str: _description_: The content type from the response.
283 response = response.headers.get(
"Content-Type")
284 if response
is not None:
288 def get_content(self, response: requests.Response) -> Dict[str, Union[str, bytes, Dict[str, Any],
None]]:
290 Retrieve and parse content from an HTTP response based on its Content-Type.
293 response (requests.Response): The HTTP response from the server.
296 ValueError: If the response content is not valid JSON.
299 Dict[str, Union[str, bytes, Dict[str, Any], None]]: A dictionary with parsed response content.
301 - ACONST.CONTENT_TYPE_KEY: str - The content type of the response.
302 - ACONST.CONTENT_KEY: Union[Dict[str, Any], str, bytes, None] - Parsed content.
303 - JSON (application/json, application/ld+json) -> Dict
304 - Text (text/html, text/plain, text/csv, text/xml) -> str
305 - XML (application/xml) -> str
306 - Binary data (e.g., application/octet-stream, application/pdf) -> bytes
307 - None for unhandled types.
309 title =
"get_content"
313 node = content_type.split(
";")[0]
314 except UnknownContentTypeError
as e:
316 f
"Response content type is unknown, {e}", title
318 return {ACONST.CONTENT_TYPE_KEY:
None, ACONST.CONTENT_KEY:
None}
320 if node
in ACONST.CONTENT_TYPES_JSON:
322 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.json()}
323 except ValueError
as e:
324 raise ValueError(
"Response content is not valid JSON")
from e
325 elif node
in ACONST.CONTENT_TYPES_TEXT:
326 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.text}
327 elif node
in ACONST.CONTENT_TYPES_XML:
328 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.text}
329 elif node
in ACONST.CONTENT_TYPES_BINARY:
330 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.content}
331 elif node
in ACONST.CONTENT_TYPES_AUDIO:
332 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.content}
333 elif node
in ACONST.CONTENT_TYPES_IMAGES:
334 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.content}
335 elif node
in ACONST.CONTENT_TYPES_VIDEO:
336 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY: response.content}
338 self.
disp.log_error(f
"Unhandled content type: {content_type}")
339 return {ACONST.CONTENT_TYPE_KEY: content_type, ACONST.CONTENT_KEY:
None}
341 def compile_response_data(self, response: requests.Response) -> Dict[str, Union[int, Dict[str, Union[str, bytes, Dict[str, Any],
None]]]]:
343 Compile the response from an HTTP request into a dictionary.
346 response (requests.Response): The HTTP response from the server.
349 Dict[str, Union[int, Dict[str, Union[str, bytes, Dict[str, Any], None]]]: A dictionary with the response status code and content.
351 title =
"compile_response_data"
352 self.
disp.log_debug(
"Compiling response data", title)
353 self.
disp.log_debug(f
"response = {response}", title)
356 self.
disp.log_debug(f
"data = {data}", title)
357 compiled[ACONST.RESPONSE_NODE_BODY_KEY] = data[ACONST.CONTENT_KEY]
358 compiled[ACONST.RESPONSE_NODE_BODY_TYPE_KEY] = data[ACONST.CONTENT_TYPE_KEY]
359 compiled[ACONST.RESPONSE_NODE_STATUS_CODE_KEY] = response.status_code
360 compiled[ACONST.RESPONSE_NODE_HEADERS_KEY] = response.headers
361 compiled[ACONST.RESPONSE_NODE_HEADERS_TYPE_KEY] = type(
363 compiled[ACONST.RESPONSE_NODE_ENCODING_KEY] = response.encoding
364 compiled[ACONST.RESPONSE_NODE_HISTORY_KEY] = response.history
365 compiled[ACONST.RESPONSE_NODE_COOKIES_KEY] = response.cookies
366 compiled[ACONST.RESPONSE_NODE_ELAPSED_KEY] = response.elapsed
367 compiled[ACONST.RESPONSE_NODE_REASON_KEY] = response.reason
368 compiled[ACONST.RESPONSE_NODE_URL_KEY] = response.url
369 compiled[ACONST.RESPONSE_NODE_URL_KEY] = response.request.method
370 self.
disp.log_debug(f
"compiled = {compiled}", title)
Dict[str, Union[str, bytes, Dict[str, Any], None]] get_content(self, requests.Response response)
requests.Response put_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
requests.Response delete_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
int get_status(self, requests.Response response)
requests.Response post_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
Dict[str, Union[int, Dict[str, Union[str, bytes, Dict[str, Any], None]]]] compile_response_data(self, requests.Response response)
None __init__(self, str host="http://127.0.0.1", Union[int, None] port=6000, int delay=2, bool debug=False)
requests.Response head_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
str get_content_type(self, requests.Response response)
requests.Response patch_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
requests.Response get_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
requests.Response options_endpoint(self, str path, Union[Dict[str, Any], None] content=None, Union[Mapping[str, str], None] header=None)
None __init__(self, str message="No Content-Type found in the header")