Added more details when server send invalid response

This commit is contained in:
Alex Root Junior 2022-10-02 19:22:12 +03:00
parent 44ae565149
commit efae83d337
No known key found for this signature in database
GPG key ID: 074C1D455EBEA4AC
4 changed files with 56 additions and 3 deletions

1
CHANGES/1014.misc.rst Normal file
View file

@ -0,0 +1 @@
Added more detailed error when server response can't be deserialized. This feature will help to debug unexpected responses from the Server

View file

@ -7,7 +7,10 @@ from http import HTTPStatus
from types import TracebackType
from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Final, Optional, Type, Union, cast
from pydantic import ValidationError
from aiogram.exceptions import (
ClientDecodeError,
RestartingTelegram,
TelegramAPIError,
TelegramBadRequest,
@ -64,8 +67,19 @@ class BaseSession(abc.ABC):
"""
Check response status
"""
json_data = self.json_loads(content)
response = method.build_response(json_data)
try:
json_data = self.json_loads(content)
except Exception as e:
# Handled error type can't be classified as specific error
# in due to decoder can be customized and raise any exception
raise ClientDecodeError("Failed to decode object", e, content)
try:
response = method.build_response(json_data)
except ValidationError as e:
raise ClientDecodeError("Failed to deserialize object", e, json_data)
if HTTPStatus.OK <= status_code <= HTTPStatus.IM_USED and response.ok:
return response

View file

@ -1,4 +1,4 @@
from typing import Optional
from typing import Any, Optional
from aiogram.methods import TelegramMethod
from aiogram.methods.base import TelegramType
@ -104,3 +104,18 @@ class RestartingTelegram(TelegramServerError):
class TelegramEntityTooLarge(TelegramNetworkError):
url = "https://core.telegram.org/bots/api#sending-files"
class ClientDecodeError(AiogramError):
def __init__(self, message: str, original: Exception, data: Any) -> None:
self.message = message
self.original = original
self.data = data
def __str__(self) -> str:
original_type = type(self.original)
return (
f"{self.message}\n"
f"Caused from error: {original_type.__module__}.{original_type.__name__}: {self.original}\n"
f"Content: {self.data}"
)

View file

@ -8,6 +8,7 @@ from aiogram import Bot
from aiogram.client.session.base import BaseSession, TelegramType
from aiogram.client.telegram import PRODUCTION, TelegramAPIServer
from aiogram.exceptions import (
ClientDecodeError,
RestartingTelegram,
TelegramAPIError,
TelegramBadRequest,
@ -183,6 +184,28 @@ class TestBaseSession:
if error.url:
assert error.url in string
def test_check_response_json_decode_error(self):
session = CustomSession()
method = DeleteMessage(chat_id=42, message_id=42)
with pytest.raises(ClientDecodeError, match="JSONDecodeError"):
session.check_response(
method=method,
status_code=200,
content="is not a JSON object",
)
def test_check_response_validation_error(self):
session = CustomSession()
method = DeleteMessage(chat_id=42, message_id=42)
with pytest.raises(ClientDecodeError, match="ValidationError"):
session.check_response(
method=method,
status_code=200,
content='{"ok": "test"}',
)
async def test_make_request(self):
session = CustomSession()