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

如何让Uvicorn将非RFC合规URL传递给FastAPI处理?

解决Uvicorn拦截非RFC标准URL的问题

Uvicorn会在请求解析阶段拦截不符合RFC标准的URL(比如带空格、未编码Unicode的地址)并直接返回400错误,要让这类请求流转到FastAPI处理,可通过自定义ASGI中间件捕获Uvicorn的URL解析异常,重新构造请求后传递给FastAPI。

实现步骤

1. 编写异常捕获中间件

这个中间件会捕捉Uvicorn抛出的InvalidURL异常,从原始请求中提取未解析的路径并修改请求scope,让FastAPI能接收并处理该请求:

from uvicorn.errors import InvalidURL
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request

class InvalidURLMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        try:
            return await call_next(request)
        except InvalidURL:
            # 从scope中获取原始字节路径,用latin-1解码避免编码错误
            raw_path = request.scope.get("raw_path", b"")
            request.scope["path"] = raw_path.decode("latin-1")
            # 重新将请求传递给FastAPI
            return await call_next(request)

2. 配置FastAPI并添加兼容路由

将中间件挂载到FastAPI实例,同时添加一个通配路由处理所有非法URL,按需返回格式化响应或兼容旧API逻辑:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()
# 挂载自定义中间件
app.add_middleware(InvalidURLMiddleware)

# 通配路由,匹配所有路径(含非法URL)
@app.api_route("/{full_path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def handle_invalid_url(request: Request, full_path: str):
    # 这里可替换为旧API的兼容逻辑,或返回格式化错误
    return JSONResponse(
        status_code=400,
        content={
            "code": "INVALID_URL",
            "message": "请求URL格式不符合标准",
            "original_path": full_path
        }
    )

# 原有正常业务路由
@app.get("/api/v1/health")
async def health_check():
    return {"status": "ok"}

关键说明

  • 用latin-1解码原始路径是因为它能处理所有字节类型,不会因特殊字符抛出解码异常;
  • 通配路由/{full_path:path}会匹配所有层级的路径,确保所有非法URL都能被捕获;
  • 若需完全兼容旧API行为,可在handle_invalid_url中实现对应的请求处理逻辑,而非直接返回错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:35:11