发出 HTTP 请求

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

调用 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"
    }
  }
]

后续步骤