How to reliably get peer IP address when using aiohttp client? #13293
Replies: 2 comments 2 replies
|
Your observation is correct: there is currently no fully public API that For short responses, registering the EOF callback can immediately call A practical workaround is to use the documented from typing import Any
import aiohttp
class PeerAwareResponse(aiohttp.ClientResponse):
peername: object | None = None
async def start(self, connection: Any) -> aiohttp.ClientResponse:
transport = connection.transport
if transport is not None:
self.peername = transport.get_extra_info("peername")
return await super().start(connection)
async with aiohttp.ClientSession(
response_class=PeerAwareResponse,
) as session:
async with session.request(method, url, **kwargs) as response:
raw_bytes = await response.read()
peername = response.peername
used_ip = (
peername[0]
if isinstance(peername, tuple) and peername
else None
)Capture before This also records each redirect hop because every for hop in (*response.history, response):
print(hop.url, hop.peername)I tested the reproducer against aiohttp 3.14.3 with two short responses on one Two operational caveats:
Source paths checked on current Verification disclosure: I used OpenAI Codex to inspect the current aiohttp |
|
The reason the The reliable place to read it is the connector, not the response. import contextvars, aiohttp
peer_ip: contextvars.ContextVar = contextvars.ContextVar("peer_ip", default=None)
class PeerIPConnector(aiohttp.TCPConnector):
async def connect(self, req, traces, timeout):
conn = await super().connect(req, traces, timeout)
peername = conn.transport.get_extra_info("peername") if conn.transport else None
if peername:
peer_ip.set(peername[0])
return connasync with aiohttp.ClientSession(connector=PeerIPConnector()) as session:
async with session.get(url) as resp:
body = await resp.read()
used_ip = peer_ip.get() # set reliably, even for a 2-byte bodyWhy this holds up where the response-side trick doesn't:
Tested on aiohttp 3.14.3: new + pooled connections, 2-byte vs 200 KB bodies, and 25 concurrent requests — |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Please note that the solutions you're likely to run into in google searches and AI are not reliable, and this is why I am asking here.
cc @asvetlov
Knowing peer IP and being able to log it is critical for diagnostics in production systems.
Here is what I tried which isn't reliable:
The above isn't reliable because when the response is pretty short such that it's completely read by the time that
session.request(method=method, url=url, **kwargs) as response:context is entered,response.connectionis already None, so it's impossible to get the peer IP address using the above technique.What is a reliable technique for obtaining the peer IP which was used in the request?
All reactions