HTTP Target タスクを作成する

このリリースの HTTP Targets では、Cloud Tasks ハンドラを、パブリック IP アドレスを持つ任意の HTTP エンドポイントで実行できるようになりました。このようなエンドポイントには、Cloud FunctionsCloud RunGKECompute Engine や、場合によってはオンプレミスのウェブサーバーなどがあります。こうしたサービスで、信頼性が高く構成が可能な方法でタスクを実行できるようになります。

このページでは、HTTP Target タスクをプログラムによって作成し、Cloud Tasks キューに入れる方法を説明します。

タスクの名前を指定した場合、Cloud Tasks はその名前を使用してタスクの重複排除を行いますが、必要な処理によってレイテンシが増加する場合があります。

一般に、タスクは HTTP リクエストの形式で作成します。次の例のように、クライアント ライブラリサービス アカウントを使用することで、Cloud Tasks サーバーとの通信の詳細を管理でき、タスクの作成が簡単になります。

HTTP Target タスクの作成

HTTP ターゲットを持つタスクの場合、タスクを作成する方法は 2 つあります。

  • BufferTask メソッド: サービスの前にタスクをバッファリングするようにキューが設定されている場合は、このメソッドを使用します。キューにはキューレベルのルーティングが必要です。

  • CreateTask メソッド: より複雑なメソッドです。タスク オブジェクトを明示的に作成する必要があります。この方法は、キュー内のタスクのルーティング構成が異なる場合に使用します。この場合は、タスクレベルでルーティングを指定します。

BufferTask メソッド

制限事項

  • クライアント ライブラリ: BufferTask メソッドは、クライアント ライブラリではサポートされていません。

  • RPC API: BufferTask メソッドは、RPC API ではサポートされていません。

  • キューレベルのルーティング: BufferTask メソッドを使用するには、キューレベルのルーティングを使用する必要があります(そうする以外に、タスクはルーティング情報を持ちません)。キューでキューレベルのルーティングがまだ使用されていない場合は、HTTP タスクのキューレベルのルーティングを構成するをご覧ください。

REST の例

次のコード スニペットは、curl を使用した BufferTask メソッドを使用したタスクの作成例を示しています。

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

次のように置き換えます。

  • HTTP_METHOD: リクエストの HTTP メソッド(例: GETPOST)。
  • PROJECT_ID: Google Cloud プロジェクトの ID。 これを取得するには、ターミナルで次のコマンドを実行します。
    gcloud config get-value project
  • LOCATION: キューのロケーション。
  • QUEUE_ID: キューの ID。

CreateTask メソッド

CreateTask メソッドを使用してタスクを作成するには、タスク オブジェクトを明示的に作成して定義する必要があります。タスクを処理するサービスとハンドラを指定する必要があります。

必要に応じて、タスク固有のデータをハンドラに渡すこともできます。また、タスクが実行されるタイミングのスケジューリングや、タスクが失敗した場合の再試行回数の制限など、タスクの構成を微調整することもできます。

次の例では、CreateTask メソッドを使用して、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,
        )
    )

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());
    }
  }
}

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());

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();

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

Ruby

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

HTTP Target ハンドラの認証のサービス アカウントの設定

Cloud Tasks から HTTP Target ハンドラを呼び出すことができます。このハンドラにアクセスするには認証が必要であり、サービス アカウントに適切な認証情報が設定されている必要があります。

