Crea tareas de destino HTTP

Con esta versión de destinos HTTP, los controladores de Cloud Tasks ahora pueden ejecutarse en cualquier extremo HTTP con una dirección IP pública, como Cloud Functions, Cloud Run y GKE., Compute Engine o incluso un servidor web local. Tus tareas pueden ejecutarse en cualquiera de estos servicios de manera confiable y configurable.

En esta página, se muestra cómo crear tareas de destino de HTTP de manera programática y colocarlas en colas de Cloud Tasks.

Si decides especificar un nombre para la tarea, Cloud Tasks puede usar ese nombre para garantizar la anulación de la duplicación de la tarea, aunque el procesamiento necesario para esto puede aumentar la latencia.

En general, se crean tareas en el formato de una solicitud HTTP. Usar las bibliotecas cliente y una cuenta de servicio, como en los siguientes ejemplos, puede ayudarte a administrar los detalles de comunicación con el servidor de Cloud Tasks y facilitar la creación de tareas.

Crea tareas de destino HTTP

Para las tareas que tienen objetivos HTTP, hay dos formas de crear tareas.

  • Método BufferTask: Usa este método si tu cola está configurada para almacenar tareas en búfer frente a un servicio. La cola debe tener enrutamiento a nivel de cola.

  • Método CreateTask: Es más complejo. Debes crear un objeto de tarea de forma explícita. Usa este método si las tareas de la cola tienen diferentes configuraciones de enrutamiento. En este caso, especifica el enrutamiento a nivel de la tarea.

Método BufferTask

Limitaciones

  • Bibliotecas cliente: Las bibliotecas cliente no admiten el método BufferTask.

  • API de RPC: El método BufferTask no es compatible con la API de RPC.

  • Enrutamiento a nivel de cola: para usar el método BufferTask, la cola debe utilizar el enrutamiento a nivel de la cola (de lo contrario, la tarea no tendrá información de enrutamiento). Si la cola aún no usa el enrutamiento a nivel de la cola, consulta Configura el enrutamiento a nivel de la cola para tareas HTTP.

Ejemplo de REST

En el siguiente fragmento de código, se muestra un ejemplo de creación de una tarea con el método BufferTask por medio de curl:

  curl -X HTTP_METHOD\
   "https://cloudtasks.googleapis.com/v2/projects/PROJECT_ID/locations/LOCATION/queues/QUEUE_ID/tasks:buffer" \

Reemplaza lo siguiente:

  • HTTP_METHOD: Es el método HTTP para la solicitud, por ejemplo, GET o POST.
  • PROJECT_ID: El ID del proyecto de Google Cloud. Para ello, ejecuta el siguiente comando en la terminal:
    gcloud config get-value project
  • LOCATION: La ubicación de la fila.
  • QUEUE_ID: El ID de la cola

Método CreateTask

Para crear una tarea con el método CreateTask, debes crear y definir explícitamente el objeto de tarea. Debes especificar el servicio y el controlador que procesan la tarea.

De manera opcional, puedes pasar datos específicos de la tarea al controlador. También puedes ajustar la configuración de la tarea, como programar una hora en el futuro en la que se debe ejecutar o limitar la cantidad de veces que deseas que se reintente la tarea si falla.

En los siguientes ejemplos, se sigue el método CreateTask para crear una tarea con las bibliotecas cliente de Cloud Tasks.

C#


using Google.Cloud.Tasks.V2;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using System;

class CreateHttpTask
{
    public string CreateTask(
        string projectId = "YOUR-PROJECT-ID",
        string location = "us-central1",
        string queue = "my-queue",
        string url = "http://example.com/taskhandler",
        string payload = "Hello World!",
        int inSeconds = 0)
    {
        CloudTasksClient client = CloudTasksClient.Create();
        QueueName parent = new QueueName(projectId, location, queue);

        var response = client.CreateTask(new CreateTaskRequest
        {
            Parent = parent.ToString(),
            Task = new Task
            {
                HttpRequest = new HttpRequest
                {
                    HttpMethod = HttpMethod.Post,
                    Url = url,
                    Body = ByteString.CopyFromUtf8(payload)
                },
                ScheduleTime = Timestamp.FromDateTime(
                    DateTime.UtcNow.AddSeconds(inSeconds))
            }
        });

        Console.WriteLine($"Created Task {response.Name}");
        return response.Name;
    }
}

