Skip to content

Commit 58bae08

Browse files
Add METH_QUERY and treat QUERY as an idempotent method (aio-libs#13301)
1 parent 1297572 commit 58bae08

3 files changed

Lines changed: 29 additions & 2 deletions

File tree

aiohttp/client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,10 @@ class _WSConnectOptions(TypedDict, total=False):
216216

217217

218218
# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2
219-
IDEMPOTENT_METHODS = frozenset({"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE"})
219+
# https://www.rfc-editor.org/info/rfc10008/#section-1-12
220+
IDEMPOTENT_METHODS = frozenset(
221+
{"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE", "QUERY"}
222+
)
220223

221224
_RetType_co = TypeVar(
222225
"_RetType_co",

aiohttp/hdrs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
METH_PATCH: Final[str] = "PATCH"
1717
METH_POST: Final[str] = "POST"
1818
METH_PUT: Final[str] = "PUT"
19+
METH_QUERY: Final[str] = "QUERY"
1920
METH_TRACE: Final[str] = "TRACE"
2021

2122
METH_ALL: Final[set[str]] = {

tests/test_test_utils.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from yarl import URL
1313

1414
import aiohttp
15-
from aiohttp import web
15+
from aiohttp import hdrs, web
1616
from aiohttp.helpers import HeadersDictProxy
1717
from aiohttp.test_utils import (
1818
REUSE_ADDRESS,
@@ -356,6 +356,29 @@ async def handler(request: web.Request) -> web.Response:
356356
assert num_requests == 2
357357

358358

359+
async def test_retry_persistent_connection_query_method(
360+
aiohttp_client: AiohttpClient,
361+
) -> None:
362+
"""QUERY is safe and idempotent, so it must trigger retry."""
363+
num_requests = 0
364+
365+
async def handler(request: web.Request) -> web.Response:
366+
nonlocal num_requests
367+
num_requests += 1
368+
if num_requests == 1:
369+
request.protocol.force_close()
370+
return web.Response()
371+
372+
app = web.Application()
373+
app.router.add_route(hdrs.METH_QUERY, "/", handler)
374+
client = await aiohttp_client(app)
375+
client.session._retry_connection = True
376+
async with client.request(hdrs.METH_QUERY, "/") as resp:
377+
assert resp.status == 200
378+
379+
assert num_requests == 2
380+
381+
359382
async def test_server_context_manager(app: web.Application) -> None:
360383
async with TestServer(app) as server:
361384
async with aiohttp.ClientSession() as client:

0 commit comments

Comments
 (0)