2025年12月9日小于 1 分钟
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/")
async def read_root(request: Request):
ip = request.client.host
print("访问者 IP:", ip)
return {"ip": ip}# save as app_fastapi.py
from fastapi import FastAPI, Request
from pydantic import BaseModel
import httpx # pip install fastapi uvicorn httpx
app = FastAPI()
class WhoamiResp(BaseModel):
client_ip: str
user_agent: str | None
accept_language: str | None
headers: dict
geo: dict | None = None
def get_client_ip_from_request(req: Request) -> str:
headers = req.headers
xff = headers.get("x-forwarded-for")
if xff:
return xff.split(",")[0].strip()
xr = headers.get("x-real-ip")
if xr:
return xr
# starlette Request.scope 中有 client tuple
client = req.client
return client.host if client else ""
async def ip_geolocate_async(ip: str):
if not ip:
return None
try:
async with httpx.AsyncClient(timeout=2.0) as client:
r = await client.get(f"http://ip-api.com/json/{ip}")
if r.status_code == 200:
data = r.json()
if data.get("status") == "success":
return {
"country": data.get("country"),
"region": data.get("regionName"),
"city": data.get("city"),
"lat": data.get("lat"),
"lon": data.get("lon"),
"isp": data.get("isp"),
}
except Exception:
pass
return None
@app.get("/whoami", response_model=WhoamiResp)
async def whoami(request: Request):
ip = get_client_ip_from_request(request)
ua = request.headers.get("user-agent")
accept_lang = request.headers.get("accept-language")
headers = dict(request.headers)
geo = await ip_geolocate_async(ip) # 可选
return WhoamiResp(client_ip=ip, user_agent=ua, accept_language=accept_lang, headers=headers, geo=geo)
# 启动: uvicorn app_fastapi:app --host 0.0.0.0 --port 8000 --reload