現在使用しているサービス アカウントがある場合は、適切なロールを付与します。ここでは、この機能専用の新しいサービス アカウントを作成する方法について説明します。 Cloud Tasks の認証に使用する既存または新しいサービス アカウントは、Cloud Tasks キューと同じプロジェクトにあることが必要です。

  1. Google Cloud Console で、[サービス アカウント] ページに移動します。

    [サービス アカウント] に移動

  2. 必要に応じて、該当するプロジェクトを選択します。

  3. [サービス アカウントを作成] をクリックします。

  4. [サービス アカウントの詳細] セクションで、アカウントに名前を付けます。コンソールでアカウントに関連するメール アカウント名が作成されます。この名前でアカウントが参照されます。アカウントの説明を追加することもできます。[作成して続行] をクリックします。

  5. [このサービス アカウントにプロジェクトへのアクセスを許可する] セクションで、[ロールを選択] をクリックします。[Cloud Tasks へのデータ追加] を検索して選択します。このロールにより、タスクをキューに追加する権限がサービス アカウントに付与されます。

  6. [+ 別の役割を追加] をクリックします。

  7. [ロールを選択] をクリックします。 [サービス アカウント ユーザー] を検索して選択します。このロールにより、サービス アカウントは、サービスア アカウントの認証情報を使用してキューがトークンを作成することを承認できます。

  8. ハンドラが Google Cloud の一部である場合は、ハンドラが実行されているサービスへのアクセスに関連付けられたロールをサービスア アカウントに付与します。 Google Cloud 内の各サービスには異なるロールが必要です。たとえば、Cloud Run でハンドラにアクセスするには、Cloud Run 起動元のロールが必要です。作成したサービス アカウントまたはプロジェクト内の他のサービス アカウントを使用できます。

  9. [完了] をクリックして、サービス アカウントの作成を完了します。

Cloud Tasks 自体には、Cloud Tasks Service Agent ロールが付与された独自のサービス アカウントが必要です。これは、Cloud Tasks サービス アカウントに関連付けられた認証情報に基づいてヘッダー トークンを生成し、ハンドラ ターゲットで認証できるようにするためです。このロールが付与された Cloud Tasks のサービス アカウントは、Cloud Task API を有効にすると自動的に作成されます。ただし、2019 年 3 月 19 日より前にこの API を有効にしていた場合は、このロールを手動で追加する必要があります。

認証トークンがある HTTP Target タスクの使用

Cloud Tasks とそのような認証が必要な HTTP Target ハンドラの間で認証を行うために、Cloud Tasks はヘッダー トークンを作成します。このトークンは、メールアドレスで識別される Cloud Tasks Enqueuer サービス アカウントの認証情報に基づいて生成されます。認証に使用するサービス アカウントは、Cloud Tasks キューが存在するプロジェクトの一部であることが必要です。リクエストは、ヘッダー トークンとともに HTTPS を介してキューからハンドラに送信されます。ID トークンまたはアクセス トークンのいずれかを使用できます。ID トークンは通常、Google Cloud で実行されているハンドラ(Cloud Functions や Cloud Run など)で使用されます。主な例外は、*.googleapis.com でホストされている Google API で、この API ではアクセス トークンが使用されます。タスク自体で ID(OIDC)トークンまたはアクセス(OAuth)トークンを指定します。

BufferTask メソッド

制限事項

  • クライアント ライブラリ: BufferTask メソッドは、クライアント ライブラリではサポートされていません。

  • RPC API: BufferTask メソッドは、RPC API ではサポートされていません。

  • キューレベルのルーティング: BufferTask メソッドを使用するには、キューレベルのルーティングを使用する必要があります(そうする以外に、タスクはルーティング情報を持ちません)。キューでキューレベルのルーティングがまだ使用されていない場合は、HTTP タスクのキューレベルのルーティングを構成するをご覧ください。

認証を使用した REST の例

BufferTask メソッドを使用してタスクを作成する場合、キューレベルで設定された OIDC 構成または OAuth 構成はタスクレベルの構成をオーバーライドします。キューレベルで認証を構成するには、Cloud Tasks キューを作成するをご覧ください。ただし、タスクの作成時に認証を行うことができます。次の例では、アプリケーションのデフォルト認証情報を使用してタスクの作成時に認証します。

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

以下を置き換えます。

  • HTTP_METHOD: リクエストの HTTP メソッド(例: GETPOST)。
  • PROJECT_ID: Google Cloud プロジェクトの ID。 これを取得するには、ターミナルで次のコマンドを実行します。
    gcloud config get-value project
  • LOCATION: キューのロケーション。
  • QUEUE_ID: キューの ID。
  • ACCESS_TOKEN: 自分のアクセス トークン。これを取得するには、ターミナルで次のコマンドを実行します。
    1. gcloud auth application-default login
    2. gcloud auth application-default print-access-token

CreateTask メソッド

