''' 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 ) )