Fazer uma solicitação HTTP

É possível definir uma etapa de fluxo de trabalho que faça uma chamada HTTP e atribuir a resposta da chamada a uma variável. Por exemplo, é possível invocar um serviço do Google Cloud como o Cloud Functions ou o Cloud Run por uma solicitação HTTP.

Invocar um endpoint HTTP

Esse tipo de etapa permite fazer uma solicitação HTTP. Tanto solicitações HTTP como HTTPS são compatíveis. Os métodos de solicitação HTTP mais comuns têm um atalho de chamada (como http.get e http.post), mas é possível fazer qualquer tipo de solicitação HTTP definindo o campo call como http.request e especificando o tipo de solicitação usando o campo 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"
      }
    }
  ]
    

Substitua:

  • HTTP_REQUEST: obrigatório. Use um dos seguintes para solicitações HTTP:
    • http.delete
    • http.get
    • http.patch
    • http.post
    • http.put
    • http.request
  • URL_VALUE: obrigatório. URL para onde a solicitação é enviada.
  • REQUEST_METHOD: obrigatório se o tipo de chamada for http.request. O tipo de método de solicitação HTTP a ser usado. Por exemplo:
    • GET
    • POST
    • PATCH
    • DELETE
  • REGISTERED_SERVICE: opcional. Um nome de serviço registrado do Diretório de serviços no formato projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME. Para mais informações, consulte Invocar um endpoint particular compatível com o VPC Service Controls.
  • HEADER_KEY:HEADER_VALUE: opcional. Campos do cabeçalho para fornecer entrada à API.

    Se você usar um cabeçalho Content-Type para especificar o tipo de mídia do corpo da solicitação, somente os tipos a seguir serão compatíveis:

    • application/json ou application/type+json: precisa ser um mapa
    • application/x-www-form-urlencoded: precisa ser uma string não codificada
    • É preciso que text/type seja uma string.

    Se um cabeçalho Content-Type for especificado, o corpo será codificado conforme prescrito. Por exemplo, pode ser JSON ou codificado como URL.

    Se você estiver usando um cabeçalho User-Agent para identificar o user agent solicitante, as seguintes condições serão aplicadas:

    • O padrão é GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
    • Se um valor for especificado, GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs) será anexado a esse valor.

      Por exemplo, se User-Agent: "MY_USER_AGENT_VALUE" for especificado, o cabeçalho da solicitação HTTP será o seguinte (com um espaço entre o valor especificado e o padrão anexado):

      MY_USER_AGENT_VALUE GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
  • BODY_KEY:BODY_VALUE: opcional. Campos do corpo para fornecer a entrada à API.

    Se um cabeçalho Content-Type não for especificado e um corpo de solicitação estiver presente, o seguinte será aplicado:

    • Se o valor do corpo for bytes, o cabeçalho será definido como Content-Type: application/octet-stream.
    • Caso contrário, o corpo é codificado em JSON e o cabeçalho é definido como Content-Type: application/json; charset=utf-8.
    O exemplo a seguir é de uma estrutura de corpo equivalente a um payload 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: opcional. Campos de consulta para fornecer a entrada à API.
  • AUTH_TYPE: opcional. Obrigatório se a API que está sendo chamada exige autenticação. Use OIDC ou OAuth2. Para mais informações, consulte Fazer solicitações autenticadas de um fluxo de trabalho.
    • AUTH_SCOPE: opcional. Limita o acesso de um aplicativo à conta de um usuário. Use a tecla scope ou scopes.

      A chave scope aceita uma string ou uma lista de strings. Exemplo:

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

      ou

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

      A chave scopes, além de oferecer suporte a uma string ou lista de strings, oferece suporte a strings separadas por espaços e vírgulas. Exemplo:

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

      ou

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

      Para mais informações, consulte Escopos do OAuth 2.0 para APIs do Google.

    • AUDIENCE: opcional. Especifica o público-alvo do token OIDC. Por padrão, ele é definido como o mesmo valor de url. No entanto, ele precisa ser definido como o URL raiz do serviço. Exemplo: https://region-project.cloudfunctions.net/hello_world.
  • TIMEOUT_IN_SECONDS: opcional. Quanto tempo (em segundos) uma solicitação pode ser executada antes de gerar uma exceção. O máximo é 1.800 segundos.
  • RESULT_VALUE: opcional. Nome da variável em que o resultado de uma etapa de invocação HTTP é armazenado.

Acessar dados de resposta HTTP salvos em uma variável

Se o cabeçalho Content-Type da resposta especificar um tipo de mídia application/json, a resposta JSON armazenada em uma variável será convertida automaticamente em um mapa que pode ser acessado.

Se necessário, modifique a API que está sendo chamada para especificar um tipo de mídia application/json para o cabeçalho de resposta Content-Type. Caso contrário, use as funções json.decode e text.encode para converter o corpo da resposta em um mapa. Exemplo:

json.decode(text.encode(RESPONSE_FROM_API))

O Workflows tem um analisador integrado para acessar esses dados. Para acessar os campos da resposta HTTP, use a seguinte sintaxe:

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

Substitua:

  • VARIABLE_NAME: o nome da variável de fluxo de trabalho em que você salvou uma resposta JSON.
  • body: use o campo body para acessar o corpo da resposta HTTP.
  • code: use o campo code para acessar o código de resposta HTTP.
  • headers: use o campo headers para acessar os cabeçalhos de resposta HTTP por nome.
  • PATH_TO_FIELD: o caminho para o campo na resposta JSON que você quer acessar. Pode ser simplesmente o nome do campo ou, se o campo estiver aninhado em um objeto, pode assumir a forma de object1.object2.field.

Por exemplo, se uma API retorna {"age":50} e um fluxo de trabalho armazena essa resposta em uma variável chamada age_response, o exemplo a seguir retorna o valor do campo age. Nesse caso, 50:

age_response.body.age

Amostras

Estas amostras demonstram a sintaxe.

Atribuir a resposta de uma chamada de API

A menos que você insira seu próprio termo de pesquisa, este exemplo usa seu local do Google Cloud para criar um termo de pesquisa, que será transmitido para a API da Wikipédia. Uma lista de artigos relacionados da Wikipédia é retornada.

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

Fazer uma solicitação POST HTTP externa

Este exemplo faz uma solicitação POST para um endpoint HTTP externo.

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

Fazer uma solicitação HTTP GET externa com cabeçalhos

Este exemplo faz uma solicitação HTTP GET com um cabeçalho personalizado. Também é possível fornecer definições personalizadas de cabeçalho ao fazer outros tipos de solicitações 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}"
    }
  }
]

Usar o OIDC para autenticar ao fazer uma solicitação para o Cloud Run functions

Neste exemplo, fazemos uma solicitação HTTP usando o OIDC adicionando uma seção auth à seção args da definição do fluxo de trabalho, depois de especificar o URL.

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

Detectar e processar erros de solicitação HTTP

Este exemplo implementa um gerenciador de exceções personalizado com base no código de status HTTP retornado pela solicitação GET. O fluxo de trabalho captura uma possível exceção e retorna uma mensagem de erro predefinida. Se uma exceção não for reconhecida, a execução do fluxo de trabalho falhará e gerará a exceção conforme retornada pela solicitação GET. Para outras tags de erro, consulte Erros de fluxo de trabalho.

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

A seguir