Membuka payload untuk langganan push Pub/Sub

Saat membangun sistem Pub/Sub, pembukaan payload dapat membantu Anda terhubung ke sistem lain yang tidak mematuhi semua persyaratan sistem penerapan endpoint push Pub/Sub standar.

Berikut adalah beberapa potensi kasus penggunaan untuk membuka payload:

  • Anda tidak ingin menulis kode parsing pesan khusus Pub/Sub untuk endpoint push HTTP.
  • Anda lebih memilih menerima metadata pesan Pub/Sub sebagai header HTTP, bukan metadata di isi HTTP POST.
  • Anda ingin mengirim pesan Pub/Sub dan mengecualikan metadata Pub/Sub, misalnya saat mengirim data ke API pihak ketiga.

Cara kerja pembukaan payload

Pembukaan payload adalah fitur yang menghapus semua metadata pesan Pub/Sub, kecuali data pesan. Dengan mengirim data pesan mentah, pelanggan dapat memproses pesan tanpa harus mematuhi persyaratan sistem Pub/Sub.

  • Dengan pembukaan payload, data pesan dikirim langsung sebagai isi HTTP.
  • Tanpa pembukaan payload, Pub/Sub mengirimkan objek JSON yang berisi beberapa kolom metadata pesan dan kolom data pesan. Dalam kasus ini, JSON harus diurai untuk mengambil data pesan, lalu didekode base64.

Menulis metadata

Setelah mengaktifkan pembukaan payload, Anda dapat menggunakan opsi tulis metadata yang menambahkan metadata pesan yang sebelumnya dihapus ke header permintaan.

  • Tulis metadata diaktifkan. Tambahkan metadata pesan kembali ke header permintaan. Juga mengirimkan data pesan mentah yang telah didekode.
  • Penulisan metadata dinonaktifkan. Hanya mengirimkan data pesan mentah yang telah didekode.

Metadata penulisan diekspos melalui Pub/Sub, argumen --push-no-wrapper-write-metadata Google Cloud CLI, dan properti API NoWrapper. Secara default, nilai ini adalah null.

Sebelum memulai

Contoh untuk pesan yang dienkapsulasi dan tidak dienkapsulasi

Contoh berikut menggambarkan perbedaan antara mengirim pesan HTTP yang dienkapsulasi dan tidak dienkapsulasi. Dalam contoh ini, data pesan berisi string {"status": "Hello there"}.

Untuk contoh ini, langganan dibuat dengan fitur pembukaan payload yang diaktifkan dan memublikasikan pesan ke mytopic. Objek ini menggunakan kunci pengurutan dengan nilai some-key dan jenis media dideklarasikan sebagai application/json.

gcloud pubsub topics publish mytopic
   --message='{"status": "Hello there"}'
   --ordering-key="some-key"
   --attribute "Content-Type=application/json"

Bagian berikut menunjukkan perbedaan antara pesan yang di-wrap dan tidak di-wrap.

Pesan yang dibungkus

Contoh berikut menunjukkan pesan standar yang di-wrap Pub/Sub. Dalam hal ini, pembukaan payload tidak diaktifkan.

Publikasikan Endpoint Push Menerima
data="{"status": "Hello there"}"
ordering_key="some-key"
attributes=
  {
     {"Content-Type", "application/json"}
  }
Content-Length: 361
Content-Type: application/json
User-Agent: CloudPubSub-Google
Host: subscription-project.uc.r.appspot.com

{
  "message": {
      "attributes": {
          "Content-Type": "application/json"
      },
      "data": "eyJzdGF0dXMiOiAiSGVsbG8gdGhlcmUifQ==", //  Base64 - {"status": "Hello there"}
      "messageId": "2070443601311540",
      "message_id": "2070443601311540",
      "publishTime": "2021-02-26T19:13:55.749Z",
      "publish_time": "2021-02-26T19:13:55.749Z"
  },
  "subscription": "projects/myproject/..."
}

Pesan yang tidak di-unwrap dengan penulisan metadata dinonaktifkan

