diff --git a/roles/geoip-city-wsgi/app/files/geoip-city.wsgi b/roles/geoip-city-wsgi/app/files/geoip-city.wsgi index 94358205aa..dc5822c428 100755 --- a/roles/geoip-city-wsgi/app/files/geoip-city.wsgi +++ b/roles/geoip-city-wsgi/app/files/geoip-city.wsgi @@ -11,14 +11,14 @@ # accelerator) in front of the application server running this WSGI, # to avoid looking "behind" the real client's own forward HTTP proxy. -from string import zfill, atoi, strip, replace from paste.wsgiwrappers import * -import GeoIP +from iso3166 import countries +import geoip2.database +import geoip2.errors import json global gi -gi = GeoIP.open("/usr/share/GeoIP/GeoLiteCity.dat", GeoIP.GEOIP_STANDARD) -gi.set_charset(GeoIP.GEOIP_CHARSET_UTF8) +gi = geoip2.database.Reader("/usr/share/GeoIP/GeoLite2-City.mmdb") def real_client_ip(xforwardedfor): @@ -32,18 +32,18 @@ def get_client_ip(environ, request): request_data = request.GET if 'ip' in request_data: - client_ip = strip(request_data['ip']) + client_ip = request_data['ip'].strip() elif 'X-Forwarded-For' in request.headers and 'geoip_city.noreverseproxy' not in environ: - client_ip = real_client_ip(strip(request.headers['X-Forwarded-For'])) + client_ip = real_client_ip(request.headers['X-Forwarded-For'].strip()) else: client_ip = request.environ['REMOTE_ADDR'] - client_ip = unicode(client_ip, 'utf8', 'replace') return client_ip def application(environ, start_response): request = WSGIRequest(environ) response = WSGIResponse() + results = {} code = 500 try: @@ -51,15 +51,39 @@ def application(environ, start_response): if client_ip is None: code = 400 raise Exception - results = gi.record_by_addr(client_ip) - if results is None: + data = gi.city(client_ip) + if data is None: code = 404 raise Exception + except geoip2.errors.AddressNotFoundError: + response.status_code = 404 + return response(environ, start_response) except: response.status_code=code return response(environ, start_response) results['ip'] = client_ip + + # map geoip2 data to a structure that matches the prior geoip format + results['city'] = data.city.name + results['region_name'] = data.subdivisions.most_specific.name + results['region'] = data.subdivisions.most_specific.iso_code + results['postal_code'] = data.postal.code + results['country_name'] = data.country.name + results['country_code'] = data.country.iso_code + results['time_zone'] = data.location.time_zone + results['latitude'] = data.location.latitude + results['longitude'] = data.location.longitude + results['metro_code'] = data.location.metro_code + results['dma_code'] = data.location.metro_code + + # geoip2 no longer includes country_code3, so it has to be pulled + # from iso3166.countries + if data.country.iso_code in countries: + results['country_code3'] = countries[data.country.iso_code].alpha3 + else: + results['country_code3'] = None + results = json.dumps(results) response.headers['Content-Length'] = str(len(results)) response.write(results) diff --git a/roles/geoip-city-wsgi/app/tasks/main.yml b/roles/geoip-city-wsgi/app/tasks/main.yml index 3f0fea39ed..8f2e512fa5 100644 --- a/roles/geoip-city-wsgi/app/tasks/main.yml +++ b/roles/geoip-city-wsgi/app/tasks/main.yml @@ -3,23 +3,14 @@ # # This is the role for geoip-city-wsgi. # -# install python-paste-deploy -- name: install python-paste-deploy - package: name=python-paste-deploy state=present - tags: - - packages - - geoip-city-wsgi - - geoip-city-wsgi/app - -- name: install GeoIP-data - package: name=GeoIP-data state=present - tags: - - packages - - geoip-city-wsgi - - geoip-city-wsgi/app - -- name: link the data file to the one we use - file: state=link dest=/usr/share/GeoIP/GeoIPCity.dat src=/usr/share/GeoIP/GeoLiteCity.dat +# install necessary packages +- name: install python-paste-deploy geolite2-city python2-iso3166 + package: + name: + - python-paste-deploy + - geolite2-city + - python2-iso3166 + state: present - name: install geoip-city-wsgi.conf file copy: >