Files
wecom_it_smart_desk/deploy-server/fix_redis_v2.py
T

139 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""修复 Redis URL 解析问题"""
config_path = "/app/app/config.py"
with open(config_path, "r", encoding="utf-8") as f:
content = f.read()
# 找到并替换 create_redis_client 方法
old = ''' def create_redis_client(self) -> aioredis.Redis:
"""创建 Redis 异步客户端实例。
使用单独的 host/port/password 参数,避免 URL 解析问题
(特别是密码中包含特殊字符 ! @ # 时)。
自动附加 protocol=2 参数,强制使用 RESP2 协议。
原因:Windows 版 Redis 3.x 不支持 RESP3 协议(HELLO 命令),
而 redis-py 8.0+ 默认使用 RESP3,会导致连接失败。
全项目统一使用此方法创建 Redis 客户端,避免协议不匹配。
Returns:
aioredis.Redis: 配置好的 Redis 异步客户端
"""
# 如果 redis_url 为空,使用默认值
if not self.redis_url:
# 默认值:本地 Redis
return aioredis.Redis(
host="localhost",
port=6379,
protocol=2,
decode_responses=True
)
# 解析 REDIS_URL 提取连接参数
# 格式: redis://:password@host:port/db
from urllib.parse import urlparse
parsed = urlparse(self.redis_url)
# 提取密码(去掉用户名部分,如果存在的话)
password = parsed.password
if not password:
# 尝试从 netloc 中提取(格式 :password@host
netloc = parsed.netloc
if "@" in netloc:
password = netloc.split("@")[0].split(":")[-1]
return aioredis.Redis(
host=parsed.hostname or "localhost",
port=parsed.port or 6379,
password=password,
db=parsed.path and int(parsed.path.lstrip("/")) or 0,
protocol=2,
decode_responses=True
)'''
new = ''' def create_redis_client(self) -> aioredis.Redis:
"""创建 Redis 异步客户端实例。
使用单独的 host/port/password 参数,避免 URL 解析问题
(特别是密码中包含特殊字符 ! @ # 时)。
自动附加 protocol=2 参数,强制使用 RESP2 协议。
原因:Windows 版 Redis 3.x 不支持 RESP3 协议(HELLO 命令),
而 redis-py 8.0+ 默认使用 RESP3,会导致连接失败。
全项目统一使用此方法创建 Redis 客户端,避免协议不匹配。
Returns:
aioredis.Redis: 配置好的 Redis 异步客户端
"""
# 如果 redis_url 为空,使用默认值
if not self.redis_url:
# 默认值:本地 Redis
return aioredis.Redis(
host="localhost",
port=6379,
protocol=2,
decode_responses=True
)
# 解析 REDIS_URL 提取连接参数
# 格式: redis://:password@host:port/db
# 注意:密码中可能包含 @ 字符,需要特殊处理
# 例如:redis://:R3d!s@2026#Secure@redis:6379/0
# 其中 :R3d!s@2026#Secure 是密码,redis 是主机名
url = self.redis_url
# 找到最后一个 @ 之前的所有内容作为密码
# 格式: redis://:password@host:port/db
scheme_prefix = "redis://:"
if url.startswith(scheme_prefix):
# 提取 @ 之后的部分(主机和端口)
rest = url[len(scheme_prefix):]
at_pos = rest.rfind("@")
if at_pos > 0:
password = rest[:at_pos]
host_part = rest[at_pos+1:]
# 解析主机部分
if "/" in host_part:
host_port, db = host_part.split("/", 1)
db = int(db) if db.isdigit() else 0
else:
host_port = host_part
db = 0
if ":" in host_port:
host, port = host_port.split(":", 1)
port = int(port)
else:
host = host_port
port = 6379
return aioredis.Redis(
host=host,
port=port,
password=password,
db=db,
protocol=2,
decode_responses=True
)
# 回退:使用 from_url
return aioredis.from_url(url, protocol=2)'''
if old not in content:
print("ERROR: Could not find old method")
print("Looking for method...")
import re
match = re.search(r'def create_redis_client.*?(?=\n def |\nclass |\Z)', content, re.DOTALL)
if match:
print(f"Found: {match.group(0)[:200]}")
sys.exit(1)
new_content = content.replace(old, new)
with open(config_path, "w", encoding="utf-8") as f:
f.write(new_content)
print("Fixed!")