nuvolaris/ip_util.py (37 lines of code) (raw):

# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import logging from backoff import expo, on_exception from requests import get from requests.exceptions import RequestException # The maximum amount of tries to attempt when making API calls. MAX_TRIES = 3 class IpUtil: _machine_ip = None def __init__(self): self.IPIFY_API_URI = 'https://api.ipify.org' self.IP_INFO_API_URI = 'https://ipinfo.io/ip' self.IDENT_ME_API_URI = 'https://4.ident.me/' self.USER_AGENT = 'nuvolaris-ip-resolver' # The maximum amount of tries to attempt when making API calls. self.MAX_TRIES = 3 @on_exception(expo, RequestException, max_tries=MAX_TRIES) def _get_ip_resp(self,api_uri: str): """ Internal function which attempts to retrieve this machine's public IP address from a service running at the given api_uri parameter. :rtype: obj :returns: The response object from the HTTP request. :raises: RequestException if something bad happened and the request wasn't completed. .. note:: If an error occurs when making the HTTP request, it will be retried using an exponential backoff algorithm. This is a safe way to retry failed requests without giving up. """ logging.debug(f"querying ip from {api_uri}") return get(api_uri, headers={'user-agent': self.USER_AGENT}) def handle_ip_request(self,url, extra=None): """ Query a public api returning the machine's public ip address >>> from nuvolaris.ip_util import IpUtil >>> ip_util = IpUtil() >>> ipify_ip = ip_util.handle_ip_request('https://api.ipify.org') >>> ifinfo_ip = ip_util.handle_ip_request('https://ipinfo.io/ip') >>> identme_ip = ip_util.handle_ip_request('https://4.ident.me/') >>> ipify_ip == ifinfo_ip True >>> ipify_ip == identme_ip True """ try: resp = self._get_ip_resp(url) except RequestException as e: logging.error(e) return None if resp.status_code != 200: logging.error('Received an invalid status code from ip service:' + str(resp.status_code) + '. The service might be experiencing issues.') return None return resp.text def get_ip_chain(self, url): if not self._machine_ip: self._machine_ip = self.handle_ip_request(url) else : logging.info(f"current ip address {self._machine_ip}") def get_public_ip(self): """ Attempt to get the machine public ip >>> from nuvolaris.ip_util import IpUtil >>> ip_util = IpUtil() >>> ip = ip_util.get_public_ip() >>> ip != None True >>> ipify_ip = ip_util.handle_ip_request('https://api.ipify.org') >>> ip == ipify_ip True """ self.get_ip_chain(self.IPIFY_API_URI) self.get_ip_chain(self.IP_INFO_API_URI) self.get_ip_chain(self.IDENT_ME_API_URI) return self._machine_ip