You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python FastAPI处理URL编码SHA1格式info_hash的异常问题排查

解决FastAPI解析BitTorrent info_hash字段的问题

问题原因

BitTorrent的info_hash是20字节的SHA1原始二进制值,URL编码后会包含大量非UTF-8兼容的字节。FastAPI默认会按照UTF-8编码自动解码URL查询参数,遇到无效UTF-8字节时,会用Unicode替换字符�(对应字节\xef\xbf\xbd)替代,导致原始的info_hash数据损坏:

  • 用str类型接收时,得到的是乱码字符串;
  • 用bytes类型接收时,FastAPI会先将损坏的字符串转回字节,最终得到的是包含大量\xef\xbf\xbd的错误数组。

修复方法

方法1:直接读取原始查询参数

绕过FastAPI的自动解码,直接获取URL的原始编码查询字符串,自行解析info_hash:

from fastapi import FastAPI, Request
from urllib.parse import parse_qs

app = FastAPI()

@app.get("/announce")
async def handle_announce(request: Request):
    # 获取原始URL编码的查询参数
    raw_query = request.query_params._urlencoded
    # 解析原始字节形式的查询参数
    parsed_params = parse_qs(raw_query)
    # 提取info_hash(确保取第一个值)
    info_hash = parsed_params.get(b"info_hash", [b""])[0]
    
    # 验证:转成十六进制字符串查看是否正确
    return {"info_hash_hex": info_hash.hex()}

方法2:使用自定义依赖项封装逻辑

如果多个路由需要处理info_hash,可以封装成依赖项复用:

from fastapi import FastAPI, Request, Depends
from urllib.parse import parse_qs

app = FastAPI()

def get_info_hash(request: Request) -> bytes:
    raw_query = request.query_params._urlencoded
    parsed_params = parse_qs(raw_query)
    return parsed_params.get(b"info_hash", [b""])[0]

@app.get("/announce")
async def handle_announce(info_hash: bytes = Depends(get_info_hash)):
    return {"info_hash_hex": info_hash.hex()}

注意事项

  • 如果同时支持POST请求(部分BT客户端会用POST提交宣告请求),需要额外处理请求体的原始数据,类似raw_query = await request.body();
  • 解析后得到的info_hash是20字节的原始二进制数据,如需对外展示或存储,建议转成十六进制字符串(如示例中的.hex()方法)。

内容的提问来源于stack exchange,提问作者Steven Venham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:42:45