次の例では、Cloud Tasks クライアント ライブラリで CreateTask メソッドを使用して、ヘッダー トークンの作成を含むタスクを作成します。この例では ID トークンが使用されます。 アクセス トークンを使用する場合は、リクエストの作成時に OIDC パラメータを、それぞれの言語に応じて適切な OAuth パラメータに置き換えます。

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,
        )
    )

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());
    }
  }
}

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();

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

独自の HTTP Target タスクハンドラの指定

HTTP Target タスクハンドラは App Engine タスクハンドラとよく似ていますが、次の点が異なります。

  • タイムアウト: HTTP Target タスクハンドラでは、デフォルトのタイムアウトは 10 分、最大は 30 分です。
  • 認証ロジック: 対象とするサービスで独自のコードを作成してトークンを検証する場合は、ID トークンを使用する必要があります。この操作に関する詳細については、OpenID Connect の、特に ID トークンの検証をご覧ください。
  • ヘッダー: HTTP Target リクエストには、ハンドラが使用できるタスク固有の情報が含まれたキューによって、ヘッダーが設定されています。これらは App Engine タスク リクエストに設定されたヘッダーと似ていますが、同じではありません。 これらのヘッダーは情報のみを提供します。これらは ID のソースとして使用しないでください

    アプリに対する外部ユーザー リクエストにこのようなヘッダーが含まれている場合、それらは内部ユーザー リクエストによって置換されます。ただし、ログイン済みのアプリケーション管理者からのリクエストは唯一の例外です。アプリケーション管理者は、テストの目的でこのヘッダーを設定することが許可されています。

    HTTP Target リクエストには、常に次のヘッダーが含まれます。

    ヘッダー 説明
    X-CloudTasks-QueueName キューの名前。
    X-CloudTasks-TaskName タスクの「省略」名。または、作成時に名前が指定されなかった場合は、システムによって生成された一意の ID です。これは、完全なタスク名(task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id)の my-task-id 値になります。
    X-CloudTasks-TaskRetryCount このタスクが再試行された回数。最初の試行の場合は、この値は 0 です。この試行回数には、5XX エラーコードが原因でタスクが異常終了したため実行フェーズに到達できなかった試行も含まれています。
    X-CloudTasks-TaskExecutionCount タスクがハンドラからレスポンスを受け取った合計回数。Cloud Tasks は成功のレスポンスを受け取った時点でタスクを削除するため、それ以前のハンドラからのレスポンスはすべて失敗を意味します。この回数には、5XX エラーコードが原因の失敗は含まれていません。
    X-CloudTasks-TaskETA タスクのスケジュール時間。1970 年 1 月 1 日からの秒数で指定されます。

    さらに、Cloud Tasks からのリクエストには次のヘッダーが含まれる場合もあります。

    ヘッダー 説明
    X-CloudTasks-TaskPreviousResponse 前回の再試行の HTTP レスポンス コード。
    X-CloudTasks-TaskRetryReason タスクを再試行する理由。

Cloud Tasks サービス アカウントに Cloud Tasks サービス エージェントの役割を追加

この操作は、Cloud Tasks API を 2019 年 3 月 19 日より前に有効にした場合のみ必要になります。

コンソールの使用

  1. プロジェクトのプロジェクト番号は、Google Cloud プロジェクトの設定ページで確認できます。
  2. その番号をコピーします。
  3. IAM 管理コンソール ページを開きます。
  4. [アクセス権を付与] をクリックします。 [アクセス権を付与] 画面が開きます。
  5. [プリンシパルを追加] セクションで、次の形式のメールアドレスを追加します。

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

    PROJECT_NUMBER は上記のプロジェクト番号に置き換えます。

  6. [ロールの割り当て] セクションで、[Cloud Tasks サービス エージェント] を検索して選択します。

  7. [保存] をクリックします。

gcloud の使用

  1. プロジェクト番号を確認します。

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

    PROJECT_ID は、実際のプロジェクト ID に置き換えます。

  2. その番号をコピーします。

  3. コピーしたプロジェクト番号を使用して、Cloud Tasks サービス アカウントに Cloud Tasks Service Agent の役割を付与します。

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

    PROJECT_ID はプロジェクト ID に置き換え、PROJECT_NUMBER は上記のプロジェクト番号に置き換えます。

次のステップ