发出 HTTP 请求

您可以定义执行 HTTP 调用的工作流步骤,并将调用的响应分配给变量。例如,您可以通过 HTTP 请求调用 Google Cloud服务(例如 Cloud Run 函数或 Cloud Run)

通过 HTTP 请求调用 Google Cloud 服务不应与使用 Workflows 连接器执行 API 操作相混淆。连接器会为您处理请求的格式,从而为您处理请求的格式设置并提供方法和参数,这样您就无需了解 Google Cloud API 的详细信息。

调用 HTTP 端点

这种类型的步骤允许您发出 HTTP 请求。支持 HTTP 和 HTTPS 请求。最常见的 HTTP 请求方法具有调用快捷方式(例如 http.gethttp.post),但您可以发出任何类型的 HTTP 请求,方法是将 call 字段设置为 http.request 并使用 method 字段指定请求类型。

YAML

  - STEP_NAME:
      call: HTTP_REQUEST
      args:
          url: URL_VALUE
          method: REQUEST_METHOD
          private_service_name: "REGISTERED_SERVICE"
          headers:
              HEADER_KEY:HEADER_VALUE
              ...
          body:
              BODY_KEY:BODY_VALUE
              ...
          query:
              QUERY_KEY:QUERY_VALUE
              ...
          auth:
              type: AUTH_TYPE
              scope: AUTH_SCOPE
              scopes: AUTH_SCOPE
              audience: AUDIENCE
          timeout: TIMEOUT_IN_SECONDS
      result: RESULT_VALUE
    

JSON

  [
    {
      "STEP_NAME": {
        "call": "HTTP_REQUEST",
        "args": {
          "url": "URL_VALUE",
          "method": "REQUEST_METHOD",
          "private_service_name": "REGISTERED_SERVICE",
          "headers": {"HEADER_KEY":"HEADER_VALUE",
          ...
          },
          "body": {"BODY_KEY":"BODY_VALUE",
          ...
          },
          "query": {"QUERY_KEY":"QUERY_VALUE",
          ...
          },
          "auth": {
            "type":"AUTH_TYPE",
            "scope":"AUTH_SCOPE",
            "scopes":"AUTH_SCOPE",
            "audience":"AUDIENCE"
          },
          "timeout": "TIMEOUT_IN_SECONDS"
        },
        "result": "RESULT_VALUE"
      }
    }
  ]
    

请替换以下内容:

  • HTTP_REQUEST:必填。对 HTTP 请求使用下列其中一项:
    • http.delete
    • http.get
    • http.patch
    • http.post
    • http.put
    • http.request
  • URL_VALUE:必填。发送请求的网址。
  • REQUEST_METHOD:如果使用调用类型 http.request,则需要此参数。要使用的 HTTP 请求方法的类型。例如:
    • GET
    • POST
    • PATCH
    • DELETE
  • REGISTERED_SERVICE:可选。已注册的 Service Directory 服务名称,格式为 projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME。 如需了解详情,请参阅调用符合 VPC Service Controls 要求的专用端点
  • HEADER_KEY:HEADER_VALUE:可选。用于向 API 提供输入的标头字段。

    如果使用 Content-Type 标头指定请求正文的媒体类型,则仅支持以下类型:

    • application/jsonapplication/type+json - 必须是映射
    • application/x-www-form-urlencoded - 必须是未编码的字符串
    • text/type - 必须是字符串

    如果指定了 Content-Type 标头,则正文会按规定编码。例如,它可以是 JSON 或网址编码。

    如果使用 User-Agent 标头来识别发出请求的用户代理,则以下规则适用:

    • 默认值为 GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
    • 如果指定了值,则会将 GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs) 附加到该值

      例如,如果指定了 User-Agent: "MY_USER_AGENT_VALUE",则 HTTP 请求标头如下所示(指定值与附加的默认值之间有一个空格):

      MY_USER_AGENT_VALUE GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
  • BODY_KEY:BODY_VALUE:可选。用于向 API 提供输入的正文字段。

    如果未指定 Content-Type 标头,并且存在请求正文,则适用以下规则:

    • 如果正文值为字节,则标头设置为 Content-Type: application/octet-stream
    • 否则,正文将采用 JSON 编码,标头将设置为 Content-Type: application/json; charset=utf-8
    以下示例中的正文结构等效于 JSON 载荷:

    YAML

    body:
      requests:
      - image:
          source:
            gcsImageUri: ${gsUri}
        features:
        - type: LABEL_DETECTION
        - type: SAFE_SEARCH_DETECTION
        - type: IMAGE_PROPERTIES
    result: imageAnalysisResponse

    JSON

    {
      "requests":[
        {
          "image": {
            "source": {
                "gcsUri": "img.png"
            }
          },
          "features": [
            { "type":"LABEL_DETECTION" },
            { "type":"SAFE_SEARCH_DETECTION" },
            { "type":"IMAGE_PROPERTIES" },
          ]
        }
      ]
    }
  • QUERY_KEY:QUERY_VALUE:可选。用于向 API 提供输入的查询字段。
  • AUTH_TYPE:可选。如果调用的 API 需要身份验证,此元素是必需的。请使用 OIDCOAuth2。如需了解详情,请参阅通过工作流发出经过身份验证的请求
    • AUTH_SCOPE:可选。限制应用对用户账号的访问权限。使用 scopescopes 键。

      scope 键支持字符串或字符串列表。例如:

      "https://www.googleapis.com/auth/cloud-platform"

      ["https://www.googleapis.com/auth/cloud-platform", "scope2", "scope3"]

      scopes 键除了支持字符串或字符串列表之外,还支持空格和英文逗号分隔的字符串。 例如:

      "https://www.googleapis.com/auth/cloud-platform scope2 scope3"

      "https://www.googleapis.com/auth/cloud-platform,scope2,scope3"

      如需了解详情,请参阅 适用于 Google API 的 OAuth 2.0 范围

    • AUDIENCE:可选。指定 OIDC 令牌的受众群体。默认情况下,它设置为与 url 相同的值:但是,它应该设置为服务的根网址。例如:https://region-project.cloudfunctions.net/hello_world
  • TIMEOUT_IN_SECONDS:可选。抛出异常之前,请求可以运行的时长(以秒为单位)。最大值为 1800 秒。
  • RESULT_VALUE:可选。存储 HTTP 调用步骤的结果的变量名称。

