Realiza una solicitud HTTP

Puedes definir un paso del flujo de trabajo que realice una llamada HTTP y asignar la respuesta de la llamada a una variable. Por ejemplo, puedes invocar un servicio Google Cloud como Cloud Run Functions o Cloud Run a través de una solicitud HTTP.

Invocar un servicio de Google Cloud a través de una solicitud HTTP no debe confundirse con el uso de conectores de Workflows para realizar operaciones de API. Los conectores simplifican las llamadas a los servicios porque manejan el formato de las solicitudes por ti y proporcionan métodos y argumentos para que no necesites conocer los detalles de una API de Google Cloud .

Invoca un extremo HTTP

Este tipo de paso te permite realizar una solicitud HTTP. Se admiten solicitudes HTTP y HTTPS. Los métodos de solicitud HTTP más comunes tienen un atajo de llamada (como http.get y http.post), pero puedes realizar cualquier tipo de solicitud HTTP configurando el campo call en http.request y especificando el tipo de solicitud con el 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"
      }
    }
  ]
    

Reemplaza lo siguiente:

  • HTTP_REQUEST: Obligatorio. Usa una de las siguientes opciones para las solicitudes HTTP:
    • http.delete
    • http.get
    • http.patch
    • http.post
    • http.put
    • http.request
  • URL_VALUE: Obligatorio. Es la URL a la que se envía la solicitud.
  • REQUEST_METHOD: Se requiere si se usa el tipo de llamada http.request. Es el tipo de método de solicitud HTTP que se usará. Por ejemplo:
    • GET
    • POST
    • PATCH
    • DELETE
  • REGISTERED_SERVICE: es opcional. Es un nombre de servicio del Directorio de servicios registrado en el formato projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME. Para obtener más información, consulta Invoca un extremo privado con el registro de servicios de Service Directory.
  • HEADER_KEY:HEADER_VALUE: Opcional. Son los campos de encabezado para proporcionar entrada a la API.

    Si usas un encabezado Content-Type para especificar el tipo de medio del cuerpo de la solicitud, solo se admiten los siguientes tipos:

    • application/json o application/type+json: Debe ser un mapa.
    • application/x-www-form-urlencoded: Debe ser una cadena sin codificar.
    • text/type: Debe ser una cadena.

    Si se especifica un encabezado Content-Type, el cuerpo se codifica según lo prescrito. Por ejemplo, podría ser JSON o estar codificado como URL.

    Si usas un encabezado User-Agent para identificar el usuario-agente que realiza la solicitud, se aplica lo siguiente:

    • El valor predeterminado es GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs).
    • Si se especifica un valor, se agrega GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs) a ese valor.

      Por ejemplo, si se especifica User-Agent: "MY_USER_AGENT_VALUE", el encabezado de la solicitud HTTP sería el siguiente (con un espacio entre el valor especificado y el valor predeterminado agregado):

      MY_USER_AGENT_VALUE GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
  • BODY_KEY:BODY_VALUE: Opcional. Son los campos del cuerpo que proporcionan entrada a la API.

    Si no se especifica un encabezado Content-Type y hay un cuerpo de solicitud presente, se aplica lo siguiente:

    • Si el valor del cuerpo son bytes, el encabezado se establece en Content-Type: application/octet-stream.
    • De lo contrario, el cuerpo se codifica en JSON y el encabezado se establece en Content-Type: application/json; charset=utf-8.
    El siguiente ejemplo muestra una estructura de cuerpo equivalente a una carga útil de 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. Son los campos de consulta para proporcionar entrada a la API.
  • AUTH_TYPE: es opcional. Obligatorio si la API a la que se llama requiere autenticación. Usa OIDC o OAuth2. Para obtener más información, consulta Realiza solicitudes autenticadas desde un flujo de trabajo.
    • AUTH_SCOPE: es opcional. Limita el acceso de una aplicación a la cuenta de un usuario. Usa la tecla scope o scopes.

      La clave scope admite una cadena o una lista de cadenas. Por ejemplo:

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

      o

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

      La clave scopes, además de admitir una cadena o una lista de cadenas, admite cadenas separadas por espacios y comas. Por ejemplo:

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

      o

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

      Si deseas obtener más información, consulta Permisos de OAuth 2.0 para las APIs de Google.

    • AUDIENCE: es opcional. Especifica el público del token de OIDC. De forma predeterminada, se establece en el mismo valor que url. Sin embargo, debe establecerse en la URL raíz de tu servicio. Por ejemplo:https://region-project.cloudfunctions.net/hello_world.
  • TIMEOUT_IN_SECONDS: es opcional. Tiempo en segundos que se permite que se ejecute una solicitud antes de arrojar una excepción. El máximo es de 1,800 segundos.
  • RESULT_VALUE: es opcional. Nombre de la variable en la que se almacena el resultado de un paso de invocación HTTP.