Python

import datetime
import json
from typing import Dict, Optional

from google.cloud import tasks_v2
from google.protobuf import duration_pb2, timestamp_pb2

def create_http_task(
    project: str,
    location: str,
    queue: str,
    url: str,
    json_payload: Dict,
    scheduled_seconds_from_now: Optional[int] = None,
    task_id: Optional[str] = None,
    deadline_in_seconds: Optional[int] = None,
) -> tasks_v2.Task:
    """Create an HTTP POST task with a JSON payload.
    Args:
        project: The project ID where the queue is located.
        location: The location where the queue is located.
        queue: The ID of the queue to add the task to.
        url: The target URL of the task.
        json_payload: The JSON payload to send.
        scheduled_seconds_from_now: Seconds from now to schedule the task for.
        task_id: ID to use for the newly created task.
        deadline_in_seconds: The deadline in seconds for task.
    Returns:
        The newly created task.
    """

    # Create a client.
    client = tasks_v2.CloudTasksClient()

    # Construct the task.
    task = tasks_v2.Task(
        http_request=tasks_v2.HttpRequest(
            http_method=tasks_v2.HttpMethod.POST,
            url=url,
            headers={"Content-type": "application/json"},
            body=json.dumps(json_payload).encode(),
        ),
        name=(
            client.task_path(project, location, queue, task_id)
            if task_id is not None
            else None
        ),
    )

    # Convert "seconds from now" to an absolute Protobuf Timestamp
    if scheduled_seconds_from_now is not None:
        timestamp = timestamp_pb2.Timestamp()
        timestamp.FromDatetime(
            datetime.datetime.utcnow()
            + datetime.timedelta(seconds=scheduled_seconds_from_now)
        )
        task.schedule_time = timestamp

    # Convert "deadline in seconds" to a Protobuf Duration
    if deadline_in_seconds is not None:
        duration = duration_pb2.Duration()
        duration.FromSeconds(deadline_in_seconds)
        task.dispatch_deadline = duration

    # Use the client to send a CreateTaskRequest.
    return client.create_task(
        tasks_v2.CreateTaskRequest(
            # The queue to add the task to
            parent=client.queue_path(project, location, queue),
            # The task itself
            task=task,
        )
    )

Ten en cuenta el archivo requirements.txt:

google-cloud-tasks==2.13.1

Java

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.HttpRequest;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.Charset;

public class CreateHttpTask {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String locationId = "us-central1";
    String queueId = "my-queue";
    createTask(projectId, locationId, queueId);
  }

  // Create a task with a HTTP target using the Cloud Tasks client.
  public static void createTask(String projectId, String locationId, String queueId)
      throws IOException {

    // Instantiates a client.
    try (CloudTasksClient client = CloudTasksClient.create()) {
      String url = "https://example.com/taskhandler";
      String payload = "Hello, World!";

      // Construct the fully qualified queue name.
      String queuePath = QueueName.of(projectId, locationId, queueId).toString();

      // Construct the task body.
      Task.Builder taskBuilder =
          Task.newBuilder()
              .setHttpRequest(
                  HttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(payload, Charset.defaultCharset()))
                      .setUrl(url)
                      .setHttpMethod(HttpMethod.POST)
                      .build());

      // Send create task request.
      Task task = client.createTask(queuePath, taskBuilder.build());
      System.out.println("Task created: " + task.getName());
    }
  }
}

Ten en cuenta el archivo pom.xml:

<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.tasks</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>

  <!--
    The parent pom defines common style checks and testing strategies for our samples.
    Removing or replacing it should not affect the execution of the samples in anyway.
  -->
  <parent>
    <groupId>com.google.cloud.samples</groupId>
    <artifactId>shared-configuration</artifactId>
    <version>1.2.0</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>libraries-bom</artifactId>
        <version>26.32.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.4.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

PHP

use Google\Cloud\Tasks\V2\Client\CloudTasksClient;
use Google\Cloud\Tasks\V2\CreateTaskRequest;
use Google\Cloud\Tasks\V2\HttpMethod;
use Google\Cloud\Tasks\V2\HttpRequest;
use Google\Cloud\Tasks\V2\Task;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $locationId = 'The Location ID';
// $queueId = 'The Cloud Tasks Queue ID';
// $url = 'The full url path that the task request will be sent to.'
// $payload = 'The payload your task should carry to the task handler. Optional';

