diff --git a/CHANGES/1664.bugfix.rst b/CHANGES/1664.bugfix.rst new file mode 100644 index 00000000..9a4fb2a3 --- /dev/null +++ b/CHANGES/1664.bugfix.rst @@ -0,0 +1,25 @@ +Fix empty response into webhook. + +We need to return something “empty”, and “empty” form doesn’t work since +it’s sending only “end” boundary w/o “start”. + +An empty formdata should look smth like this for Telegram to understand: + +:: + + --webhookBoundaryvsF_aMHhspPjfOq7O0JNRg + --webhookBoundaryvsF_aMHhspPjfOq7O0JNRg-- + +But aiohttp sends only the ending boundary: + +:: + + --webhookBoundaryvsF_aMHhspPjfOq7O0JNRg-- + +Such response doesn't suit Telegram servers. + +The fix replaces empty response with empty JSON response: + +:: + + {} diff --git a/aiogram/webhook/aiohttp_server.py b/aiogram/webhook/aiohttp_server.py index 7caa0e15..a453c9d8 100644 --- a/aiogram/webhook/aiohttp_server.py +++ b/aiogram/webhook/aiohttp_server.py @@ -4,7 +4,7 @@ from abc import ABC, abstractmethod from asyncio import Transport from typing import Any, Awaitable, Callable, Dict, Optional, Set, Tuple, cast -from aiohttp import MultipartWriter, web +from aiohttp import JsonPayload, MultipartWriter, Payload, web from aiohttp.abc import Application from aiohttp.typedefs import Handler from aiohttp.web_middlewares import middleware @@ -151,13 +151,17 @@ class BaseRequestHandler(ABC): def _build_response_writer( self, bot: Bot, result: Optional[TelegramMethod[TelegramType]] - ) -> MultipartWriter: + ) -> Payload: + if not result: + # we need to return something "empty" + # and "empty" form doesn't work + # since it's sending only "end" boundary w/o "start" + return JsonPayload({}) + writer = MultipartWriter( "form-data", boundary=f"webhookBoundary{secrets.token_urlsafe(16)}", ) - if not result: - return writer payload = writer.append(result.__api_method__) payload.set_content_disposition("form-data", name="method") diff --git a/tests/test_webhook/test_aiohtt_server.py b/tests/test_webhook/test_aiohtt_server.py index f29895ba..c185b841 100644 --- a/tests/test_webhook/test_aiohtt_server.py +++ b/tests/test_webhook/test_aiohtt_server.py @@ -150,13 +150,9 @@ class TestSimpleRequestHandler: resp = await self.make_reqest(client=client, text="spam") assert resp.status == 200 - assert resp.content_type == "multipart/form-data" - result = {} - reader = MultipartReader.from_response(resp) - while part := await reader.next(): - value = await part.read() - result[part.name] = value.decode() - assert not result + assert resp.content_type == "application/json" + expected_result = {} + assert await resp.json() == expected_result async def test_reply_into_webhook_background(self, bot: MockedBot, aiohttp_client): app = Application()