22
33import os
44from typing import Optional
5+ from urllib import error as urllib_error
56from urllib import request as urllib_request
67
78import netaddr
@@ -13,6 +14,22 @@ class ExternalIPNotFound(Exception):
1314 """Raised if we cannot attain your external ip from CURL/URLLIB/IPIFY/AWS"""
1415
1516
17+ # Exceptions each provider in `get_external_ip` can raise on failure. Caught per
18+ # provider so that a single failing lookup falls through to the next one instead
19+ # of crashing the whole function. Kept as a tuple so the list stays consistent
20+ # across providers.
21+ _IP_LOOKUP_EXCEPTIONS = (
22+ requests .exceptions .RequestException ,
23+ netaddr .core .AddrFormatError ,
24+ OSError ,
25+ urllib_error .URLError ,
26+ ValueError ,
27+ KeyError ,
28+ AssertionError ,
29+ ExternalIPNotFound ,
30+ )
31+
32+
1633def int_to_ip (int_val : int ) -> str :
1734 """Maps an integer to a unique ip-string
1835
@@ -68,7 +85,7 @@ def get_external_ip() -> str:
6885 external_ip = requests .get ("https://checkip.amazonaws.com" ).text .strip ()
6986 assert isinstance (ip_to_int (external_ip ), int )
7087 return str (external_ip )
71- except ExternalIPNotFound :
88+ except _IP_LOOKUP_EXCEPTIONS :
7289 pass
7390
7491 # --- Try ipconfig.
@@ -78,7 +95,7 @@ def get_external_ip() -> str:
7895 process .close ()
7996 assert isinstance (ip_to_int (external_ip ), int )
8097 return str (external_ip )
81- except ExternalIPNotFound :
98+ except _IP_LOOKUP_EXCEPTIONS :
8299 pass
83100
84101 # --- Try ipinfo.
@@ -88,7 +105,7 @@ def get_external_ip() -> str:
88105 process .close ()
89106 assert isinstance (ip_to_int (external_ip ), int )
90107 return str (external_ip )
91- except ExternalIPNotFound :
108+ except _IP_LOOKUP_EXCEPTIONS :
92109 pass
93110
94111 # --- Try myip.dnsomatic
@@ -98,23 +115,23 @@ def get_external_ip() -> str:
98115 process .close ()
99116 assert isinstance (ip_to_int (external_ip ), int )
100117 return str (external_ip )
101- except ExternalIPNotFound :
118+ except _IP_LOOKUP_EXCEPTIONS :
102119 pass
103120
104121 # --- Try urllib ipv6
105122 try :
106123 external_ip = urllib_request .urlopen ("https://ident.me" ).read ().decode ("utf8" )
107124 assert isinstance (ip_to_int (external_ip ), int )
108125 return str (external_ip )
109- except ExternalIPNotFound :
126+ except _IP_LOOKUP_EXCEPTIONS :
110127 pass
111128
112129 # --- Try Wikipedia
113130 try :
114131 external_ip = requests .get ("https://www.wikipedia.org" ).headers ["X-Client-IP" ]
115132 assert isinstance (ip_to_int (external_ip ), int )
116133 return str (external_ip )
117- except ExternalIPNotFound :
134+ except _IP_LOOKUP_EXCEPTIONS :
118135 pass
119136
120137 raise ExternalIPNotFound
0 commit comments