// Instantiate the client and queue name.
$client = new CloudTasksClient();
$queueName = $client->queueName($projectId, $locationId, $queueId);

// Create an Http Request Object.
$httpRequest = new HttpRequest();
// The full url path that the task request will be sent to.
$httpRequest->setUrl($url);
// POST is the default HTTP method, but any HTTP method can be used.
$httpRequest->setHttpMethod(HttpMethod::POST);
// Setting a body value is only compatible with HTTP POST and PUT requests.
if (!empty($payload)) {
    $httpRequest->setBody($payload);
}

// Create a Cloud Task object.
$task = new Task();
$task->setHttpRequest($httpRequest);

// Send request and print the task name.
$request = (new CreateTaskRequest())
    ->setParent($queueName)
    ->setTask($task);
$response = $client->createTask($request);
printf('Created task %s' . PHP_EOL, $response->getName());

Ten en cuenta el archivo composer.json:

{
    "require": {
        "google/cloud-tasks": "^1.14"
    }
}

Go


// Command createHTTPtask constructs and adds a task to a Cloud Tasks Queue.
package main

import (
	"context"
	"fmt"

	cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
	taskspb "cloud.google.com/go/cloudtasks/apiv2/cloudtaskspb"
)

// createHTTPTask creates a new task with a HTTP target then adds it to a Queue.
func createHTTPTask(projectID, locationID, queueID, url, message string) (*taskspb.Task, error) {

	// Create a new Cloud Tasks client instance.
	// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
	ctx := context.Background()
	client, err := cloudtasks.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	// Build the Task queue path.
	queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)

	// Build the Task payload.
	// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
	req := &taskspb.CreateTaskRequest{
		Parent: queuePath,
		Task: &taskspb.Task{
			// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
			MessageType: &taskspb.Task_HttpRequest{
				HttpRequest: &taskspb.HttpRequest{
					HttpMethod: taskspb.HttpMethod_POST,
					Url:        url,
				},
			},
		},
	}

	// Add a payload message if one is present.
	req.Task.GetHttpRequest().Body = []byte(message)

	createdTask, err := client.CreateTask(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("cloudtasks.CreateTask: %w", err)
	}

	return createdTask, nil
}

Node.js

// Imports the Google Cloud Tasks library.
const {CloudTasksClient} = require('@google-cloud/tasks');

// Instantiates a client.
const client = new CloudTasksClient();

async function createHttpTask() {
  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-queue';
  // const location = 'us-central1';
  // const url = 'https://example.com/taskhandler';
  // const payload = 'Hello, World!';
  // const inSeconds = 180;

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  const task = {
    httpRequest: {
      headers: {
        'Content-Type': 'text/plain', // Set content type to ensure compatibility your application's request parsing
      },
      httpMethod: 'POST',
      url,
    },
  };

  if (payload) {
    task.httpRequest.body = Buffer.from(payload).toString('base64');
  }

  if (inSeconds) {
    // The time when the task is scheduled to be attempted.
    task.scheduleTime = {
      seconds: parseInt(inSeconds) + Date.now() / 1000,
    };
  }

  // Send create task request.
  console.log('Sending task:');
  console.log(task);
  const request = {parent: parent, task: task};
  const [response] = await client.createTask(request);
  console.log(`Created task ${response.name}`);
}
createHttpTask();

Ten en cuenta el archivo package.json:

{
  "name": "appengine-cloudtasks",
  "description": "Google App Engine Cloud Tasks example.",
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "private": true,
  "engines": {
    "node": ">=16.0.0"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "c8 mocha -p -j 2 --timeout 30000",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^4.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^8.0.0",
    "chai": "^4.2.0",
    "mocha": "^10.0.0",
    "uuid": "^9.0.0"
  }
}

Rita

require "google/cloud/tasks"

