Google Cloud Tasks调用Django接口返回301失败求助
根据你描述的情况——手动访问API正常但Cloud Tasks调用返回301失败,我推测核心原因是请求协议不匹配导致的重定向,结合你的代码细节,给你几个针对性的解决方向:
1. 给Cloud Tasks任务添加HTTPS协议指定
你的TasksCreate类中定义app_engine_http_request时没有指定scheme,默认情况下Cloud Tasks会用HTTP请求你的App Engine服务。如果你的tasks服务开启了强制HTTPS(比如tasks.yaml里有secure: always配置),就会触发301重定向到HTTPS地址,但Cloud Tasks默认不会自动跟随重定向,直接导致任务失败。
修改tasks.py中的任务定义,添加scheme: HTTPS:
task = { 'app_engine_http_request': { 'http_method': 'POST', 'relative_uri': url, 'app_engine_routing': {'service': 'tasks'}, 'scheme': 'HTTPS' # 新增这一行,强制使用HTTPS请求 } }
2. 修复Django视图的导入错误(非301直接原因,但必须修正)
你的api.py中使用了HttpResponse但没有导入,这会触发500错误,你说手动访问正常应该是粘贴代码时遗漏了导入,补上:
from django.http import HttpResponse # 新增导入 from django.views.decorators.csrf import csrf_exempt @csrf_exempt def tasks(request): print('Start api') payload = request.body.decode("utf-8") print(payload) print('End api') return HttpResponse('OK')
3. 验证URL路由的斜杠一致性
Django默认开启APPEND_SLASH=True,如果请求URL和路由定义的斜杠不一致,会触发重定向。虽然你手动访问正常,但可以确保路由同时匹配带/不带斜杠的情况:
# urls.py path('api/v1/tasks', tasks, name='tasks'), path('api/v1/tasks/', tasks, name='tasks-with-slash'),
或者用正则路由简化:
from django.urls import re_path re_path(r'^api/v1/tasks/?$', tasks, name='tasks'),
4. 确认dispatch.yaml的规则优先级
你的dispatch.yaml中先匹配了*/api/v1/tasks和*/api/v1/tasks/,再匹配*appspot.com/*,这个优先级是对的,但可以把规则写得更精确,避免歧义:
dispatch: - url: "*/api/v1/tasks" service: tasks - url: "*/api/v1/tasks/" service: tasks - url: "[proj].appspot.com/*" # 替换成你的项目ID,更精确 service: default
5. 检查tasks服务的app.yaml配置
确保tasks.yaml中没有冲突的HTTPS强制配置(如果已经在Cloud Tasks中指定了HTTPS,这个配置可以保留):
# tasks.yaml示例配置 runtime: python37 instance_class: F1 automatic_scaling: max_instances: 2 service: tasks handlers: - url: .* secure: always redirect_http_response_code: 301 script: auto entrypoint: gunicorn -b :$PORT --chdir src server.wsgi
按照上面的步骤修改后,重新部署服务和Cloud Tasks任务,应该就能解决301重定向导致的任务失败问题了。
内容的提问来源于stack exchange,提问作者JCampos

