-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Requests with IPv6 Link-Local address and Zone Identifier fail #10314
Comments
Probably:
I guess it's a feature missing in aiodns. |
You should be able to use the ThreadedResolver explicitly in the connector as a workaround, which should get you the same behaviour as previous versions. |
It looks like proactor is being used on windows so unless aiodns is installed and selector event loop is being used, I think something else is going on here as I would expect ThreadedResolver is already being used in this case. |
Maybe related to #9032 |
Thank you for your quick responses. I think as @bdraco says the ThreadedResolver is being used by default. If I use the AsyncResolver it seems to work. (other changes in code from the earlier example are to get it working on my specific setup with uv to manage dependencies and a self signed certificate on the server etc). #!/usr/bin/env python3
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "aiodns",
# "aiohttp",
# "termcolor",
# "websockets",
# "winloop",
# ]
# ///
import asyncio
import ssl
import sys
import aiohttp
from aiohttp.resolver import AsyncResolver
async def get_serial():
url = "https://[fe80::255:daff:fe40:6158%5]:8092/SerialNumber"
headers = {'Content-Type': 'application/json'}
print(f"Attempting to GET {url}")
resolver = AsyncResolver()
conn = aiohttp.TCPConnector(resolver=resolver, ssl=False)
async with aiohttp.ClientSession(connector=conn) as session:
async with session.get(url, headers=headers ) as resp:
if resp.status != 200:
raise ResponseError(f"Received unexpected response {resp.status} from {url}")
parsed = await resp.json()
print(f"Server has serial number {parsed['SerialNumber']}")
if __name__ == "__main__":
if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(get_serial()) I can use this as a work around for now though. |
Scratch that it's not quite working as a workaround in my larger codebase for a seemingly unrelated reason - a large post request (>100MB) seems to now stall and get a 400 response from our server after switching to AsyncResolver. |
Sorry for sending so many updates. But this is getting weirder. If I explicitly set ThreadedResolver but use WindowsSelectorEventLoopPolicy it seems to work: #!/usr/bin/env python3
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "aiohttp",
# "termcolor",
# "websockets",
# "winloop",
# ]
# ///
import asyncio
import ssl
import sys
import aiohttp
from aiohttp.resolver import ThreadedResolver
async def get_serial():
url = "https://[fe80::255:daff:fe40:6158%5]:8092/SerialNumber"
headers = {'Content-Type': 'application/json'}
print(f"Attempting to GET {url}")
resolver = ThreadedResolver()
conn = aiohttp.TCPConnector(resolver=resolver, ssl=False)
async with aiohttp.ClientSession(connector=conn) as session:
async with session.get(url, headers=headers ) as resp:
if resp.status != 200:
raise ResponseError(f"Received unexpected response {resp.status} from {url}")
parsed = await resp.json()
print(f"Server has serial number {parsed['SerialNumber']}")
if __name__ == "__main__":
if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
pass
asyncio.run(get_serial()) But if I comment out
If I run under WSL (mirrored mode networking) with the original code but using |
Describe the bug
With aiohttp versions from 3.10 onwards, HTTP client requests to IPv6 link-local addresses with Zone Identifiers no longer work.
Previous versions (3.7 and 3.9 tested) work when using zone Identifiers.
I can't see any information about this change in behaviour in the changelogs so I think it is a bug.
IPv6 Zone identifiers in address literals/URIs are described in RFC6874. They specify a specific network interface to use when communicating with scoped IPv6 addresses wiki. On windows the interface is identified by the ifIndex from Get-NetAdapter in Powershell, in Linux it is the interface name.
In previous versions a request to a URL of the form
https://[fe80::255:daff:fe40:6158%5]:8092/SerialNumber
would work (although it should be noted that this is not actually RFC compliant as the % literal is not escaped as %25).In current versions the request times out without sending any packets (checked in wireshark) and a
aiohttp.client_exceptions.ClientConnectorError
is raised.To Reproduce
fe80::
).Expected behavior
A HTTP request is sent to the server and the response is received correctly.
Logs/tracebacks
Python Version
3.13.1
aiohttp Version
3.11.11
multidict Version
6.1.0
propcache Version
0.2.1
yarl Version
1.18.3
OS
Windows 11
Related component
Client
Additional context
This behaviour is observed using IPv6 link local addresses which are on the local network. The internet and proxies etc are not involved.
My specific test case uses https as our server requires SSL with a self signed certificate but I don't think this is related to the issue as no network packets are ever being sent.
Code of Conduct
The text was updated successfully, but these errors were encountered: