This repository has been archived on 2024-06-12. You can view files and clone it, but cannot push or open issues or pull requests.
ipserv/ipserv.py

69 lines
2 KiB
Python
Raw Normal View History

2024-04-17 16:27:58 +01:00
import requests
2024-04-18 10:18:38 +01:00
import json
2024-04-18 11:26:09 +01:00
import logging
2024-04-19 10:38:32 +01:00
import time
2024-04-19 10:59:19 +01:00
import aiohttp
2024-04-19 10:53:06 +01:00
from fastapi import FastAPI, Header, Request, Query, HTTPException
from fastapi.responses import JSONResponse
2024-04-19 10:59:19 +01:00
from contextlib import asynccontextmanager
2024-04-17 16:27:58 +01:00
2024-04-18 11:26:09 +01:00
logging.basicConfig(level=logging.INFO)
2024-04-19 10:59:19 +01:00
@asynccontextmanager()
async def lifespan(_app: FastAPI):
async with aiohttp.ClientSession(
"https://ip.shronk.tech",
connector=aiohttp.TCPConnector(limit=2048)
) as client:
_app.state.session = client
yield
app = FastAPI()
app.state.cache = {}
2024-04-17 16:27:58 +01:00
@app.get("/")
2024-04-19 10:59:19 +01:00
async def ip(
2024-04-19 10:53:06 +01:00
request: Request,
X_Forwarded_For: str = Header(None),
User_Agent: str = Header("Mozilla/5.0"),
Accept: str = Header("text/plain"),
Accept_Language: str = Header("en-us"),
lookup: str = Query(None),
):
if lookup:
ip = lookup
elif X_Forwarded_For:
ip = X_Forwarded_For
2024-04-17 16:27:58 +01:00
else:
2024-04-19 10:53:06 +01:00
ip = request.client.host
2024-04-19 10:38:32 +01:00
2024-04-19 10:59:19 +01:00
if ip in app.state.cache:
data, timestamp = app.state.cache[ip]
2024-04-19 10:38:32 +01:00
if time.time() - timestamp < 3600:
logging.info("cache hit for %s", ip)
2024-04-19 10:53:06 +01:00
return JSONResponse(data)
2024-04-19 10:38:32 +01:00
logging.info("cache expired for %s", ip)
2024-04-18 11:26:09 +01:00
logging.info("looking up IP info for %s", ip)
2024-04-18 10:18:38 +01:00
try:
2024-04-19 10:59:19 +01:00
async with app.state.session.get(f"/lookup?ip={ip}") as response:
response.raise_for_status()
data = await response.json()
2024-04-18 10:18:38 +01:00
except Exception as e:
2024-04-18 11:26:09 +01:00
logging.error("Failed to get data for %s: %s", ip, e, exc_info=True)
2024-04-19 10:53:06 +01:00
raise HTTPException(500, "Failed to get upstream data.")
2024-04-18 10:18:38 +01:00
except json.JSONDecodeError as e:
2024-04-18 11:26:09 +01:00
logging.error("Failed to parse data for %s: %s", ip, e, exc_info=True)
2024-04-19 10:53:06 +01:00
raise HTTPException(500, "Failed to parse upstream response.")
2024-04-18 11:26:09 +01:00
logging.info("%s -> %r", ip, data)
data["ip"] = ip
2024-04-18 10:18:38 +01:00
data.pop("legalese", None)
data.pop("source", None)
data.pop("brexitRequired", None)
2024-04-19 10:53:06 +01:00
if response.status_code == 200:
2024-04-19 10:59:19 +01:00
app.state.cache[ip] = [data, time.time()]
2024-04-19 10:53:06 +01:00
return JSONResponse(data, response.status_code)