访问保存在变量中的 HTTP 响应数据

如果响应的 Content-Type 标头指定了 application/json 媒体类型,则存储在变量中的 JSON 响应会自动转换为可访问的映射。

如有必要,请修改要调用的 API,为 Content-Type 响应标头指定 application/json 媒体类型。否则,您可以使用 json.decodetext.encode 函数将响应正文转换为映射。例如:

json.decode(text.encode(RESPONSE_FROM_API))

Workflows 内置了用于访问这些数据的解析器。要从 HTTP 响应访问这些字段,请使用以下语法:

${VARIABLE_NAME.body|code|headers.PATH_TO_FIELD}

替换以下内容:

  • VARIABLE_NAME:您保存 JSON 响应的工作流变量的名称。
  • body:使用 body 字段访问 HTTP 响应的正文。
  • code:使用 code 字段访问 HTTP 响应代码。
  • headers:使用 headers 字段按名称访问 HTTP 响应标头。
  • PATH_TO_FIELD:您要访问的 JSON 响应中的字段的路径。这可能是字段的名称,如果字段嵌套在对象中,则可以采用 object1.object2.field 形式。

例如,如果 API 返回 {"age":50},并且工作流将该响应存储在名为 age_response 的变量中,则以下示例返回 age 字段的值:在此示例中为 50

age_response.body.age

示例

这些示例演示了语法。

分配来自 API 调用的响应

除非您输入自己的搜索字词,否则此示例会使用您的 Google Cloud位置构造搜索字词,并将其传递给 Wikipedia API。系统会返回相关 Wikipedia 文章的列表。

YAML

main:
  params: [input]
  steps:
    - checkSearchTermInInput:
        switch:
          - condition: '${"searchTerm" in input}'
            assign:
              - searchTerm: '${input.searchTerm}'
            next: readWikipedia
    - getLocation:
        call: sys.get_env
        args:
          name: GOOGLE_CLOUD_LOCATION
        result: location
    - setFromCallResult:
        assign:
          - searchTerm: '${text.split(location, "-")[0]}'
    - readWikipedia:
        call: http.get
        args:
          url: 'https://en.wikipedia.org/w/api.php'
          query:
            action: opensearch
            search: '${searchTerm}'
        result: wikiResult
    - returnOutput:
        return: '${wikiResult.body[1]}'

JSON

