从requests HTTPAdapter迁移至httpx HTTPTransport遇授权错误如何解决?
背景
我们此前使用requests==2.32.3和google-cloud-storage==2.16.0,通过挂载HTTPAdapter配置连接池,代码如下:
from google.cloud import storage from requests.adapters import HTTPAdapter gcs_client = storage.Client() adapter = HTTPAdapter(pool_connections=30, pool_maxsize=30) gcs_client._http.mount("https://", adapter) gcs_client._http._auth_request.session.mount("https://", adapter)
迁移到httpx==0.27.0时,尝试自定义HTTPTransport配置连接池,但代码抛出401未授权错误:
import google.auth import httpx from google.cloud import storage transport = httpx.HTTPTransport( limits=httpx.Limits( max_connections=30, max_keepalive_connections=30 ) ) http = httpx.Client(transport=transport) http.is_mtls = False # 模拟requests适配器属性 gcs_client = storage.Client( _http=http, credentials=google.auth.default(scopes=storage.Client.SCOPE)[0], )
错误信息:
google.api_core.exceptions.Unauthorized: 401 GET https://storage.googleapis.com/storage/v1/b/foo?projection=noAcl&prettyPrint=false: Anonymous caller does not have storage.buckets.get access to the Google Cloud Storage bucket. Permission 'storage.buckets.get' denied on resource (or it may not exist).
问题原因
直接传入原生httpx.Client给GCS客户端无效,因为Google Auth库需要对请求进行令牌注入、签名等处理——原生httpx客户端没有集成这些逻辑。之前的requests方案是基于Google已适配好的requests会话,我们仅替换了连接池适配器;但httpx需要手动将Google Auth的认证逻辑与客户端结合。
正确实现方案
使用google-auth官方提供的httpx适配模块,将认证逻辑与自定义连接池的httpx客户端结合:
步骤1:确保依赖版本
需要安装以下依赖(版本不低于指定值):
pip install google-auth>=2.15.0 httpx>=0.27.0 google-cloud-storage>=2.16.0
步骤2:正确代码示例
import httpx import google.auth from google.cloud import storage from google.auth.transport.httpx import AuthorizedHttp # 1. 自定义httpx Transport,配置连接池参数 transport = httpx.HTTPTransport( limits=httpx.Limits( max_connections=30, # 对应原HTTPAdapter的pool_connections max_keepalive_connections=30 # 对应原HTTPAdapter的pool_maxsize ) ) # 2. 创建基础httpx客户端 base_http = httpx.Client(transport=transport) # 3. 获取GCS所需的认证凭证 credentials, _ = google.auth.default(scopes=storage.Client.SCOPE) # 4. 创建带Google Auth认证的httpx客户端 authorized_http = AuthorizedHttp(credentials, client=base_http) # 5. 初始化GCS客户端,传入带认证的httpx实例 gcs_client = storage.Client(_http=authorized_http)
说明
AuthorizedHttp会自动处理OAuth2令牌的获取、注入和刷新,彻底解决401未授权问题- 连接池配置通过
HTTPTransport的limits参数实现,与原HTTPAdapter的参数一一对应 - 该方案完全兼容GCS客户端的所有原有功能,仅替换了底层HTTP客户端实现
内容的提问来源于stack exchange,提问作者Intrastellar Explorer

