import socket | |
import struct | |
from typing import Optional | |
from urllib.parse import urlparse | |
def is_loopback(address): | |
host: Optional[str] = None | |
try: | |
parsed_url = urlparse(address) | |
host = parsed_url.hostname | |
except ValueError: | |
return False # url is not even a url | |
loopback_checker = { | |
socket.AF_INET: lambda x: struct.unpack("!I", socket.inet_aton(x))[0] | |
>> (32 - 8) | |
== 127, | |
socket.AF_INET6: lambda x: x == "::1", | |
} | |
for family in (socket.AF_INET, socket.AF_INET6): | |
try: | |
r = socket.getaddrinfo(host, None, family, socket.SOCK_STREAM) | |
except socket.gaierror: | |
continue | |
for family, _, _, _, sockaddr in r: | |
if loopback_checker[family](sockaddr[0]): | |
return True | |
if host in ("localhost",): | |
return True | |
return False | |