Skip to content

Commit c8c4034

Browse files
authored
Merge pull request #102 from pogzyb/do-max-depth
Make authoritative server querying optional
2 parents 27941d9 + 91a5fc5 commit c8c4034

File tree

3 files changed

+60
-35
lines changed

3 files changed

+60
-35
lines changed

asyncwhois/__init__.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@
4242
"GeneralError",
4343
"QueryError",
4444
]
45-
__version__ = "1.1.7"
45+
__version__ = "1.1.8"
4646

4747

4848
def whois(
4949
search_term: Union[str, ipaddress.IPv4Address, ipaddress.IPv6Address],
50-
authoritative_only: bool = False,
50+
authoritative_only: bool = False, # todo: deprecate and remove this argument
51+
find_authoritative_server: bool = True,
5152
ignore_not_found: bool = False,
5253
proxy_url: str = None,
5354
timeout: int = 10,
@@ -59,8 +60,11 @@ def whois(
5960
otherwise a DNS search is performed.
6061
6162
:param search_term: Any domain, URL, IPv4, or IPv6
62-
:param authoritative_only: If False (default), asyncwhois returns the entire WHOIS query chain,
63+
:param authoritative_only: DEPRECATED - If False (default), asyncwhois returns the entire WHOIS query chain,
6364
otherwise if True, only the authoritative response is returned.
65+
:param find_authoritative_server: This parameter only applies to domain queries. If True (default), asyncwhois
66+
will attempt to find the authoritative response, otherwise if False, asyncwhois will only query the whois server
67+
associated with the given TLD as specified in the IANA root db (`asyncwhois/servers/domains.py`).
6468
:param ignore_not_found: If False (default), the `NotFoundError` exception is raised if the query output
6569
contains "no such domain" language. If True, asyncwhois will not raise `NotFoundError` exceptions.
6670
:param proxy_url: Optional SOCKS4 or SOCKS5 proxy url (e.g. 'socks5://host:port')
@@ -85,6 +89,7 @@ def whois(
8589
except (ipaddress.AddressValueError, ValueError):
8690
return DomainClient(
8791
authoritative_only=authoritative_only,
92+
find_authoritative_server=find_authoritative_server,
8893
ignore_not_found=ignore_not_found,
8994
proxy_url=proxy_url,
9095
timeout=timeout,
@@ -140,7 +145,8 @@ def rdap(
140145

141146
async def aio_whois(
142147
search_term: str,
143-
authoritative_only: bool = False,
148+
authoritative_only: bool = False, # todo: deprecate and remove this argument
149+
find_authoritative_server: bool = True,
144150
ignore_not_found: bool = False,
145151
proxy_url: str = None,
146152
timeout: int = 10,
@@ -152,8 +158,11 @@ async def aio_whois(
152158
otherwise a DNS search is performed.
153159
154160
:param search_term: Any domain, URL, IPv4, or IPv6
155-
:param authoritative_only: If False (default), asyncwhois returns the entire WHOIS query chain,
161+
:param authoritative_only: DEPRECATED - If False (default), asyncwhois returns the entire WHOIS query chain,
156162
otherwise if True, only the authoritative response is returned.
163+
:param find_authoritative_server: This parameter only applies to domain queries. If True (default), asyncwhois
164+
will attempt to find the authoritative response, otherwise if False, asyncwhois will only query the whois server
165+
associated with the given TLD as specified in the IANA root db (`asyncwhois/servers/domains.py`).
157166
:param ignore_not_found: If False (default), the `NotFoundError` exception is raised if the query output
158167
contains "no such domain" language. If True, asyncwhois will not raise `NotFoundError` exceptions.
159168
:param proxy_url: Optional SOCKS4 or SOCKS5 proxy url (e.g. 'socks5://host:port')
@@ -182,6 +191,7 @@ async def aio_whois(
182191
proxy_url=proxy_url,
183192
timeout=timeout,
184193
tldextract_obj=tldextract_obj,
194+
find_authoritative_server=find_authoritative_server,
185195
).aio_whois(search_term)
186196
else:
187197
return "", {}

asyncwhois/client.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class DomainClient(Client):
4949
def __init__(
5050
self,
5151
authoritative_only: bool = False,
52+
find_authoritative_server: bool = True,
5253
ignore_not_found: bool = False,
5354
proxy_url: str = None,
5455
whodap_client: whodap.DNSClient = None,
@@ -61,7 +62,11 @@ def __init__(
6162
self.proxy_url = proxy_url
6263
self.timeout = timeout
6364
self.tldextract_obj = tldextract_obj
64-
self.query_obj = DomainQuery(proxy_url=proxy_url, timeout=timeout)
65+
self.query_obj = DomainQuery(
66+
proxy_url=proxy_url,
67+
timeout=timeout,
68+
find_authoritative_server=find_authoritative_server,
69+
)
6570
self.parse_obj = DomainParser(ignore_not_found=ignore_not_found)
6671

6772
def _get_domain_components(self, domain: str) -> tuple[str, str, str]:

asyncwhois/query.py

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@ class Query:
1919
refer_regex = r"refer: *(.+)"
2020
whois_server_regex = r".+ whois server: *(.+)"
2121

22-
def __init__(self, proxy_url: str = None, timeout: int = 10):
22+
def __init__(
23+
self,
24+
proxy_url: str = None,
25+
timeout: int = 10,
26+
find_authoritative_server: bool = True,
27+
):
2328
self.proxy_url = proxy_url
2429
self.timeout = timeout
30+
self.find_authoritative_server = find_authoritative_server
2531

2632
@staticmethod
2733
def _find_match(regex: str, blob: str) -> str:
@@ -117,6 +123,16 @@ def run(self, search_term: str, server: str = None) -> list[str]:
117123
server_regex = self.whois_server_regex
118124
return self._do_query(server, data, server_regex, [])
119125

126+
@staticmethod
127+
def _continue_querying(current_server: str, next_server: str) -> bool:
128+
next_server = next_server.lower()
129+
return (
130+
next_server
131+
and next_server != current_server
132+
and not next_server.startswith("http")
133+
and not next_server.startswith("www.")
134+
)
135+
120136
async def aio_run(self, search_term: str, server: str = None) -> list[str]:
121137
data = search_term + "\r\n"
122138
if not server:
@@ -141,19 +157,16 @@ def _do_query(
141157
query_output = self._send_and_recv(conn, data)
142158
# save query chain
143159
chain.append(query_output)
144-
# parse response for the referred WHOIS server name
145-
whois_server = self._find_match(regex, query_output)
146-
whois_server = whois_server.lower()
147-
if (
148-
whois_server
149-
and whois_server != server
150-
and not whois_server.startswith("http")
151-
and not whois_server.startswith("www.")
152-
):
153-
# recursive call to find more authoritative server
154-
chain = self._do_query(
155-
whois_server, data, self.whois_server_regex, chain
156-
)
160+
# if we should find the authoritative response,
161+
# then parse the response for the next server
162+
if self.find_authoritative_server:
163+
# parse response for the referred WHOIS server name
164+
whois_server = self._find_match(regex, query_output)
165+
if self._continue_querying(server, whois_server):
166+
# recursive call to find more authoritative server
167+
chain = self._do_query(
168+
whois_server, data, self.whois_server_regex, chain
169+
)
157170
# return the WHOIS query chain
158171
return chain
159172

@@ -171,20 +184,16 @@ async def _aio_do_query(
171184
self._aio_send_and_recv(reader, writer, data), self.timeout
172185
)
173186
chain.append(query_output)
174-
# parse response for the referred WHOIS server name
175-
whois_server = self._find_match(regex, query_output)
176-
whois_server = whois_server.lower()
177-
# check for another legitimate server name
178-
if (
179-
whois_server
180-
and whois_server != server
181-
and not whois_server.startswith("http")
182-
and not whois_server.startswith("www.")
183-
):
184-
# recursive call to find the authoritative server
185-
chain = await self._aio_do_query(
186-
whois_server, data, self.whois_server_regex, chain
187-
)
187+
# if we should find the authoritative response,
188+
# then parse the response for the next server
189+
if self.find_authoritative_server:
190+
# parse response for the referred WHOIS server name
191+
whois_server = self._find_match(regex, query_output)
192+
if self._continue_querying(server, whois_server):
193+
# recursive call to find more authoritative server
194+
chain = self._do_query(
195+
whois_server, data, self.whois_server_regex, chain
196+
)
188197
# return the WHOIS query chain
189198
return chain
190199

@@ -195,8 +204,9 @@ def __init__(
195204
server: str = None,
196205
proxy_url: str = None,
197206
timeout: int = 10,
207+
find_authoritative_server: bool = True,
198208
):
199-
super().__init__(proxy_url, timeout)
209+
super().__init__(proxy_url, timeout, find_authoritative_server)
200210
self.server = server
201211

202212
@staticmethod

0 commit comments

Comments
 (0)