forked from ipinfo/python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.py
More file actions
93 lines (76 loc) · 3.38 KB
/
Copy pathhandler.py
File metadata and controls
93 lines (76 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
Main API client handler for fetching data from the IPinfo service.
"""
import ipaddress
import json
import os
import requests
import sys
from .cache.default import DefaultCache
from .details import Details
from .exceptions import RequestQuotaExceededError
class Handler:
"""
Allows client to request data for specified IP address. Instantiates and
and maintains access to cache.
"""
API_URL = 'https://ipinfo.io'
CACHE_MAXSIZE = 4096
CACHE_TTL = 60 * 60 * 24
COUNTRY_FILE_DEFAULT = 'countries.json'
REQUEST_TIMEOUT_DEFAULT = 2
def __init__(self, access_token=None, **kwargs):
"""Initialize the Handler object with country name list and the cache initialized."""
self.access_token = access_token
self.countries = self._read_country_names(kwargs.get('countries_file'))
self.request_options = kwargs.get('request_options', {})
if 'timeout' not in self.request_options:
self.request_options['timeout'] = self.REQUEST_TIMEOUT_DEFAULT
if 'cache' in kwargs:
self.cache = kwargs['cache']
else:
cache_options = kwargs.get('cache_options', {})
maxsize = cache_options.get('maxsize', self.CACHE_MAXSIZE)
ttl = cache_options.get('ttl', self.CACHE_TTL)
self.cache = DefaultCache(maxsize, ttl, **cache_options)
def getDetails(self, ip_address=None):
"""Get details for specified IP address as a Details object."""
raw_details = self._requestDetails(ip_address)
raw_details['country_name'] = self.countries.get(raw_details.get('country'))
raw_details['ip_address'] = ipaddress.ip_address(raw_details.get('ip'))
raw_details['latitude'], raw_details['longitude'] = self._read_coords(raw_details.get('loc'))
return Details(raw_details)
def _requestDetails(self, ip_address=None):
"""Get IP address data by sending request to IPinfo API."""
if ip_address not in self.cache:
url = self.API_URL
if ip_address:
url += '/' + ip_address
response = requests.get(url, headers=self._get_headers(), **self.request_options)
if response.status_code == 429:
raise RequestQuotaExceededError()
response.raise_for_status()
self.cache[ip_address] = response.json()
return self.cache[ip_address]
def _get_headers(self):
"""Built headers for request to IPinfo API."""
headers = {
'user-agent': 'IPinfoClient/Python{version}/1.0'.format(version=sys.version_info[0]),
'accept': 'application/json'
}
if self.access_token:
headers['authorization'] = 'Bearer {}'.format(self.access_token)
return headers
def _read_coords(self, location):
lat, lon = None, None
coords = tuple(location.split(',')) if location else ''
if len(coords) == 2 and coords[0] and coords[1]:
lat, lon = coords[0], coords[1]
return lat, lon
def _read_country_names(self, countries_file=None):
"""Read list of countries from specified country file or default file."""
if not countries_file:
countries_file = os.path.join(os.path.dirname(__file__), self.COUNTRY_FILE_DEFAULT)
with open(countries_file) as f:
countries_json = f.read()
return json.loads(countries_json)