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

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,步骤如下:

  1. 在终端执行以下命令获取默认User-Agent:
python -c "import requests; print(requests.utils.default_user_agent())"
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:20:55