{
  "main": {
    "params": [
      "input"
    ],
    "steps": [
      {
        "checkSearchTermInInput": {
          "switch": [
            {
              "condition": "${\"searchTerm\" in input}",
              "assign": [
                {
                  "searchTerm": "${input.searchTerm}"
                }
              ],
              "next": "readWikipedia"
            }
          ]
        }
      },
      {
        "getLocation": {
          "call": "sys.get_env",
          "args": {
            "name": "GOOGLE_CLOUD_LOCATION"
          },
          "result": "location"
        }
      },
      {
        "setFromCallResult": {
          "assign": [
            {
              "searchTerm": "${text.split(location, \"-\")[0]}"
            }
          ]
        }
      },
      {
        "readWikipedia": {
          "call": "http.get",
          "args": {
            "url": "https://en.wikipedia.org/w/api.php",
            "query": {
              "action": "opensearch",
              "search": "${searchTerm}"
            }
          },
          "result": "wikiResult"
        }
      },
      {
        "returnOutput": {
          "return": "${wikiResult.body[1]}"
        }
      }
    ]
  }
}

发出外部 HTTP POST 请求

此示例向外部 HTTP 端点发出 POST 请求。

YAML

- send_message:
    call: http.post
    args:
      url: https://www.example.com/endpoint
      body:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "send_message": {
      "call": "http.post",
      "args": {
        "url": "https://www.example.com/endpoint",
        "body": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

使用标头发出外部 HTTP GET 请求

此示例使用自定义标头发出 HTTP GET 请求。您也可以在发出其他类型的 HTTP 请求时提供自定义标头定义。

YAML

- get_message:
    call: http.get
    args:
      url: https://www.example.com/endpoint
      headers:
        Content-Type: "text/plain"
      query:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "get_message": {
      "call": "http.get",
      "args": {
        "url": "https://www.example.com/endpoint",
        "headers": {
          "Content-Type": "text/plain"
        },
        "query": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

向 Cloud Run functions 发出请求时,使用 OIDC 进行身份验证

在指定网址后,通过将 auth 部分添加到工作流定义的 args 部分中,使用 OIDC 发出 HTTP 请求。

YAML

- call_my_function:
    call: http.post
    args:
      url: https://us-central1-myproject123.cloudfunctions.net/myfunc1
      auth:
        type: OIDC
      body:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "call_my_function": {
      "call": "http.post",
      "args": {
        "url": "https://us-central1-myproject123.cloudfunctions.net/myfunc1",
        "auth": {
          "type": "OIDC"
        },
        "body": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

捕获和处理 HTTP 请求错误

此示例根据 GET 请求返回的 HTTP 状态代码实现了自定义异常处理程序。工作流会捕获潜在异常并返回预定义的错误消息。如果未识别异常,则工作流执行将失败,并抛出 GET 请求返回的异常。如需了解其他错误标记,请参阅工作流错误

YAML

# Use a custom exception handler to catch exceptions and return predefined
# error messages; if the exception isn't recognized, the workflow
# execution fails and throws the exception returned by the GET request
- read_item:
    try:
      call: http.get
      args:
        url: https://example.com/someapi
        auth:
          type: OIDC
      result: API_response
    except:
      as: e
      steps:
        - known_errors:
            switch:
              - condition: ${not("HttpError" in e.tags)}
                next: connection_problem
              - condition: ${e.code == 404}
                next: url_not_found
              - condition: ${e.code == 403}
                next: auth_problem
        - unhandled_exception:
            raise: ${e}
- url_found:
    return: ${API_response.body}
- connection_problem:
    return: "Connection problem; check URL"
- url_not_found:
    return: "Sorry, URL wasn't found"
- auth_problem:
    return: "Authentication error"

JSON

[
  {
    "read_item": {
      "try": {
        "call": "http.get",
        "args": {
          "url": "https://example.com/someapi",
          "auth": {
            "type": "OIDC"
          }
        },
        "result": "API_response"
      },
      "except": {
        "as": "e",
        "steps": [
          {
            "known_errors": {
              "switch": [
                {
                  "condition": "${not(\"HttpError\" in e.tags)}",
                  "next": "connection_problem"
                },
                {
                  "condition": "${e.code == 404}",
                  "next": "url_not_found"
                },
                {
                  "condition": "${e.code == 403}",
                  "next": "auth_problem"
                }
              ]
            }
          },
          {
            "unhandled_exception": {
              "raise": "${e}"
            }
          }
        ]
      }
    }
  },
  {
    "url_found": {
      "return": "${API_response.body}"
    }
  },
  {
    "connection_problem": {
      "return": "Connection problem; check URL"
    }
  },
  {
    "url_not_found": {
      "return": "Sorry, URL wasn't found"
    }
  },
  {
    "auth_problem": {
      "return": "Authentication error"
    }
  }
]

后续步骤