Désencapsulation de la charge utile pour les abonnements push Pub/Sub

Lors de la création de votre système Pub/Sub, la désencapsulation de la charge utile peut aider vous vous connectez à d'autres systèmes qui ne répondent pas à toutes les exigences système un point de terminaison push Pub/Sub standard.

Voici quelques cas d'utilisation potentiels de la désencapsulation de la charge utile:

  • Vous ne voulez pas écrire de code d'analyse de message spécifique à Pub/Sub pour vos points de terminaison HTTP push.
  • Vous préférez recevoir les métadonnées des messages Pub/Sub sous forme d'en-têtes HTTP. au lieu des métadonnées dans le corps HTTP POST.
  • Vous voulez envoyer des messages Pub/Sub et exclure les métadonnées Pub/Sub, par exemple lors de l'envoi de données une API tierce.

Fonctionnement de la désencapsulation de la charge utile

La désencapsulation de la charge utile est une fonctionnalité qui supprime Pub/Sub messages de toutes les métadonnées des messages, à l'exception de leurs données. En envoyant des données brutes données de message, les abonnés peuvent traiter le message sans avoir à se conformer les exigences système de Pub/Sub.

  • Avec la désencapsulation de la charge utile, les données du message sont transmises directement .
  • Sans désencapsulation de la charge utile, Pub/Sub fournit un objet JSON qui contient plusieurs champs de métadonnées de message et un champ de données de message. Dans ce le JSON doit être analysé pour récupérer les données du message, puis en base64. décodée.

Écrire des métadonnées

Après avoir activé la désencapsulation de la charge utile, vous pouvez utiliser l'option write metadata (écrire les métadonnées). ajoute les métadonnées de message précédemment supprimées dans l'en-tête de la requête.

  • Écriture des métadonnées activée. Ajouter à nouveau les métadonnées du message à la requête en-tête. Fournit également les données brutes et décodées du message.
  • Écriture de métadonnées désactivée. Cela permet de n'envoyer que les données de message brutes décodées.

Les métadonnées d'écriture sont exposées via Pub/Sub, la Google Cloud CLI l'argument --push-no-wrapper-write-metadata et la propriété d'API NoWrapper. Par défaut, cette valeur est nulle.

Avant de commencer

Exemple de messages encapsulés et désencapsulés

Les exemples suivants illustrent la différence entre l'envoi d'une encapsulé et désencapsulé. Dans ces exemples, les données du message contiennent la chaîne {"status": "Hello there"}.

Dans cet exemple, un abonnement est créé avec la fonction fonctionnalité activée et publie un message sur mytopic. Elle utilise une fonction de tri avec la valeur some-key et le type de média est déclaré comme suit : application/json

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

Les sections suivantes montrent la différence entre une valeur encapsulée et une valeur non encapsulée. .

Message encapsulé

L'exemple suivant présente un message encapsulé Pub/Sub standard. Dans dans ce cas, la désencapsulation de la charge utile n'est pas activée.

Publier Réception par le point de terminaison push
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/..."
}

Message désencapsulé avec l'écriture de métadonnées désactivée

L'exemple suivant présente un message désencapsulé avec l'option d'écriture de métadonnées est désactivé. Dans ce cas, les en-têtes x-goog-pubsub-* et les attributs de message ne sont pas incluses.

Publier Réception par le point de terminaison push
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"}

Message désencapsulé avec les métadonnées en écriture activées

L'exemple suivant présente un message désencapsulé avec l'option d'écriture de métadonnées est activé. Dans ce cas, les en-têtes x-goog-pubsub-* et les attributs de message sont incluses.

Publier Réception par le point de terminaison push
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"}

Configurer la désencapsulation de la charge utile

Vous pouvez activer la distribution push de désencapsulation de la charge utile pour un abonnement à l'aide de la page Détails de l'abonnement de la console Google Cloud, de la Google Cloud CLI, ou les bibliothèques clientes.

