mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 10:11:52 +00:00
Added more details when server send invalid response
This commit is contained in:
parent
44ae565149
commit
efae83d337
4 changed files with 56 additions and 3 deletions
1
CHANGES/1014.misc.rst
Normal file
1
CHANGES/1014.misc.rst
Normal 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
|
||||||
|
|
@ -7,7 +7,10 @@ from http import HTTPStatus
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Final, Optional, Type, Union, cast
|
from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Final, Optional, Type, Union, cast
|
||||||
|
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from aiogram.exceptions import (
|
from aiogram.exceptions import (
|
||||||
|
ClientDecodeError,
|
||||||
RestartingTelegram,
|
RestartingTelegram,
|
||||||
TelegramAPIError,
|
TelegramAPIError,
|
||||||
TelegramBadRequest,
|
TelegramBadRequest,
|
||||||
|
|
@ -64,8 +67,19 @@ class BaseSession(abc.ABC):
|
||||||
"""
|
"""
|
||||||
Check response status
|
Check response status
|
||||||
"""
|
"""
|
||||||
json_data = self.json_loads(content)
|
try:
|
||||||
response = method.build_response(json_data)
|
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:
|
if HTTPStatus.OK <= status_code <= HTTPStatus.IM_USED and response.ok:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from aiogram.methods import TelegramMethod
|
from aiogram.methods import TelegramMethod
|
||||||
from aiogram.methods.base import TelegramType
|
from aiogram.methods.base import TelegramType
|
||||||
|
|
@ -104,3 +104,18 @@ class RestartingTelegram(TelegramServerError):
|
||||||
|
|
||||||
class TelegramEntityTooLarge(TelegramNetworkError):
|
class TelegramEntityTooLarge(TelegramNetworkError):
|
||||||
url = "https://core.telegram.org/bots/api#sending-files"
|
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}"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from aiogram import Bot
|
||||||
from aiogram.client.session.base import BaseSession, TelegramType
|
from aiogram.client.session.base import BaseSession, TelegramType
|
||||||
from aiogram.client.telegram import PRODUCTION, TelegramAPIServer
|
from aiogram.client.telegram import PRODUCTION, TelegramAPIServer
|
||||||
from aiogram.exceptions import (
|
from aiogram.exceptions import (
|
||||||
|
ClientDecodeError,
|
||||||
RestartingTelegram,
|
RestartingTelegram,
|
||||||
TelegramAPIError,
|
TelegramAPIError,
|
||||||
TelegramBadRequest,
|
TelegramBadRequest,
|
||||||
|
|
@ -183,6 +184,28 @@ class TestBaseSession:
|
||||||
if error.url:
|
if error.url:
|
||||||
assert error.url in string
|
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):
|
async def test_make_request(self):
|
||||||
session = CustomSession()
|
session = CustomSession()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue