59 lines
1.7 KiB
Python

'''
Simple Geolocation with FastAPI
'''
from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network
from typing import Annotated, Optional, Union
import geoip2.database
from fastapi import FastAPI, Path
from pydantic import BaseModel
app = FastAPI()
GEOLITE2_ASN_DB = '/usr/local/share/GeoIP/GeoLite2-ASN.mmdb'
GEOLITE2_CITY_DB = '/usr/local/share/GeoIP/GeoLite2-City.mmdb'
class Locality(BaseModel):
'''
Locality data
'''
city: Optional[str]
country: Optional[str]
continent: Optional[str]
is_eu: bool
class GeoLocation(BaseModel):
'''
Geolocation data model
'''
ip: Union[IPv6Address,IPv4Address]
asn: Optional[int]
asn_org: Optional[str]
network: Union[IPv6Network,IPv4Network,None]
locality: Locality
@app.get("/{ipaddress}")
async def root(ipaddress: Annotated[Union[IPv4Address,IPv6Address],
Path(title="The IPAddress to geolocate")]
) -> GeoLocation:
'''
Look up geolocation for ip in path parameter
'''
with (geoip2.database.Reader(GEOLITE2_ASN_DB) as reader_asn,
geoip2.database.Reader(GEOLITE2_CITY_DB) as reader_city):
asn_data = reader_asn.asn(ipaddress)
city_data = reader_city.city(ipaddress)
return GeoLocation(
ip=ipaddress,
asn=asn_data.autonomous_system_number,
asn_org=asn_data.autonomous_system_organization,
network=asn_data.network,
locality=Locality(
city=city_data.city.name,
country=city_data.country.iso_code,
continent=city_data.continent.code,
is_eu=city_data.country.is_in_european_union
)
)