# Create a Task with an HTTP Target
#
# @param [String] project_id Your Google Cloud Project ID.
# @param [String] location_id Your Google Cloud Project Location ID.
# @param [String] queue_id Your Google Cloud Tasks Queue ID.
# @param [String] url The full path to sent the task request to.
# @param [String] payload The request body of your task.
# @param [Integer] seconds The delay, in seconds, to process your task.
def create_http_task project_id, location_id, queue_id, url, payload: nil, seconds: nil
  # Instantiates a client.
  client = Google::Cloud::Tasks.cloud_tasks

  # Construct the fully qualified queue name.
  parent = client.queue_path project: project_id, location: location_id, queue: queue_id

  # Construct task.
  task = {
    http_request: {
      http_method: "POST",
      url:         url
    }
  }

  # Add payload to task body.
  task[:http_request][:body] = payload if payload

  # Add scheduled time to task.
  if seconds
    timestamp = Google::Protobuf::Timestamp.new
    timestamp.seconds = Time.now.to_i + seconds.to_i
    task[:schedule_time] = timestamp
  end

  # Send create task request.
  puts "Sending task #{task}"

  response = client.create_task parent: parent, task: task

  puts "Created task #{response.name}" if response.name
end

Configura cuentas de servicio para la autenticación del controlador de destino HTTP

Cloud Tasks puede llamar a controladores de destino HTTP que requieren autenticación si tienes una cuenta de servicio con las credenciales adecuadas para acceder al controlador.

Si tienes una cuenta de servicio actual que deseas usar, puedes hacerlo. Solo otórgale las funciones adecuadas. Estas instrucciones abarcan la creación de una cuenta de servicio nueva, en particular, para esta función. La cuenta de servicio nueva o existente que se usa para la autenticación de Cloud Tasks debe estar en el mismo proyecto que las colas de Cloud Tasks.

  1. En la consola de Google Cloud, ve a la página Cuentas de servicio.

    Ir a Cuentas de servicio

  2. Si es necesario, selecciona el proyecto adecuado.

  3. Haz clic en Crear cuenta de servicio.

  4. En la sección Detalles de la cuenta de servicio, asígnale un nombre a la cuenta. La consola crea un nombre de cuenta de correo electrónico relacionado para la cuenta. Así es como haces referencia a la cuenta. También puedes agregar una descripción del objetivo de la cuenta. Haz clic en Crear y continuar.

  5. En la sección Otorga a esta cuenta de servicio acceso al proyecto, haz clic en Selecciona un rol. Busca y selecciona Agregador de elementos en cola de Cloud Tasks. Este rol le otorga permiso a la cuenta de servicio para agregar tareas a la cola.

  6. Haz clic en + Agregar otra función.

  7. Haga clic en Selecciona un rol. Busca y selecciona Usuario de cuenta de servicio. Esta función permite que la cuenta de servicio autorice a la cola para crear tokens en su nombre con las credenciales de la cuenta de servicio.

  8. Si tu controlador es parte de Google Cloud, otorga a la cuenta de servicio la función asociada con el acceso al servicio en el que se ejecuta tu controlador. Cada servicio dentro de Google Cloud requiere una función diferente. Por ejemplo, para acceder a un controlador en Cloud Run, se necesita la función Invocador de Cloud Run, y así sucesivamente. Puedes usar la cuenta de servicio que acabas de crear o cualquier otra cuenta de servicio de tu proyecto.

  9. Haz clic en Listo para terminar de crear la cuenta de servicio.

Cloud Tasks en sí debe tener una cuenta de servicio propia que tenga la función Cloud Tasks Service Agent otorgada. Esto es para que pueda generar tokens de encabezado basados en las credenciales asociadas con la cuenta de servicio de Cloud Tasks a fin de autenticarse con tu objetivo de controlador. La cuenta de servicio de Cloud Tasks con esta función otorgada se crea automáticamente cuando habilitas la API de Cloud Tasks, a menos que la hayas habilitado antes del 19 de marzo de 2019. Si ese es el caso, debes agregar la función manualmente.

Usa tareas de destino HTTP con tokens de autenticación

Para autenticar entre Cloud Tasks y un controlador de destino HTTP que requiera esa autenticación, Cloud Tasks crea un token de encabezado. Este token se basa en las credenciales de la cuenta de servicio Cloud Tasks Enqueuer, identificada por su dirección de correo electrónico. La cuenta de servicio que se usa para la autenticación debe ser parte del mismo proyecto en el que reside tu lista de tareas en cola de Cloud. La solicitud, con el token de encabezado, se envía a través de HTTPS, desde la cola hasta el controlador. Puedes usar un token de ID o un token de acceso. Por lo general, los tokens de ID se deben usar para cualquier controlador que se ejecute en Google Cloud, por ejemplo, en Cloud Functions o Cloud Run. La excepción principal es para las APIs de Google alojadas en *.googleapis.com: estas APIs esperan un token de acceso. Especifica un token de ID (OIDC) o un token de acceso (OAuth) en la tarea.