Contoh berikut menampilkan pesan yang tidak di-unwrapping dengan opsi tulis metadata dinonaktifkan. Dalam hal ini, header x-goog-pubsub-* dan atribut pesan tidak disertakan.

Publikasikan Endpoint Push Menerima
data="{"status": "Hello there"}"
ordering_key="some-key"
attributes=
  {
     {"Content-Type", "application/json"}
  }
Content-Length: 25
User-Agent: CloudPubSub-Google
Host: subscription-project.uc.r.appspot.com

{"status": "Hello there"}

Pesan yang tidak di-unwrap dengan metadata penulisan diaktifkan

Contoh berikut menampilkan pesan yang tidak di-unwrap dengan opsi tulis metadata diaktifkan. Dalam hal ini, atribut pesan dan header x-goog-pubsub-* disertakan.

Publikasikan Endpoint Push Menerima
data="{"status": "Hello there"}"
ordering_key="some-key"
attributes=
  {
     {"Content-Type", "application/json"}
  }
x-goog-pubsub-subscription-name: "projects/myproject/..."
x-goog-pubsub-message-id: "2070443601311540"
x-goog-pubsub-publish-time: "2021-02-26T19:13:55.749Z"
x-goog-pubsub-ordering-key: "some-key"
Content-Type: application/json
Content-Length: 12
User-Agent: CloudPubSub-Google
Host: subscription-project.uc.r.appspot.com

{"status": "Hello there"}

Mengonfigurasi pembukaan payload

Anda dapat mengaktifkan pengiriman push pembukaan payload untuk langganan menggunakan halaman Trusted Cloud konsol Detail Langganan, Google Cloud CLI, atau Library Klien.

Konsol

  1. Di konsol Trusted Cloud , buka halaman Subscriptions.

    Membuka langganan Pub/Sub

  2. Klik Buat langganan.

  3. Di kolom Subscription ID, masukkan nama.

    Untuk mengetahui informasi tentang cara memberi nama langganan, lihat Panduan untuk memberi nama topik atau langganan.

  4. Pilih topik dari menu drop-down. Langganan menerima pesan dari topik.

  5. Untuk Jenis pengiriman, pilih Push.

  6. Untuk mengaktifkan pembukaan payload, pilih Aktifkan pembukaan payload.

  7. (Opsional) Untuk mempertahankan metadata pesan di header permintaan, pilih Tulis metadata. Anda harus mengaktifkan opsi ini untuk menetapkan header Content-Type untuk pesan Anda.

  8. Tentukan URL endpoint.

  9. Pertahankan semua nilai default lainnya.

  10. Klik Buat.

gcloud

Untuk mengonfigurasi langganan dengan pembukaan payload yang mencakup header HTTP standar, jalankan perintah gcloud pubsub subscriptions create berikut:

gcloud pubsub subscriptions create SUBSCRIPTION \
  --topic TOPIC \
  --push-endpoint=PUSH_ENDPOINT \
  --push-no-wrapper

Ganti kode berikut:

  • SUBSCRIPTION: nama atau ID langganan pull Anda.
  • TOPIC: ID topik.
  • PUSH_ENDPOINT: URL yang akan digunakan sebagai endpoint untuk langganan ini. Misalnya, https://myproject.appspot.com/myhandler
  • --push-no-wrapper: mengirimkan data pesan secara langsung sebagai isi HTTP.

Untuk mengonfigurasi langganan dengan pembukaan payload dan mengontrol penggunaan header x-goog-pubsub-*, jalankan perintah berikut:

gcloud pubsub subscriptions create SUBSCRIPTION \
  --topic TOPIC \
  --push-endpoint=PUSH_ENDPOINT \
  --push-no-wrapper \
  --push-no-wrapper-write-metadata
  • --push-no-wrapper-write-metadata: Jika benar (true), menulis metadata pesan Pub/Sub ke header x-goog-pubsub-<KEY>:<VAL> permintaan HTTP. Menulis atribut pesan Pub/Sub ke header <KEY>:<VAL> permintaan HTTP.

