使用Cloud Scheduler的HTTP触发云功能

时间:2018-11-08 21:10:02

标签: python google-cloud-functions google-cloud-scheduler

我在Cloud Scheduler中执行我的云功能时遇到问题。我使用下一个参数创建了作业:

目标:HTTP

URL :我针对云功能的触发URL

HTTP方法:POST

身体

{
 "expertsender": {
  "apiKey": "ExprtSender API key",
  "apiAddress": "ExpertSender APIv2 address",
  "date": "YYYY-MM-DD",
  "entities": [
     {
        "entity": "Messages"
     },
     {
        "entity": "Activities",
        "types":[
           "Subscriptions"
        ]
     }
  ]
 },
 "bq": {
         "project_id": "YOUR GCP PROJECT",
         "dataset_id": "YOUR DATASET NAME",
         "location": "US"
       } 
}

此主体的实际值已更改。

运行此作业时出现错误。原因是由于POST请求中的处理主体引起的。

但是,当我使用此主体并将其用作“测试”中的触发事件时,没有任何错误。因此,我认为这是我工作中身体表征的问题,但我不知道如何解决。任何想法我都会很高兴。

4 个答案:

答案 0 :(得分:8)

解决问题的另一种方法是:

request.get_json(force=True)

它强制解析器将有效负载视为json,从而使Mimetype陷入困境。 对烧瓶文档的引用为here

我认为这比提出的其他解决方案要简洁一些。

答案 1 :(得分:3)


免责声明: 我已经尝试使用NodeJS解决相同的问题,并且能够找到解决方案


我知道这是一个老问题。但是我觉得值得回答这个问题,因为我花了将近2个小时来弄清楚这个问题的答案。

场景-1:通过Cloud Scheduler触发Cloud功能

  • 函数无法读取请求正文中的消息。

方案-2:通过“云功能”界面中的“测试”选项卡触发云功能

  • 函数调用始终可以正常执行,没有错误。

我找到了什么?

  • 通过Cloud Scheduler执行GCF例程时,它将标头content-type作为application/octet-stream发送。这使得Express js无法在Cloud Scheduler POST数据时解析请求正文中的数据。
  • 但是,当使用完全相同的请求正文通过Cloud Function接口测试功能时,一切正常,因为接口上的 Testing 功能将标头content-type发送为{{ 1}}和express js能够读取请求正文并将数据解析为JSON对象。

解决方案

我必须手动将请求正文解析为JSON(明确使用基于内容类型标头的if条件)来获取请求正文中的数据。

application/json

这确实是一个功能问题,Google必须解决,并希望Google尽快解决。

Cloud Scheduler - Content Type header issue

答案 2 :(得分:1)

感谢@Dinesh指向请求标头作为解决方案!对于所有仍在徘徊而迷路的人,请使用python 3.7.4中的代码:

import json

raw_request_data = request.data

# Luckily it's at least UTF-8 encoded...
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)

完全同意,从可用性角度来看,这是低于标准的。让测试实用程序传递一个JSON,并让云调度程序发布一个“应用程序/八位字节流”,这是非常不负责任的设计。 但是,如果要以其他方式调用该函数,则应创建一个请求处理程序:

def request_handler(request):
    # This works if the request comes in from 
    # requests.post("cloud-function-etc", json={"key":"value"})
    # or if the Cloud Function test was used
    request_json = request.get_json()
    if request_json:
        return request_json

    # That's the hard way, i.e. Google Cloud Scheduler sending its JSON payload as octet-stream
    if not request_json and request.headers.get("Content-Type") == "application/octet-stream":
        raw_request_data = request.data
        string_request_data = raw_request_data.decode("utf-8")
        request_json: dict = json.loads(string_request_data)

    if request_json:
        return request_json

    # Error code is obviously up to you
    else:
        return "500"

答案 3 :(得分:0)

您可以使用的一种解决方法是提供一个设置为“application/json”的标头“Content-Type”。您可以看到设置 here