FastAPI请求GitHub公开仓库API返回无效凭证,终端请求正常问题排查
问题:FastAPI调用GitHub API返回"Bad credentials",终端Python请求却正常
问题背景
我开发了一个FastAPI镜像服务,用于为无法访问公网的本地机器返回GitHub公开仓库资源。但调用该接口时,收到GitHub返回的"Bad credentials"(无效凭证)响应。
诡异的是,在运行FastAPI服务的同一台设备上,通过终端直接用Python发起完全相同的请求,却能正常通过验证,获取到包含包资产和下载链接的响应。两种场景下我都没有提供任何凭证,因为GitHub公开版本的API端点理应无需认证。
代码对比
FastAPI接口代码
""" 出现问题的API端点 """ import requests from fastapi import APIRouter, Response windows_terminal = APIRouter(prefix="/microsoft/terminal") @windows_terminal.get("/releases/latest", response_class=Response) def get_latest_windows_terminal_release(): url = "https://api.github.com/repos/microsoft/terminal/releases/latest" response = requests.get(url) return Response( content=response.content, status_code=response.status_code, headers=response.headers, )
注:此代码运行时返回"Bad credentials",但添加GitHub个人访问令牌后可正常返回数据。
终端Python请求代码
# 同一设备终端中的操作 $ python >>> import requests >>> url = "https://api.github.com/repos/microsoft/terminal/releases/latest" >>> response = requests.get(url) >>> print(response.text)
注:无需令牌即可成功返回最新版本的JSON数据。
错误响应时的请求/响应头
响应头
access-control-allow-origin * access-control-expose-headers ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset content-length 95 content-security-policy default-src 'none' content-type application/json; charset=utf-8 date Wed, 16 Oct 2024 09:26:30 GMT, Wed, 16 Oct 2024 09:26:30 GMT referrer-policy origin-when-cross-origin, strict-origin-when-cross-origin server uvicorn, github.com strict-transport-security max-age=31536000; includeSubdomains; preload vary Accept-Encoding, Accept, X-Requested-With x-content-type-options nosniff x-frame-options deny x-github-media-type github.v3; format=json x-github-request-id C62C:3C7F8A:20BE68E:230F16B:670F86C6 x-ratelimit-limit 60 x-ratelimit-remaining 59 x-ratelimit-reset 1729074390 x-ratelimit-resource core x-ratelimit-used 1 x-xss-protection 0
请求头
Accept text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Encoding gzip, deflate Accept-Language en-GB,en;q=0.5 Connection keep-alive DNT 1 Host ######## (已省略) Upgrade-Insecure-Requests 1 User-Agent Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
原因分析
核心差异在于请求的User-Agent头:
- 终端中
requests库默认发送的User-Agent是python-requests/[版本号],属于GitHub认可的规范请求标识; - FastAPI接口转发的请求中,User-Agent来自客户端(这里是Firefox浏览器的标识),GitHub的API对这类非标准的、可能来自爬虫的User-Agent会触发验证逻辑,即使没有传递凭证,也会返回"Bad credentials"错误。
解决方法
在FastAPI的requests.get请求中显式设置符合规范的User-Agent即可解决问题。可以直接使用终端中requests的默认User-Agent,步骤如下:
- 在终端执行以下命令获取默认User-Agent:
python -c "import requests; print(requests.utils.default_user_agent())"
- 修改FastAPI代码,添加自定义User-Agent头:
""" 修复后的API端点 """ import requests from fastapi import APIRouter, Response windows_terminal = APIRouter(prefix="/microsoft/terminal") @windows_terminal.get("/releases/latest", response_class=Response) def get_latest_windows_terminal_release(): url = "https://api.github.com/repos/microsoft/terminal/releases/latest" # 替换成你终端获取到的默认User-Agent headers = { "User-Agent": "python-requests/2.31.0" } response = requests.get(url, headers=headers) return Response( content=response.content, status_code=response.status_code, headers=response.headers, )
内容的提问来源于stack exchange,提问作者TheEponymousProgrammer
相关产品推荐
相关产品推荐

