fix empty response into webhook (#1665)

This commit is contained in:
Suren Khorenyan 2025-04-05 20:31:42 +03:00 committed by GitHub
parent 02683b8c37
commit 870d97c783
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 11 deletions

25
CHANGES/1664.bugfix.rst Normal file
View file

@ -0,0 +1,25 @@
Fix empty response into webhook.
We need to return something “empty”, and “empty” form doesnt work since
its 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:
::
{}

View file

@ -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")

View file

@ -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()