Fix IPServer
This commit is contained in:
parent
6b29f7d868
commit
3ba2c19aa9
2 changed files with 46 additions and 35 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,3 +2,5 @@
|
||||||
.vscode/
|
.vscode/
|
||||||
.venv/
|
.venv/
|
||||||
venv/
|
venv/
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
73
ipserv.py
73
ipserv.py
|
@ -6,7 +6,7 @@ import aiohttp
|
||||||
import random
|
import random
|
||||||
import ipaddress
|
import ipaddress
|
||||||
from fastapi import FastAPI, Header, Request, Query, HTTPException
|
from fastapi import FastAPI, Header, Request, Query, HTTPException
|
||||||
from fastapi.responses import JSONResponse, PlainTextResponse
|
from fastapi.responses import JSONResponse, PlainTextResponse, RedirectResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
@ -57,12 +57,26 @@ app.add_middleware(
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def http_middleware(request: Request, call_next):
|
async def http_middleware(request: Request, call_next):
|
||||||
if app.state.meta.waiting >= 2512:
|
if app.state.meta.waiting >= 2512:
|
||||||
return JSONResponse({"error": os.urandom(512).decode("latin-1", "replace")}, status_code=503)
|
return JSONResponse({"detail": os.urandom(512).decode("latin-1", "replace")}, status_code=503)
|
||||||
|
|
||||||
|
try:
|
||||||
|
_ip = ipaddress.ip_address(request.client.host)
|
||||||
|
if isinstance(_ip, ipaddress.IPv6Address):
|
||||||
|
return JSONResponse(
|
||||||
|
{"detail": "IPv6 is not supported at this time."},
|
||||||
|
status_code=400
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
return JSONResponse(
|
||||||
|
{"detail": "Invalid IP address."},
|
||||||
|
status_code=400
|
||||||
|
)
|
||||||
|
|
||||||
with app.state.meta:
|
with app.state.meta:
|
||||||
return await call_next(request)
|
return await call_next(request)
|
||||||
|
|
||||||
|
|
||||||
async def make_request(ip: str, headers: dict[str, str]) -> dict | HTTPException:
|
async def make_request(ip: str, headers: dict[str, str] = None) -> dict | HTTPException:
|
||||||
if ip in app.state.cache:
|
if ip in app.state.cache:
|
||||||
data, timestamp = app.state.cache[ip]
|
data, timestamp = app.state.cache[ip]
|
||||||
if time.time() - timestamp < 3600:
|
if time.time() - timestamp < 3600:
|
||||||
|
@ -71,7 +85,7 @@ async def make_request(ip: str, headers: dict[str, str]) -> dict | HTTPException
|
||||||
logging.info("cache expired for %s", ip)
|
logging.info("cache expired for %s", ip)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with app.state.session.get(f"/lookup?ip={ip}") as response:
|
async with app.state.session.get(f"/lookup?ip={ip}", headers=headers) as response:
|
||||||
data = await response.json()
|
data = await response.json()
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
logging.error("Failed to parse data for %s: %s", ip, e, exc_info=True)
|
logging.error("Failed to parse data for %s: %s", ip, e, exc_info=True)
|
||||||
|
@ -86,7 +100,6 @@ async def make_request(ip: str, headers: dict[str, str]) -> dict | HTTPException
|
||||||
async def ip(
|
async def ip(
|
||||||
request: Request,
|
request: Request,
|
||||||
X_Forwarded_For: str = Header(None),
|
X_Forwarded_For: str = Header(None),
|
||||||
User_Agent: str = Header("Mozilla/5.0"),
|
|
||||||
lookup: str = Query(None),
|
lookup: str = Query(None),
|
||||||
):
|
):
|
||||||
if lookup:
|
if lookup:
|
||||||
|
@ -96,18 +109,11 @@ async def ip(
|
||||||
else:
|
else:
|
||||||
ip = request.client.host
|
ip = request.client.host
|
||||||
|
|
||||||
try:
|
if ip == "127.0.0.1":
|
||||||
_ip = ip_address.ip_address(ip)
|
ip = ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
|
||||||
if isinstance(_ip, ipaddress.IPv6Address):
|
|
||||||
raise HTTPException(400, detail="IPv6 is not supported at this time.")
|
|
||||||
except ValueError:
|
|
||||||
raise HTTPException(400, detail="%r does not appear to be a valid IP address" % ip)
|
|
||||||
|
|
||||||
logging.info("looking up IP info for %s", ip)
|
logging.info("looking up IP info for %s", ip)
|
||||||
data = await make_request(
|
data = await make_request(ip)
|
||||||
ip,
|
|
||||||
{"User-Agent": User_Agent}
|
|
||||||
)
|
|
||||||
if isinstance(data, HTTPException):
|
if isinstance(data, HTTPException):
|
||||||
raise data
|
raise data
|
||||||
data["ip"] = ip
|
data["ip"] = ip
|
||||||
|
@ -128,12 +134,8 @@ async def lookup(ip: str = Query(...), User_Agent: str = Header("Mozilla/5.0")):
|
||||||
return JSONResponse(data)
|
return JSONResponse(data)
|
||||||
logging.info("cache expired for %s", ip)
|
logging.info("cache expired for %s", ip)
|
||||||
|
|
||||||
try:
|
if ip == "127.0.0.1":
|
||||||
_ip = ip_address.ip_address(ip)
|
ip = ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
|
||||||
if isinstance(_ip, ipaddress.IPv6Address):
|
|
||||||
raise HTTPException(400, detail="IPv6 is not supported at this time.")
|
|
||||||
except ValueError:
|
|
||||||
raise HTTPException(400, detail="%r does not appear to be a valid IP address" % ip)
|
|
||||||
|
|
||||||
logging.info("looking up IP info for %s", ip)
|
logging.info("looking up IP info for %s", ip)
|
||||||
data = await make_request(
|
data = await make_request(
|
||||||
|
@ -153,21 +155,15 @@ async def lookup(ip: str = Query(...), User_Agent: str = Header("Mozilla/5.0")):
|
||||||
|
|
||||||
@app.get("/imfeelinglucky")
|
@app.get("/imfeelinglucky")
|
||||||
async def im_feeling_lucky(req: Request):
|
async def im_feeling_lucky(req: Request):
|
||||||
host = req.client.host
|
ip = req.client.host
|
||||||
|
if ip == "127.0.0.1":
|
||||||
try:
|
ip = ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
|
||||||
_ip = ip_address.ip_address(host)
|
data = await make_request(ip)
|
||||||
if isinstance(_ip, ipaddress.IPv6Address):
|
|
||||||
raise HTTPException(400, detail="IPv6 is not supported at this time.")
|
|
||||||
except ValueError:
|
|
||||||
raise HTTPException(400, detail="%r does not appear to be a valid IP address" % host)
|
|
||||||
|
|
||||||
data = await make_request(host, {"User-Agent": "Mozilla/5.0 Nex/19.04.2024"})
|
|
||||||
if not isinstance(data, dict):
|
if not isinstance(data, dict):
|
||||||
raise data
|
raise data
|
||||||
data = data.copy()
|
data = data.copy()
|
||||||
|
|
||||||
parts = list(map(int, host.split(".")))
|
parts = list(map(int, ip.split(".")))
|
||||||
n = random.randint(1, 1000)
|
n = random.randint(1, 1000)
|
||||||
if n in range(50, 54):
|
if n in range(50, 54):
|
||||||
if n > 400:
|
if n > 400:
|
||||||
|
@ -183,6 +179,12 @@ def get_raw(req: Request):
|
||||||
return PlainTextResponse(req.client.host)
|
return PlainTextResponse(req.client.host)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/random")
|
||||||
|
def get_random():
|
||||||
|
ip = ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
|
||||||
|
return RedirectResponse(f"/lookup?ip={ip}")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def get_health():
|
async def get_health():
|
||||||
detail = {"issues": []}
|
detail = {"issues": []}
|
||||||
|
@ -208,3 +210,10 @@ async def get_health():
|
||||||
|
|
||||||
|
|
||||||
app.mount("/check", StaticFiles(directory="./cert", html=True), name="shronk-cert")
|
app.mount("/check", StaticFiles(directory="./cert", html=True), name="shronk-cert")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import uvicorn
|
||||||
|
logging.critical("Running in development mode! Even then, you should use the docker container!")
|
||||||
|
app.debug = True
|
||||||
|
uvicorn.run("ipserv:app", port=0, reload=True, log_level="info")
|
||||||
|
|
Reference in a new issue