Console

  1. Dans la console Google Cloud, accédez à la page Abonnements.

    Abonnements Pub/Sub ouverts

  2. Cliquez sur Créer un abonnement.

  3. Dans le champ ID d'abonnement, saisissez un nom.

    Pour savoir comment nommer un abonnement, consultez Consignes pour nommer un sujet ou un abonnement.

  4. Sélectionnez un thème dans le menu déroulant. L'abonnement reçoit des messages du sujet.

  5. Dans Type de distribution, sélectionnez Push.

  6. Pour activer la désencapsulation de la charge utile, sélectionnez Activer la désencapsulation de la charge utile.

  7. (Facultatif) Pour conserver les métadonnées des messages dans l'en-tête de requête, procédez comme suit : sélectionnez Écrire les métadonnées. Vous devez activer cette option pour définir un en-tête Content-Type pour vos messages.

  8. Spécifiez une URL de point de terminaison.

  9. Conservez toutes les autres valeurs par défaut.

  10. Cliquez sur Créer.

gcloud

Pour configurer un abonnement avec une désencapsulation de la charge utile incluant des En-têtes HTTP, exécutez la commande gcloud pubsub subscriptions create suivante :

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

Remplacez les éléments suivants :

  • SUBSCRIPTION: nom ou ID de votre abonnement pull.
  • TOPIC: ID du sujet.
  • PUSH_ENDPOINT: URL à utiliser comme point de terminaison pour cette abonnement. Par exemple, https://myproject.appspot.com/myhandler.
  • --push-no-wrapper: distribue les données du message directement en tant que corps HTTP.

Pour configurer un abonnement avec la désencapsulation de la charge utile et contrôler l'utilisation x-goog-pubsub-*, exécutez la commande suivante:

gcloud pubsub subscriptions create SUBSCRIPTION \
  --topic TOPIC \
  --push-endpoint=PUSH_ENDPOINT \
  --push-no-wrapper \
  --push-no-wrapper-write-metadata
  • --push-no-wrapper-write-metadata: si la valeur est "true", écrit le Métadonnées du message Pub/Sub vers x-goog-pubsub-<KEY>:<VAL> de la requête HTTP. Écrire le message Pub/Sub aux en-têtes <KEY>:<VAL> de la requête HTTP.

Python

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Python qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Python.

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

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Java qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Java.

/*
 * 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++

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage C++ qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour C++.

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

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Go qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Go.

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/pubsub"
)

// createPushNoWrapperSubscription creates a push subscription where messages are delivered in the HTTP body.
func createPushNoWrapperSubscription(w io.Writer, projectID, subID string, topic *pubsub.Topic, endpoint string) error {
	// projectID := "my-project-id"
	// subID := "my-sub"
	// topic of type https://godoc.org/cloud.google.com/go/pubsub#Topic
	// 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()

	sub, err := client.CreateSubscription(ctx, subID, pubsub.SubscriptionConfig{
		Topic:       topic,
		AckDeadline: 10 * time.Second,
		PushConfig: pubsub.PushConfig{
			Endpoint: endpoint,
			Wrapper: &pubsub.NoWrapper{
				// Determines if message metadata is added to the HTTP headers of
				// the delivered message.
				WriteMetadata: true,
			},
		},
	})
	if err != nil {
		return fmt.Errorf("CreateSubscription: %w", err)
	}
	fmt.Fprintf(w, "Created push no wrapper subscription: %v\n", sub)
	return nil
}

Node.js

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Node.js qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Node.js.

/**
 * 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

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Node.js qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Node.js.

/**
 * 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.`);
}

Définir un en-tête de type de contenu dans votre message

Après avoir activé la désencapsulation de la charge utile, Pub/Sub n'effectue pas définir automatiquement un champ d'en-tête de type de média dans votre requête. Si vous ne définissez pas explicitement de champ d'en-tête Content-Type, le serveur Web le traitement de votre demande peut définir la valeur par défaut application/octet-stream ou d'interpréter la requête de manière inattendue.

Si vous avez besoin d'un en-tête Content-Type, veillez à le déclarer explicitement au moment de la publication pour chaque message publié. Pour ce faire, vous devez Activez d'abord l'option Écrire les métadonnées. Ce résultat de l'activation de l'écriture de métadonnées comme indiqué dans les exemples fournis.

Étape suivante