Python

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Python di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi Pub/Sub Python API.

from google.cloud import pubsub_v1

# TODO(developer)
# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"
# endpoint = "https://my-test-project.appspot.com/push"

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic_path = publisher.topic_path(project_id, topic_id)
subscription_path = subscriber.subscription_path(project_id, subscription_id)

no_wrapper = pubsub_v1.types.PushConfig.NoWrapper(write_metadata=True)
push_config = pubsub_v1.types.PushConfig(
    push_endpoint=endpoint, no_wrapper=no_wrapper
)

# Wrap the subscriber in a 'with' block to automatically call close() to
# close the underlying gRPC channel when done.
with subscriber:
    subscription = subscriber.create_subscription(
        request={
            "name": subscription_path,
            "topic": topic_path,
            "push_config": push_config,
        }
    )

print(f"Push no wrapper subscription created: {subscription}.")
print(f"Endpoint for subscription is: {endpoint}")
print(f"No wrapper configuration for subscription is: {no_wrapper}")

Java

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Java di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi Pub/Sub Java API.

/*
 * Copyright 2016 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package pubsub;


import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
import com.google.pubsub.v1.PushConfig;
import com.google.pubsub.v1.PushConfig.NoWrapper;
import com.google.pubsub.v1.Subscription;
import com.google.pubsub.v1.SubscriptionName;
import com.google.pubsub.v1.TopicName;
import java.io.IOException;

public class CreateUnwrappedPushSubscriptionExample {
  public static void main(String... args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String subscriptionId = "your-subscription-id";
    String topicId = "your-topic-id";
    String pushEndpoint = "https://my-test-project.appspot.com/push";

    createPushSubscriptionExample(projectId, subscriptionId, topicId, pushEndpoint);
  }

  public static void createPushSubscriptionExample(
      String projectId, String subscriptionId, String topicId, String pushEndpoint)
      throws IOException {
    try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
      TopicName topicName = TopicName.of(projectId, topicId);
      SubscriptionName subscriptionName = SubscriptionName.of(projectId, subscriptionId);
      NoWrapper noWrapper =
          NoWrapper.newBuilder()
              // Determines if message metadata is added to the HTTP headers of
              // the delivered message.
              .setWriteMetadata(true)
              .build();
      PushConfig pushConfig =
          PushConfig.newBuilder().setPushEndpoint(pushEndpoint).setNoWrapper(noWrapper).build();

      // Create a push subscription with default acknowledgement deadline of 10 seconds.
      // Messages not successfully acknowledged within 10 seconds will get resent by the server.
      Subscription subscription =
          subscriptionAdminClient.createSubscription(subscriptionName, topicName, pushConfig, 10);
      System.out.println("Created push subscription: " + subscription.getName());
    }
  }
}

C++

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan C++ di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi Pub/Sub C++ API.

namespace pubsub = ::google::cloud::pubsub;
namespace pubsub_admin = ::google::cloud::pubsub_admin;
[](pubsub_admin::SubscriptionAdminClient client,
   std::string const& project_id, std::string const& topic_id,
   std::string const& subscription_id, std::string const& endpoint) {
  google::pubsub::v1::Subscription request;
  request.set_name(
      pubsub::Subscription(project_id, subscription_id).FullName());
  request.set_topic(pubsub::Topic(project_id, topic_id).FullName());
  request.mutable_push_config()->set_push_endpoint(endpoint);
  request.mutable_push_config()->mutable_no_wrapper()->set_write_metadata(
      true);
  auto sub = client.CreateSubscription(request);
  if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {
    std::cout << "The subscription already exists\n";
    return;
  }
  if (!sub) throw std::move(sub).status();

  std::cout << "The subscription was successfully created: "
            << sub->DebugString() << "\n";
}

Go

Contoh berikut menggunakan library klien Go Pub/Sub versi utama (v2). Jika Anda masih menggunakan library v1, lihat panduan migrasi ke v2. Untuk melihat daftar contoh kode v1, lihat contoh kode yang tidak digunakan lagi.

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Go di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi Pub/Sub Go API.

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub/v2"
	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)

// createPushNoWrapperSubscription creates a push subscription where messages are delivered in the HTTP body.
func createPushNoWrapperSubscription(w io.Writer, projectID, topic, subscription, endpoint string) error {
	// projectID := "my-project-id"
	// topic := "projects/my-project-id/topics/my-topic"
	// subscription := "projects/my-project/subscriptions/my-sub"
	// endpoint := "https://my-test-project.appspot.com/push"
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %w", err)
	}
	defer client.Close()
	pbSubscription := &pubsubpb.Subscription{
		Name:               subscription,
		Topic:              topic,
		AckDeadlineSeconds: 10,
		PushConfig: &pubsubpb.PushConfig{
			PushEndpoint: endpoint,
			Wrapper: &pubsubpb.PushConfig_NoWrapper_{
				NoWrapper: &pubsubpb.PushConfig_NoWrapper{
					// Determines if message metadata is added to the HTTP headers of
					// the delivered message.
					WriteMetadata: true,
				},
			},
		},
	}
	sub, err := client.SubscriptionAdminClient.CreateSubscription(ctx, pbSubscription)
	if err != nil {
		return fmt.Errorf("CreateSubscription: %w", err)
	}
	fmt.Fprintf(w, "Created push no wrapper subscription: %v\n", sub)
	return nil
}

Node.js

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Node.js di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API Node.js Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const pushEndpoint = 'YOUR_ENDPOINT_URL';
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createPushSubscriptionNoWrapper(
  pushEndpoint,
  topicNameOrId,
  subscriptionNameOrId,
) {
  const options = {
    pushConfig: {
      // Set to an HTTPS endpoint of your choice. If necessary, register
      // (authorize) the domain on which the server is hosted.
      pushEndpoint,
      // When true, writes the Pub/Sub message metadata to
      // `x-goog-pubsub-<KEY>:<VAL>` headers of the HTTP request. Writes the
      // Pub/Sub message attributes to `<KEY>:<VAL>` headers of the HTTP request.
      noWrapper: {
        writeMetadata: true,
      },
    },
  };

  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, options);
  console.log(`Subscription ${subscriptionNameOrId} created.`);
}

Node.js

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Node.js di Panduan memulai: Menggunakan Library Klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API Node.js Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const pushEndpoint = 'YOUR_ENDPOINT_URL';
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
import {PubSub, CreateSubscriptionOptions} from '@google-cloud/pubsub';

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createPushSubscriptionNoWrapper(
  pushEndpoint: string,
  topicNameOrId: string,
  subscriptionNameOrId: string,
) {
  const options: CreateSubscriptionOptions = {
    pushConfig: {
      // Set to an HTTPS endpoint of your choice. If necessary, register
      // (authorize) the domain on which the server is hosted.
      pushEndpoint,
      // When true, writes the Pub/Sub message metadata to
      // `x-goog-pubsub-<KEY>:<VAL>` headers of the HTTP request. Writes the
      // Pub/Sub message attributes to `<KEY>:<VAL>` headers of the HTTP request.
      noWrapper: {
        writeMetadata: true,
      },
    },
  };

  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, options);
  console.log(`Subscription ${subscriptionNameOrId} created.`);
}

Menetapkan header content-type dalam pesan Anda

Setelah mengaktifkan pembukaan payload, Pub/Sub tidak otomatis menetapkan kolom header jenis media dalam permintaan Anda. Jika Anda tidak menetapkan kolom header Content-Type secara eksplisit, server web yang memproses permintaan Anda dapat menetapkan nilai default application/octet-stream atau menafsirkan permintaan dengan cara yang tidak terduga.

Jika Anda memerlukan header Content-Type, pastikan Anda mendeklarasikannya secara eksplisit pada saat publikasi untuk setiap pesan yang dipublikasikan. Untuk melakukannya, Anda harus mengaktifkan Tulis metadata terlebih dahulu. Hasil pengaktifan Tulis metadata ini ditampilkan dalam contoh yang diberikan.

Langkah berikutnya