Compare commits
5 Commits
d090e90ee2
...
main
Author | SHA1 | Date | |
---|---|---|---|
98643f9a69
|
|||
e77e4dc174
|
|||
a95dfaae2b | |||
4eb906f6d4
|
|||
878a2b6bbf
|
17
.gitea/workflows/flake8.yml
Normal file
17
.gitea/workflows/flake8.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Flake8
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
|
||||||
|
# XXX need to do stuff with uv
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: freebsd
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.11"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Analyse code with Flake8
|
||||||
|
run: |
|
||||||
|
flake8 $(git ls-files '*.py')
|
17
.gitea/workflows/mypy.yml
Normal file
17
.gitea/workflows/mypy.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Mypy
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
|
||||||
|
# XXX need to do stuff with uv
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: freebsd
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.11"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Analyse code with Mypy
|
||||||
|
run: |
|
||||||
|
mypy --install-types --non-interactive $(git ls-files '*.py')
|
17
.gitea/workflows/pylint.yml
Normal file
17
.gitea/workflows/pylint.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Pylint
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
|
||||||
|
# XXX need to do stuff with uv
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: freebsd
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.11"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Analyse code with Pylint
|
||||||
|
run: |
|
||||||
|
pylint $(git ls-files '*.py')
|
13
app/main.py
13
app/main.py
@ -15,12 +15,14 @@ app = FastAPI()
|
|||||||
GEOLITE2_ASN_DB = '/usr/local/share/GeoIP/GeoLite2-ASN.mmdb'
|
GEOLITE2_ASN_DB = '/usr/local/share/GeoIP/GeoLite2-ASN.mmdb'
|
||||||
GEOLITE2_CITY_DB = '/usr/local/share/GeoIP/GeoLite2-City.mmdb'
|
GEOLITE2_CITY_DB = '/usr/local/share/GeoIP/GeoLite2-City.mmdb'
|
||||||
|
|
||||||
|
|
||||||
class IPAddressParam(BaseModel):
|
class IPAddressParam(BaseModel):
|
||||||
'''
|
'''
|
||||||
Payload entry as used in POST
|
Payload entry as used in POST
|
||||||
'''
|
'''
|
||||||
ip: Union[IPv6Address, IPv4Address]
|
ip: Union[IPv6Address, IPv4Address]
|
||||||
|
|
||||||
|
|
||||||
class Locality(BaseModel):
|
class Locality(BaseModel):
|
||||||
'''
|
'''
|
||||||
Locality data
|
Locality data
|
||||||
@ -30,6 +32,7 @@ class Locality(BaseModel):
|
|||||||
continent: Optional[str] = None
|
continent: Optional[str] = None
|
||||||
is_eu: bool = False
|
is_eu: bool = False
|
||||||
|
|
||||||
|
|
||||||
class GeoLocation(BaseModel):
|
class GeoLocation(BaseModel):
|
||||||
'''
|
'''
|
||||||
Geolocation data model
|
Geolocation data model
|
||||||
@ -40,8 +43,10 @@ class GeoLocation(BaseModel):
|
|||||||
network: Optional[Union[IPv6Network, IPv4Network]] = None
|
network: Optional[Union[IPv6Network, IPv4Network]] = None
|
||||||
locality: Locality = Locality()
|
locality: Locality = Locality()
|
||||||
|
|
||||||
|
|
||||||
@app.post("/")
|
@app.post("/")
|
||||||
async def root_post(ipaddresses: Annotated[list[IPAddressParam],
|
async def root_post(ipaddresses: Annotated[
|
||||||
|
list[IPAddressParam],
|
||||||
Body(title="The IPAddresses to geolocate")],
|
Body(title="The IPAddresses to geolocate")],
|
||||||
response: Response
|
response: Response
|
||||||
) -> list[GeoLocation]:
|
) -> list[GeoLocation]:
|
||||||
@ -79,20 +84,22 @@ async def root_post(ipaddresses: Annotated[list[IPAddressParam],
|
|||||||
|
|
||||||
|
|
||||||
@app.get("/{ipaddress}")
|
@app.get("/{ipaddress}")
|
||||||
async def root_get(ipaddress: Annotated[Union[IPv4Address,IPv6Address],
|
async def root_get(ipaddress: Annotated[
|
||||||
|
Union[IPv4Address, IPv6Address],
|
||||||
Path(title="The IPAddress to geolocate")],
|
Path(title="The IPAddress to geolocate")],
|
||||||
response: Response
|
response: Response
|
||||||
) -> GeoLocation:
|
) -> GeoLocation:
|
||||||
'''
|
'''
|
||||||
Look up geolocation for ip in path parameter
|
Look up geolocation for ip in path parameter
|
||||||
'''
|
'''
|
||||||
locations = await root_post([IPAddressParam(ip=ipaddress)])
|
locations = await root_post([IPAddressParam(ip=ipaddress)], response)
|
||||||
if locations:
|
if locations:
|
||||||
response.headers['Cache-Control'] = 'private, max-age=604800'
|
response.headers['Cache-Control'] = 'private, max-age=604800'
|
||||||
return locations.pop()
|
return locations.pop()
|
||||||
response.status_code = status.HTTP_404_NOT_FOUND
|
response.status_code = status.HTTP_404_NOT_FOUND
|
||||||
return GeoLocation()
|
return GeoLocation()
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
def root_redirect(req: Request) -> RedirectResponse:
|
def root_redirect(req: Request) -> RedirectResponse:
|
||||||
'''
|
'''
|
||||||
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
geoip2==4.7.0
|
||||||
|
fastapi==0.115.6
|
Reference in New Issue
Block a user