Accede a los datos de respuesta HTTP guardados en una variable

Si el encabezado Content-Type de la respuesta especifica un tipo de medio application/json, la respuesta JSON que se almacena en una variable se convierte automáticamente en un mapa al que se puede acceder.

Si es necesario, modifica la API a la que se llama para especificar un tipo de medio application/json para el encabezado de respuesta Content-Type. De lo contrario, puedes usar las funciones json.decode y text.encode para convertir el cuerpo de la respuesta en un mapa. Por ejemplo:

json.decode(text.encode(RESPONSE_FROM_API))

Workflows incluye un analizador integrado para acceder a estos datos. Para acceder a los campos de la respuesta HTTP, usa la siguiente sintaxis:

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

Reemplaza lo siguiente:

  • VARIABLE_NAME: Es el nombre de la variable de flujo en la que guardaste una respuesta JSON.
  • body: Usa el campo body para acceder al cuerpo de la respuesta HTTP.
  • code: Usa el campo code para acceder al código de respuesta HTTP.
  • headers: Usa el campo headers para acceder a los encabezados de respuesta HTTP por nombre.
  • PATH_TO_FIELD: Es la ruta de acceso al campo en la respuesta JSON al que deseas acceder. Puede ser el nombre del campo o, si el campo está anidado dentro de un objeto, puede tomar la forma de object1.object2.field.

Por ejemplo, si una API devuelve {"age":50} y un flujo de trabajo almacena esa respuesta en una variable llamada age_response, el siguiente ejemplo devuelve el valor del campo age; en este caso, 50:

age_response.body.age

Muestras

En estos ejemplos, se muestra la sintaxis.

Asigna la respuesta de una llamada a la API

A menos que ingreses tu propio término de búsqueda, este ejemplo usa tu ubicación de Google Cloudpara construir un término de búsqueda, que pasa a la API de Wikipedia. Se muestra una lista de artículos de Wikipedia relacionados.

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

Realiza una solicitud HTTP POST externa

En este ejemplo, se realiza una solicitud POST a un extremo 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}"
    }
  }
]

Realiza una solicitud HTTP GET externa con encabezados

En este ejemplo, se realiza una solicitud HTTP GET con un encabezado personalizado. También puedes proporcionar definiciones de encabezado personalizadas cuando realices otros tipos de solicitudes 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}"
    }
  }
]

Usa OIDC para autenticarte cuando realices una solicitud a Cloud Run Functions

En este ejemplo, se realiza una solicitud HTTP con OIDC agregando una sección auth a la sección args de la definición del flujo de trabajo, después de especificar la 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}"
    }
  }
]

Cómo detectar y controlar errores de solicitudes HTTP

En este ejemplo, se implementa un controlador de excepciones personalizado basado en el código de estado HTTP que devuelve la solicitud GET. El flujo de trabajo detecta una posible excepción y devuelve un mensaje de error predefinido. Si no se reconoce una excepción, falla la ejecución del flujo de trabajo y se arroja la excepción que devolvió la solicitud GET. Para obtener información sobre otras etiquetas de error, consulta Errores de flujo de trabajo.

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

¿Qué sigue?