Skip to content

Commit 9b0d43b

Browse files
authored
Backport aiohttp conditional HEAD bug workaround
1 parent ebad38c commit 9b0d43b

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

elasticsearch/_async/http_aiohttp.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import asyncio
1919
import os
20+
import re
2021
import ssl
2122
import warnings
2223

@@ -49,6 +50,15 @@
4950
except ImportError:
5051
pass
5152

53+
_version_parts = []
54+
for _version_part in aiohttp.__version__.split(".")[:3]:
55+
try:
56+
_version_parts.append(int(re.search(r"^([0-9]+)", _version_part).group(1))) # type: ignore[union-attr]
57+
except (AttributeError, ValueError):
58+
break
59+
_AIOHTTP_SEMVER_VERSION = tuple(_version_parts)
60+
_AIOHTTP_FIXED_HEAD_BUG = _AIOHTTP_SEMVER_VERSION >= (3, 7, 0)
61+
5262

5363
class AsyncConnection(Connection):
5464
"""Base class for Async HTTP connection implementations"""
@@ -247,11 +257,11 @@ async def perform_request(
247257
query_string = ""
248258
url_target = url_path
249259

250-
# There is a bug in aiohttp that disables the re-use
260+
is_head = False
261+
# There is a bug in aiohttp<3.7 that disables the re-use
251262
# of the connection in the pool when method=HEAD.
252263
# See: aio-libs/aiohttp#1769
253-
is_head = False
254-
if method == "HEAD":
264+
if method == "HEAD" and not _AIOHTTP_FIXED_HEAD_BUG:
255265
method = "GET"
256266
is_head = True
257267

test_elasticsearch/test_async/test_connection.py

+19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from mock import patch
3030
from multidict import CIMultiDict
3131

32+
import elasticsearch._async.http_aiohttp
3233
from elasticsearch import AIOHttpConnection, AsyncElasticsearch, __versionstr__
3334
from elasticsearch.compat import reraise_exceptions
3435
from elasticsearch.exceptions import ConnectionError, NotFoundError
@@ -56,6 +57,9 @@ async def __aenter__(self, *_, **__):
5657
async def __aexit__(self, *_, **__):
5758
pass
5859

60+
async def release(self):
61+
pass
62+
5963
async def text(self):
6064
return response_body.decode("utf-8", "surrogatepass")
6165

@@ -421,6 +425,21 @@ def request_raise(*_, **__):
421425
await conn.perform_request("GET", "/")
422426
assert str(e.value) == "Wasn't modified!"
423427

428+
@pytest.mark.parametrize("aiohttp_fixed_head_bug", [True, False])
429+
async def test_head_workaround(self, aiohttp_fixed_head_bug, monkeypatch):
430+
monkeypatch.setattr(
431+
elasticsearch._async.http_aiohttp,
432+
"_AIOHTTP_FIXED_HEAD_BUG",
433+
aiohttp_fixed_head_bug,
434+
)
435+
436+
con = await self._get_mock_connection()
437+
await con.perform_request("HEAD", "/anything")
438+
439+
method, url = con.session.request.call_args[0]
440+
assert method == "HEAD" if aiohttp_fixed_head_bug else "GET"
441+
assert url.human_repr() == "http://localhost:9200/anything"
442+
424443

425444
class TestConnectionHttpbin:
426445
"""Tests the HTTP connection implementations against a live server E2E"""

0 commit comments

Comments
 (0)