Método BufferTask

Limitaciones

  • Bibliotecas cliente: Las bibliotecas cliente no admiten el método BufferTask.

  • API de RPC: El método BufferTask no es compatible con la API de RPC.

  • Enrutamiento a nivel de cola: para usar el método BufferTask, la cola debe utilizar el enrutamiento a nivel de la cola (de lo contrario, la tarea no tendrá información de enrutamiento). Si la cola aún no usa el enrutamiento a nivel de la cola, consulta Configura el enrutamiento a nivel de la cola para tareas HTTP.

Ejemplo de REST con autenticación

Cuando usas el método BufferTask para crear tareas, cualquier configuración de OIDC o de OAuth que se establezca a nivel de la cola anula la configuración a nivel de la tarea. Para configurar la autenticación a nivel de cola, consulta Crea colas de Cloud Tasks. Sin embargo, puedes autenticarte cuando crees la tarea. En el siguiente ejemplo, se usan credenciales predeterminadas de la aplicación para autenticarse cuando se crea una tarea:

  curl -X HTTP_METHOD\
   "https://cloudtasks.googleapis.com/v2/projects/PROJECT_ID/locations/LOCATION/queues/QUEUE_ID/tasks:buffer" \
      -H "Authorization: Bearer ACCESS_TOKEN"

Reemplaza lo siguiente:

  • HTTP_METHOD: Es el método HTTP para la solicitud, por ejemplo, GET o POST.
  • PROJECT_ID: El ID del proyecto de Google Cloud. Para ello, ejecuta el siguiente comando en la terminal:
    gcloud config get-value project
  • LOCATION: La ubicación de la fila.
  • QUEUE_ID: El ID de la cola
  • ACCESS_TOKEN: Es el token de acceso. Para ello, ejecuta lo siguiente en tu terminal:
    1. gcloud auth application-default login
    2. gcloud auth application-default print-access-token

Método CreateTask

En los siguientes ejemplos, se usa el método CreateTask con las bibliotecas cliente de Cloud Tasks para crear una tarea que también incluye la creación de un token de encabezado. tokens de ID que se usan en los ejemplos. Si quieres usar un token de acceso, reemplaza el parámetro de OIDC por el parámetro de OAuth apropiado para el lenguaje en la construcción de la solicitud.

Python

from typing import Optional

from google.cloud import tasks_v2

def create_http_task_with_token(
    project: str,
    location: str,
    queue: str,
    url: str,
    payload: bytes,
    service_account_email: str,
    audience: Optional[str] = None,
) -> tasks_v2.Task:
    """Create an HTTP POST task with an OIDC token and an arbitrary payload.
    Args:
        project: The project ID where the queue is located.
        location: The location where the queue is located.
        queue: The ID of the queue to add the task to.
        url: The target URL of the task.
        payload: The payload to send.
        service_account_email: The service account to use for generating the OIDC token.
        audience: Audience to use when generating the OIDC token.
    Returns:
        The newly created task.
    """

    # Create a client.
    client = tasks_v2.CloudTasksClient()

    # Construct the request body.
    task = tasks_v2.Task(
        http_request=tasks_v2.HttpRequest(
            http_method=tasks_v2.HttpMethod.POST,
            url=url,
            oidc_token=tasks_v2.OidcToken(
                service_account_email=service_account_email,
                audience=audience,
            ),
            body=payload,
        ),
    )

    # Use the client to build and send the task.
    return client.create_task(
        tasks_v2.CreateTaskRequest(
            parent=client.queue_path(project, location, queue),
            task=task,
        )
    )

Ten en cuenta el archivo requirements.txt:

google-cloud-tasks==2.13.1

Java

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.HttpRequest;
import com.google.cloud.tasks.v2.OidcToken;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.Charset;

