From e2c9a1fcd8f69084a9dd250957cea564e2c46491 Mon Sep 17 00:00:00 2001 From: lumi-tip Date: Wed, 1 Oct 2025 16:16:44 -0400 Subject: [PATCH] adding try catch to linked services in order to include timeout requests --- src/linked_services/core/service.py | 531 +++++++++++++++++----------- 1 file changed, 333 insertions(+), 198 deletions(-) diff --git a/src/linked_services/core/service.py b/src/linked_services/core/service.py index c4bbb1c..59dfbd0 100644 --- a/src/linked_services/core/service.py +++ b/src/linked_services/core/service.py @@ -83,6 +83,8 @@ def _sync_proxy(self, request: Callable[[], requests.Response], stream: bool) -> try: response = request() + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") except Exception as e: raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") @@ -142,9 +144,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_options(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -162,9 +168,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_head(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -182,9 +192,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_post(self, url, data=None, json=None, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -202,9 +216,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_webhook(self, url, data=None, json=None, **kwargs): url = self.app.webhook_url @@ -222,9 +240,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_put(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -242,9 +264,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_patch(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -262,9 +288,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_delete(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -282,9 +312,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _sync_request(self, method, url, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -302,9 +336,13 @@ def request() -> requests.Response: if self.proxy: return self._sync_proxy(request, kwargs.get("stream", False)) - res = request() - - return res + try: + res = request() + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") else: @@ -353,6 +391,8 @@ async def _async_proxy(self, response: Coroutine[Any, Any, ClientResponse]) -> H try: r = await response + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") except Exception as e: raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") @@ -378,190 +418,235 @@ def _async_get(self, url, params=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("get", params=params, **kwargs) - obj = self.session.get(url, params=params, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.get(url, params=params, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: GET") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: GET") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_options(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("options", **kwargs) - obj = self.session.options(url, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.options(url, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: OPTIONS") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: OPTIONS") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_head(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("head", **kwargs) - obj = self.session.head(url, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.head(url, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: HEAD") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: HEAD") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_post(self, url, data=None, json=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("post", data=data, json=json, **kwargs) - obj = self.session.post(url, data=data, json=json, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.post(url, data=data, json=json, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: POST") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: POST") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_webhook(self, url, data=None, json=None, **kwargs): url = self.app.webhook_url headers = self._authenticate("post", data=data, json=json, **kwargs) - obj = self.session.post(url, data=data, json=json, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.post(url, data=data, json=json, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Type: Webhook") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Type: Webhook") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_put(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("put", data=data, **kwargs) - obj = self.session.put(url, data=data, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.put(url, data=data, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: PUT") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: PUT") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_patch(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("patch", data=data, **kwargs) - obj = self.session.patch(url, data=data, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.patch(url, data=data, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: PATCH") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: PATCH") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_delete(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("delete", **kwargs) - obj = self.session.delete(url, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.delete(url, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: DELETE") - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: DELETE") + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") def _async_request(self, method, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate(method, **kwargs) - obj = self.session.request(method, url, **kwargs, headers=headers) - self.to_close.append(obj) + try: + obj = self.session.request(method, url, **kwargs, headers=headers) + self.to_close.append(obj) - res = obj.__aenter__() + res = obj.__aenter__() - if DEBUG: - print("Request") - print(" Method: " + str(method).upper()) - print(" Url: " + str(url)) - print("") + if DEBUG: + print("Request") + print(" Method: " + str(method).upper()) + print(" Url: " + str(url)) + print("") - # wraps client response to be used within django views - if self.proxy: - return self._async_proxy(res) + # wraps client response to be used within django views + if self.proxy: + return self._async_proxy(res) - return res + return res + except aiohttp.ServerTimeoutError as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") elif LIBRARIES["requests"]: @@ -583,41 +668,46 @@ async def __aexit__(self, *args, **kwargs) -> None: pass def _async_proxy(self, response: requests.Response, stream: bool) -> StreamingHttpResponse: - header_keys = [x for x in response.headers.keys() if x not in self.banned_keys] + try: + header_keys = [x for x in response.headers.keys() if x not in self.banned_keys] - if stream: - resource = StreamingHttpResponse( - response.raw, - status=response.status_code, - reason=response.reason, - ) + if stream: + resource = StreamingHttpResponse( + response.raw, + status=response.status_code, + reason=response.reason, + ) + + for header in header_keys: + resource[header] = response.headers[header] + + if DEBUG: + print("Response") + print(" Content: no visible due to it's a stream") + print(" Headers: " + str(response.headers)) + print(" Status code: " + str(response.status_code)) + print("") + + return resource + + headers = {} for header in header_keys: - resource[header] = response.headers[header] + headers[header] = response.headers[header] if DEBUG: print("Response") - print(" Content: no visible due to it's a stream") - print(" Headers: " + str(response.headers)) + print(" Type: Proxy") + print(" Content: " + response.content.decode()) + print(" Headers: " + str(headers)) print(" Status code: " + str(response.status_code)) print("") - return resource - - headers = {} - - for header in header_keys: - headers[header] = response.headers[header] - - if DEBUG: - print("Response") - print(" Type: Proxy") - print(" Content: " + response.content.decode()) - print(" Headers: " + str(headers)) - print(" Status code: " + str(response.status_code)) - print("") - - return HttpResponse(response.content, status=response.status_code, headers=headers) + return HttpResponse(response.content, status=response.status_code, headers=headers) + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_get(self, url, params=None, **kwargs): url = self.app.app_url + self._fix_url(url) @@ -626,92 +716,137 @@ async def _async_get(self, url, params=None, **kwargs): params = kwargs.pop("params", None) headers = self._authenticate("get", params=params, **kwargs) - res = requests.get(url, params=params, **kwargs, headers=headers) + try: + res = requests.get(url, params=params, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_options(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("options", **kwargs) - res = requests.options(url, **kwargs, headers=headers) + try: + res = requests.options(url, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_head(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("head", **kwargs) - res = requests.head(url, **kwargs, headers=headers) + try: + res = requests.head(url, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_post(self, url, data=None, json=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("post", data=data, json=json, **kwargs) - res = requests.post(url, data=data, json=json, **kwargs, headers=headers) + try: + res = requests.post(url, data=data, json=json, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_webhook(self, url, data=None, json=None, **kwargs): url = self.app.webhook_url headers = self._authenticate("post", data=data, json=json, **kwargs) - res = requests.post(url, data=data, json=json, **kwargs, headers=headers) + try: + res = requests.post(url, data=data, json=json, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_put(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("put", data=data, **kwargs) - res = requests.put(url, data=data, **kwargs, headers=headers) + try: + res = requests.put(url, data=data, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_patch(self, url, data=None, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("patch", data=data, **kwargs) - res = requests.patch(url, data=data, **kwargs, headers=headers) + try: + res = requests.patch(url, data=data, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_delete(self, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate("delete", **kwargs) - res = requests.delete(url, **kwargs, headers=headers) + try: + res = requests.delete(url, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") async def _async_request(self, method, url, **kwargs): url = self.app.app_url + self._fix_url(url) headers = self._authenticate(method, **kwargs) - res = requests.request(method, url, **kwargs, headers=headers) + try: + res = requests.request(method, url, **kwargs, headers=headers) - if self.proxy: - return self._async_proxy(res, kwargs.get("stream", False)) + if self.proxy: + return self._async_proxy(res, kwargs.get("stream", False)) - return res + return res + except requests.exceptions.Timeout as e: + raise ValidationException("Request timeout", code=408, slug="timeout") + except Exception as e: + raise ValidationException("Unexpected error: " + str(e), code=500, slug="unexpected-error") else: @@ -871,4 +1006,4 @@ def request(self, method, url, **kwargs): class AppNotFound(Exception): - pass + pass \ No newline at end of file