mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 13:12:24 +00:00
Fix case where the user agent was empty (#976)
This commit is contained in:
@@ -21,7 +21,7 @@ class LoginLog(DataClassBase):
|
||||
country: Mapped[str | None] = mapped_column(sa.String(64), comment='国家')
|
||||
region: Mapped[str | None] = mapped_column(sa.String(64), comment='地区')
|
||||
city: Mapped[str | None] = mapped_column(sa.String(64), comment='城市')
|
||||
user_agent: Mapped[str] = mapped_column(sa.String(256), comment='请求头')
|
||||
user_agent: Mapped[str | None] = mapped_column(sa.String(256), comment='请求头')
|
||||
os: Mapped[str | None] = mapped_column(sa.String(64), comment='操作系统')
|
||||
browser: Mapped[str | None] = mapped_column(sa.String(64), comment='浏览器')
|
||||
device: Mapped[str | None] = mapped_column(sa.String(64), comment='设备')
|
||||
|
||||
@@ -23,7 +23,7 @@ class OperaLog(DataClassBase):
|
||||
country: Mapped[str | None] = mapped_column(sa.String(64), comment='国家')
|
||||
region: Mapped[str | None] = mapped_column(sa.String(64), comment='地区')
|
||||
city: Mapped[str | None] = mapped_column(sa.String(64), comment='城市')
|
||||
user_agent: Mapped[str] = mapped_column(sa.String(512), comment='请求头')
|
||||
user_agent: Mapped[str | None] = mapped_column(sa.String(512), comment='请求头')
|
||||
os: Mapped[str | None] = mapped_column(sa.String(64), comment='操作系统')
|
||||
browser: Mapped[str | None] = mapped_column(sa.String(64), comment='浏览器')
|
||||
device: Mapped[str | None] = mapped_column(sa.String(64), comment='设备')
|
||||
|
||||
@@ -15,7 +15,7 @@ class LoginLogSchemaBase(SchemaBase):
|
||||
country: str | None = Field(None, description='国家')
|
||||
region: str | None = Field(None, description='地区')
|
||||
city: str | None = Field(None, description='城市')
|
||||
user_agent: str = Field(description='用户代理')
|
||||
user_agent: str | None = Field(description='用户代理')
|
||||
browser: str | None = Field(None, description='浏览器')
|
||||
os: str | None = Field(None, description='操作系统')
|
||||
device: str | None = Field(None, description='设备')
|
||||
|
||||
@@ -19,7 +19,7 @@ class OperaLogSchemaBase(SchemaBase):
|
||||
country: str | None = Field(None, description='国家')
|
||||
region: str | None = Field(None, description='地区')
|
||||
city: str | None = Field(None, description='城市')
|
||||
user_agent: str = Field(description='用户代理')
|
||||
user_agent: str | None = Field(description='用户代理')
|
||||
os: str | None = Field(None, description='操作系统')
|
||||
browser: str | None = Field(None, description='浏览器')
|
||||
device: str | None = Field(None, description='设备')
|
||||
|
||||
@@ -13,7 +13,7 @@ class TypedContextProtocol(Protocol):
|
||||
region: str | None
|
||||
city: str | None
|
||||
|
||||
user_agent: str
|
||||
user_agent: str | None
|
||||
os: str | None
|
||||
browser: str | None
|
||||
device: str | None
|
||||
|
||||
@@ -17,7 +17,7 @@ class IpInfo:
|
||||
|
||||
@dataclasses.dataclass
|
||||
class UserAgentInfo:
|
||||
user_agent: str
|
||||
user_agent: str | None
|
||||
os: str | None
|
||||
browser: str | None
|
||||
device: str | None
|
||||
|
||||
@@ -32,19 +32,16 @@ def get_request_ip(request: Request) -> str:
|
||||
return request.client.host
|
||||
|
||||
|
||||
async def get_location_online(ip: str, user_agent: str) -> dict | None:
|
||||
async def get_location_online(ip: str) -> dict | None:
|
||||
"""
|
||||
在线获取 IP 地址属地,无法保证可用性,准确率较高
|
||||
|
||||
:param ip: IP 地址
|
||||
:param user_agent: 用户代理字符串
|
||||
:return:
|
||||
"""
|
||||
async with httpx.AsyncClient(timeout=3) as client:
|
||||
ip_api_url = f'http://ip-api.com/json/{ip}?lang=zh-CN'
|
||||
headers = {'User-Agent': user_agent}
|
||||
try:
|
||||
response = await client.get(ip_api_url, headers=headers)
|
||||
response = await client.get(f'http://ip-api.com/json/{ip}?lang=zh-CN')
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
@@ -92,7 +89,7 @@ async def parse_ip_info(request: Request) -> IpInfo:
|
||||
|
||||
location_info = None
|
||||
if settings.IP_LOCATION_PARSE == 'online':
|
||||
location_info = await get_location_online(ip, request.headers.get('User-Agent'))
|
||||
location_info = await get_location_online(ip)
|
||||
elif settings.IP_LOCATION_PARSE == 'offline':
|
||||
location_info = get_location_offline(ip)
|
||||
|
||||
@@ -115,9 +112,11 @@ def parse_user_agent_info(request: Request) -> UserAgentInfo:
|
||||
:param request: FastAPI 请求对象
|
||||
:return:
|
||||
"""
|
||||
os, browser, device = None, None, None
|
||||
user_agent = request.headers.get('User-Agent')
|
||||
user_agent_ = parse(user_agent)
|
||||
os = user_agent_.get_os()
|
||||
browser = user_agent_.get_browser()
|
||||
device = user_agent_.get_device()
|
||||
if user_agent:
|
||||
user_agent_ = parse(user_agent)
|
||||
os = user_agent_.get_os()
|
||||
browser = user_agent_.get_browser()
|
||||
device = user_agent_.get_device()
|
||||
return UserAgentInfo(user_agent=user_agent, device=device, os=os, browser=browser)
|
||||
|
||||
Reference in New Issue
Block a user