public class CreateHttpTaskWithToken {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String locationId = "us-central1";
    String queueId = "my-queue";
    String serviceAccountEmail =
        "java-docs-samples-testing@java-docs-samples-testing.iam.gserviceaccount.com";
    createTask(projectId, locationId, queueId, serviceAccountEmail);
  }

  // Create a task with a HTTP target and authorization token using the Cloud Tasks client.
  public static void createTask(
      String projectId, String locationId, String queueId, String serviceAccountEmail)
      throws IOException {

    // Instantiates a client.
    try (CloudTasksClient client = CloudTasksClient.create()) {
      String url =
          "https://example.com/taskhandler"; // The full url path that the request will be sent to
      String payload = "Hello, World!"; // The task HTTP request body

      // Construct the fully qualified queue name.
      String queuePath = QueueName.of(projectId, locationId, queueId).toString();

      // Add your service account email to construct the OIDC token.
      // in order to add an authentication header to the request.
      OidcToken.Builder oidcTokenBuilder =
          OidcToken.newBuilder().setServiceAccountEmail(serviceAccountEmail);

      // Construct the task body.
      Task.Builder taskBuilder =
          Task.newBuilder()
              .setHttpRequest(
                  HttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(payload, Charset.defaultCharset()))
                      .setHttpMethod(HttpMethod.POST)
                      .setUrl(url)
                      .setOidcToken(oidcTokenBuilder)
                      .build());

      // Send create task request.
      Task task = client.createTask(queuePath, taskBuilder.build());
      System.out.println("Task created: " + task.getName());
    }
  }
}

Ten en cuenta el archivo pom.xml:

<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.tasks</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>

  <!--
    The parent pom defines common style checks and testing strategies for our samples.
    Removing or replacing it should not affect the execution of the samples in anyway.
  -->
  <parent>
    <groupId>com.google.cloud.samples</groupId>
    <artifactId>shared-configuration</artifactId>
    <version>1.2.0</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>libraries-bom</artifactId>
        <version>26.32.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.4.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Go

import (
	"context"
	"fmt"

	cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
	taskspb "cloud.google.com/go/cloudtasks/apiv2/cloudtaskspb"
)

// createHTTPTaskWithToken constructs a task with a authorization token
// and HTTP target then adds it to a Queue.
func createHTTPTaskWithToken(projectID, locationID, queueID, url, email, message string) (*taskspb.Task, error) {
	// Create a new Cloud Tasks client instance.
	// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
	ctx := context.Background()
	client, err := cloudtasks.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	// Build the Task queue path.
	queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)

	// Build the Task payload.
	// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
	req := &taskspb.CreateTaskRequest{
		Parent: queuePath,
		Task: &taskspb.Task{
			// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
			MessageType: &taskspb.Task_HttpRequest{
				HttpRequest: &taskspb.HttpRequest{
					HttpMethod: taskspb.HttpMethod_POST,
					Url:        url,
					AuthorizationHeader: &taskspb.HttpRequest_OidcToken{
						OidcToken: &taskspb.OidcToken{
							ServiceAccountEmail: email,
						},
					},
				},
			},
		},
	}

	// Add a payload message if one is present.
	req.Task.GetHttpRequest().Body = []byte(message)

	createdTask, err := client.CreateTask(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("cloudtasks.CreateTask: %w", err)
	}

	return createdTask, nil
}

Node.js

// Imports the Google Cloud Tasks library.
const {CloudTasksClient} = require('@google-cloud/tasks');

// Instantiates a client.
const client = new CloudTasksClient();

async function createHttpTaskWithToken() {
  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-queue';
  // const location = 'us-central1';
  // const url = 'https://example.com/taskhandler';
  // const serviceAccountEmail = 'client@<project-id>.iam.gserviceaccount.com';
  // const payload = 'Hello, World!';

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  const task = {
    httpRequest: {
      headers: {
        'Content-Type': 'text/plain', // Set content type to ensure compatibility your application's request parsing
      },
      httpMethod: 'POST',
      url,
      oidcToken: {
        serviceAccountEmail,
      },
    },
  };

  if (payload) {
    task.httpRequest.body = Buffer.from(payload).toString('base64');
  }

  console.log('Sending task:');
  console.log(task);
  // Send create task request.
  const request = {parent: parent, task: task};
  const [response] = await client.createTask(request);
  const name = response.name;
  console.log(`Created task ${name}`);
}
createHttpTaskWithToken();

Ten en cuenta el archivo package.json:

{
  "name": "appengine-cloudtasks",
  "description": "Google App Engine Cloud Tasks example.",
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "private": true,
  "engines": {
    "node": ">=16.0.0"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "c8 mocha -p -j 2 --timeout 30000",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^4.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^8.0.0",
    "chai": "^4.2.0",
    "mocha": "^10.0.0",
    "uuid": "^9.0.0"
  }
}

