Cloud Run中requests.post请求被Django识别为GET的问题排查
Google Cloud无服务器流水线POST请求被转为GET的问题
问题概述
我在Google Cloud上搭建了一套无服务器流水线,包含三个步骤:
- 视频上传器将视频发送至Google Cloud Storage,运行正常;
- 当视频上传至GCS时,Eventarc + Pub/Sub触发器会触发名为“post processor”的Cloud Run应用;
- post processor提取文件相关信息后,向我的Django API发送请求,在数据库中创建该录制的历史记录。
post processor基于functions_framework.cloud_event实现,Google Cloud Logging中的日志显示它能正确接收所有信息:
2025-09-24 14:53:05,135 INFO main: RECEIVED DATA FROM EVENTARC (POST-PROCESSING): Original Filename=7614_2025_09_23_16_46_17.mp4, Serial=7614, UTC=2025-09-23T16:46:17+00:00, Duration=0s, Frames=0
并生成如下Payload发送至Django API:
{ "raw_file": null, "raw_file_gcp": "https://storage.cloud.google.com/homolog-videos/7614_2025_09_23_16_46_17.mp4", "motion_file": null, "event_at": "2025-09-23T16:46:17+00:00", "camera": 7614, "frames_count": 0, "duration_seconds": 0, "event_end_at": "2025-09-23T16:46:17+00:00", "size_mb": 0 }
但Django API端收到的请求没有任何Payload,且请求方法变为GET而非POST,示例日志:
[GET] /api/recordings/ | From: 34.34.234.34 | Payload: {}
这意外触发了列表接口而非创建记录的接口。
本地复现生产环境设置(DEBUG=False、ENVIRONMENT="production"等),使用相同的post processor代码和依赖版本,通过NGrok处理GCS上传的视频时,Django API能正确接收带有JSON的POST请求,与Cloud Run中的表现完全不同。
使用的依赖库如下:
functions-framework==3.5.0 cloudevents==1.11.0 cachetools==6.1.0 pytz==2025.1 requests==2.32.5
我无法理解为何Cloud Run中执行的requests.post会被Django REST Framework转换为无请求体的GET请求?是否需要在ingress.yaml中配置某些规则或主机定义?
Edit 1:相关代码示例
触发器函数代码
import functions_framework from cloudevents.http import CloudEvent # Triggered by a Cloud Storage "object finalized" event @functions_framework.cloud_event def hello_gcs(cloud_event: CloudEvent): data = cloud_event.data name = data["name"] # e.g. "7614_2025_09_23_16_46_17.mp4" # ...parse metadata and compute (serial, date, duration, frames, filename)... serial, date, duration, frames, filename = process_video(name) create_recording(serial, date, duration, frames, filename) return "OK"
构建Payload并发送请求的代码
def create_recording(serial_cam, date, duration, frames, filename): API_URL = os.environ.get("API_URL") API_TOKEN = os.environ.get("API_TOKEN") api = WrapperAPI(API_URL, API_TOKEN) # Build payload payload = { "raw_file": None, "raw_file_gcp": f"https://storage.cloud.google.com/{BUCKET}/{filename}", # ... etc ... A normal payload, nothing fancy. } # Perform the POST recording = api.create(resource="recordings", json=payload, hide_error_msg=False)
API封装类代码
import requests class WrapperAPI: def __init__(self, base_url, token): self.url = base_url.rstrip("/") self.headers = {"Authorization": token, "Content-Type": "application/json"} def create(self, resource, json, hide_error_msg=False): try: url = f"{self.url}/{resource}/" resp = requests.post(url, json=json, headers=self.headers) # <-- POST resp.raise_for_status() return resp.json() # ... etc ... Exception treatment... No magic here. Just the normal exception treatment you would expect.
Edit 2:调研结论
调研发现,当Python的requests客户端跟随重定向时,会将请求方法转换为GET并丢弃请求体,这正好解释了后端为何收到无Payload的GET请求,我们遇到的问题与同类场景下的问题完全一致。
内容的提问来源于stack exchange,提问作者Raul Chiarella
相关产品推荐
相关产品推荐

