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

Google Drive Python SDK遇SSL错误:React请求异常Postman正常

排查Flask + Google Drive API在React请求时的SSL记录层错误

问题背景

我在Flask应用中实现了一个方法,用于在Google Drive中查找指定文件夹,不存在则创建并返回folder_id:

def find_or_create_folder_in_google_drive(name, parent_id=None):
    query = f"name='{name}'"

    if parent_id:
        query += f" and '{parent_id}' in parents"
    query += " and mimeType='application/vnd.google-apps.folder'"
    query += " and trashed=false"

    response = (
        GOOGLE_DRIVE_SERVICE.files()
        .list(q=query, spaces="drive", fields="files(id, name)")
        .execute()
    )
    files = response.get("files", [])

    if not files:
        file_metadata = {"name": name, "mimeType": "application/vnd.google-apps.folder"}

        if parent_id:
            file_metadata["parents"] = [parent_id]

        folder = (
            GOOGLE_DRIVE_SERVICE.files()
            .create(body=file_metadata, fields="id")
            .execute()
        )
        return folder.get("id")

    return files[0].get("id")

该代码在Postman、Thunder Client等API测试工具中运行正常,但通过React前端发送相同请求时,抛出如下SSL异常:

File "path/backend/storage_manager/google/prompts.py", line 19, in create_or_get_prompts_path_google_sheets
    root_folder_id = find_or_create_folder_in_google_drive(ROOT_FOLDER)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "path/backend/storage_manager/google_services/get_drive_paths.py", line 15, in find_or_create_folder_in_google_drive
    .execute()
     ^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/googleapiclient/http.py", line 923, in execute
    resp, content = _retry_request(
                    ^^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/googleapiclient/http.py", line 222, in _retry_request
    raise exception
  File "path/backend/.venv/lib/python3.11/site-packages/googleapiclient/http.py", line 191, in _retry_request
    resp, content = http.request(uri, method, *args, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/google_auth_httplib2.py", line 218, in request
    response, content = self.http.request(
                        ^^^^^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/httplib2/__init__.py", line 1724, in request
    (response, content) = self._request(
                          ^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/httplib2/__init__.py", line 1444, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "path/backend/.venv/lib/python3.11/site-packages/httplib2/__init__.py", line 1396, in _conn_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1378, in getresponse
    response.begin()
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 318, in begin
    version, status, reason = self._read_status()
                              ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 279, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py", line 706, in readinto
    return self._sock.recv_into(b)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ssl.py", line 1278, in recv_into
    return self.read(nbytes, buffer)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ssl.py", line 1134, in read
    return self._sslobj.read(len, buffer)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL] record layer failure (_ssl.c:2576)

错误触发点为GOOGLE_DRIVE_SERVICE.files().list(...).execute()这一行。当前使用的Google依赖版本:

google-api-core==2.16.1
google-api-python-client==2.116.0
google-auth==2.27.0
google-auth-httplib2==0.2.0
google-auth-oauthlib==1.2.0
googleapis-common-protos==1.62.0

排查思路

  • 排除CORS直接关联:CORS错误会在浏览器控制台显示,后端SSL异常是与Google Drive API通信时的问题,和前端跨域本身无关,但前端请求的特性可能间接触发。
  • 对比请求差异:检查Postman与React请求的请求头、参数编码、请求方式是否存在差异,比如React是否携带了特殊头导致后端处理逻辑变化。
  • 网络环境排查:Postman可能使用系统代理,而React前端所在环境(浏览器/开发服务器)使用不同代理,导致后端访问Google API的网络路径变化,触发SSL握手问题。
  • 依赖兼容性检查:验证httplib2与Python 3.11的兼容性,或Google客户端库之间的版本冲突。
  • 连接稳定性排查:React请求可能触发后端并发处理,导致Google API请求的连接被中断,引发SSL记录层错误。

解决方案

1. 替换httplib2为requests适配器

httplib2在部分环境下易出现SSL问题,改用基于requests的适配器提升稳定性:

from googleapiclient.discovery import build
from google_auth_httplib2 import AuthorizedHttp
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 创建带重试机制的requests会话
session = requests.Session()
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)

# 替换Google服务的HTTP客户端
authorized_http = AuthorizedHttp(credentials, http=session)
GOOGLE_DRIVE_SERVICE = build('drive', 'v3', http=authorized_http)

2. 临时调整SSL配置(仅测试用)

临时禁用证书验证排查是否为证书问题(生产环境禁止使用):

import httplib2
httplib2.disable_ssl_certificate_validation = True

或指定SSL版本:

import ssl
from httplib2 import Http

http = Http()
http.ca_certs = "/path/to/ca-certificates.crt"
http.ssl_version = ssl.PROTOCOL_TLSv1_2

3. 修复Flask CORS配置

虽然不是直接原因,但确保CORS配置正确,避免前端请求被拦截后引发后端异常:

from flask_cors import CORS

app = Flask(__name__)
# 生产环境请指定具体域名,而非允许所有
CORS(app)

4. 更新依赖库

尝试更新Google客户端库和httplib2到最新版本,修复兼容性问题:

pip install --upgrade google-api-python-client google-auth httplib2

5. 添加请求重试机制

在Google API请求中增加重试逻辑,处理临时网络中断:

import ssl
import time
from googleapiclient.errors import HttpError

def find_or_create_folder_in_google_drive(name, parent_id=None):
    query = f"name='{name}'"
    if parent_id:
        query += f" and '{parent_id}' in parents"
    query += " and mimeType='application/vnd.google-apps.folder' and trashed=false"

    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = (
                GOOGLE_DRIVE_SERVICE.files()
                .list(q=query, spaces="drive", fields="files(id, name)")
                .execute()
            )
            break
        except ssl.SSLError as e:
            if attempt == max_retries - 1:
                raise e
            time.sleep(2 ** attempt)  # 指数退避等待

    files = response.get("files", [])
    # 后续创建逻辑保持不变...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:55:53