Proporciona tus propios controladores de tareas de destino HTTP

Los controladores de tareas de destino HTTP son muy similares a los controladores de tareas de App Engine, con las siguientes excepciones:

  • Tiempos de espera: para todos los controladores de tareas HTTP de destino, el tiempo de espera predeterminado es de 10 minutos, con un máximo de 30 minutos.
  • Lógica de autenticación: Si escribes tu propio código en el servicio de destino para validar el token, debes usar un token de ID. Para obtener más información sobre lo que esto implica, consulta OpenID Connect, en particular Valida un token de ID.
  • Encabezados: una solicitud de destino HTTP tiene encabezados establecidos por la cola, que contienen información específica de la tarea que puede usar el controlador. Estos son similares a los encabezados configurados en las solicitudes de tareas de App Engine, pero no son idénticos. Estos encabezados solo proporcionan información. No se deben usar como fuentes de identidad.

    Si estos encabezados estaban presentes en una solicitud de usuario externo a tu app, se reemplazan por los internos. La única excepción es para solicitudes de administradores que hayan accedido a la aplicación y que tengan permitido establecer encabezados con fines de prueba.

    Las solicitudes de destino HTTP siempre contendrán los siguientes encabezados:

    Header Descripción
    X-CloudTasks-QueueName El nombre de la cola.
    X-CloudTasks-TaskName El nombre "breve" de la tarea o (si no se especificó un nombre durante su creación) un ID único generado por el sistema. Este es el valor my-task-id en el nombre completo de la tarea, es decir, task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id.
    X-CloudTasks-TaskRetryCount La cantidad de veces que se reintentó esta tarea. Si es el primer intento, el valor es 0. Este número incluye los intentos en los que la tarea falló debido a códigos de error de 5XX y nunca alcanzó la fase de ejecución.
    X-CloudTasks-TaskExecutionCount La cantidad total de veces que la tarea recibió una respuesta de un controlador. Dado que Cloud Tasks borra la tarea una vez que se recibe una respuesta en la que se indica que se ejecutó correctamente, todas las respuestas anteriores que envió el controlador fueron ejecuciones con errores. Este número no incluye errores debido a los códigos de error 5XX.
    X-CloudTasks-TaskETA La fecha y hora programadas para la tarea, que se especifica en la cantidad de segundos transcurridos desde el 1 de enero de 1970.

    Además, las solicitudes de Cloud Tasks pueden contener los siguientes encabezados:

    Header Descripción
    X-CloudTasks-TaskPreviousResponse El código de respuesta HTTP del reintento anterior.
    X-CloudTasks-TaskRetryReason La razón por la que se volvió a intentar la tarea.

Agrega la función de agente de servicio de Cloud Tasks a tu cuenta de servicio de Cloud Tasks de forma manual

Esto es necesario solo si habilitas la API de Cloud Tasks antes del 19 de marzo de 2019.

Usar Console

  1. Encuentra el número del proyecto en la página de configuración del proyecto de Google Cloud.
  2. Copia el número.
  3. Abre la página de la Consola del administrador de IAM.
  4. Haz clic en Otorgar acceso. Se abrirá la pantalla Otorgar acceso.
  5. En la sección Agregar principales, agrega una dirección de correo electrónico con el siguiente formato:

     service-PROJECT_NUMBER@gcp-sa-cloudtasks.iam.gserviceaccount.com
     

    Reemplaza PROJECT_NUMBER por el número de proyecto que figura arriba.

  6. En la sección Asignar roles, busca y selecciona Agente de servicio de Cloud Tasks.

  7. Haz clic en Guardar.

Usa gcloud

  1. Busca el número de tu proyecto:

        gcloud projects describe PROJECT_ID --format='table(projectNumber)'
        

    Reemplaza PROJECT_ID con el ID del proyecto.

  2. Copia el número.

  3. Otorga la función Cloud Tasks Service Agent a la cuenta de servicio de Cloud Tasks con el número del proyecto que copiaste:

        gcloud projects add-iam-policy-binding PROJECT_ID --member serviceAccount:service-PROJECT_NUMBER@gcp-sa-cloudtasks.iam.gserviceaccount.com --role roles/cloudtasks.serviceAgent
    

    Reemplaza PROJECT_ID por el ID del proyecto y PROJECT_NUMBER por el número de proyecto anterior.

¿Qué sigue?