Annullamento del wrapping del payload per le sottoscrizioni push di Pub/Sub

Quando crei il tuo sistema Pub/Sub, l'unwrapping del payload può aiutarti ti colleghi ad altri sistemi che non rispettano tutti i requisiti di sistema di una l'implementazione standard dell'endpoint push di Pub/Sub.

Di seguito sono riportati alcuni casi d'uso potenziali per l'annullamento del wrapping del payload:

  • Non è consigliabile scrivere codice per l'analisi dei messaggi specifico per Pub/Sub per gli endpoint push HTTP.
  • Preferisci ricevere i metadati dei messaggi Pub/Sub come intestazioni HTTP invece dei metadati nel corpo HTTP POST.
  • Vuoi inviare messaggi Pub/Sub ed escludere i metadati Pub/Sub, ad esempio durante l'invio di dati a un tramite un'API di terze parti.

Come funziona l'annullamento del wrapping del payload

L'annullamento del wrapping del payload è una funzionalità che rimuove Pub/Sub messaggi di tutti i metadati dei messaggi, ad eccezione dei dati dei messaggi. Inviando i file non elaborati i dati dei messaggi, i sottoscrittori possono elaborarli senza dover a qualsiasi requisito di sistema di Pub/Sub.

  • Con l'annullamento del wrapping del payload, i dati dei messaggi vengono consegnati direttamente come HTTP del testo.
  • Senza l'annullamento del wrapping del payload, Pub/Sub fornisce un oggetto JSON che contiene più campi di metadati dei messaggi e un campo per i dati dei messaggi. In questo case, il codice JSON deve essere analizzato per recuperare i dati del messaggio e quindi in base64 decodificato.

Scrivi metadati

Dopo aver abilitato l'annullamento del wrapping del payload, puoi utilizzare l'opzione write metadata, che aggiunge i metadati del messaggio rimossi in precedenza nell'intestazione della richiesta.

  • Scrittura metadati abilitata. Aggiungi di nuovo i metadati del messaggio alla richiesta intestazione. Fornisce anche i dati dei messaggi non elaborati e decodificati.
  • Scrittura metadati disabilitata. Invia solo i dati dei messaggi non elaborati e decodificati.

I metadati di scrittura vengono esposti tramite Pub/Sub, Google Cloud CLI l'argomento --push-no-wrapper-write-metadata e la proprietà API NoWrapper. Per impostazione predefinita, questo valore è nullo.

Prima di iniziare

Esempio di messaggi con wrapping e unwrapping

I seguenti esempi illustrano la differenza tra l'invio di un messaggio HTTP con wrapping e unwrapping. In questi esempi, i dati dei messaggi contengono la stringa {"status": "Hello there"}.

Per questo esempio, viene creata una sottoscrizione con l'annullamento del wrapping del payload attivata e pubblica un messaggio su mytopic. Utilizza un sistema di ordinamento chiave con valore some-key e il tipo di media è dichiarato come application/json.

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

Le seguenti sezioni mostrano la differenza tra un wrapping e un senza wrapper per creare un nuovo messaggio email.

Messaggio con wrapping

L'esempio seguente mostra un messaggio con wrapping Pub/Sub standard. Nel In questo caso, l'unwrapping del payload non è abilitato.

Pubblica Ricezione endpoint 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/..."
}

Messaggio con wrapping con metadati di scrittura disabilitati

L'esempio seguente mostra un messaggio senza wrapping con l'opzione Scrivi metadati disattivata. In questo caso, le intestazioni x-goog-pubsub-* e gli attributi del messaggio non sono incluse.

Pubblica Ricezione endpoint 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"}

Messaggio con wrapping con metadati di scrittura abilitati

L'esempio seguente mostra un messaggio senza wrapping con l'opzione Scrivi metadati in un bucket in cui è abilitato il controllo delle versioni. In questo caso, le intestazioni x-goog-pubsub-* e gli attributi del messaggio sono inclusi.

Pubblica Ricezione endpoint 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"}

Configura l'annullamento del wrapping del payload

Puoi abilitare la consegna push dell'annullamento del wrapping del payload per una sottoscrizione utilizzando la pagina Dettagli abbonamento della console Google Cloud, Google Cloud CLI o le librerie client.

Console

  1. Nella console Google Cloud, vai alla pagina Abbonamenti.

    Aprire le sottoscrizioni Pub/Sub

  2. Fai clic su Crea sottoscrizione.

  3. Nel campo ID abbonamento, inserisci un nome.

    Per informazioni su come assegnare un nome a una sottoscrizione, vedi Linee guida per assegnare un nome a un argomento o a una sottoscrizione.

  4. Seleziona un argomento dal menu a discesa. La sottoscrizione riceve messaggi dall'argomento.

  5. Per Tipo di pubblicazione, seleziona Push.

  6. Per attivare l'annullamento del wrapping del payload, seleziona Abilita l'annullamento del wrapping del payload.

  7. (Facoltativo) Per conservare i metadati dei messaggi nell'intestazione della richiesta: Seleziona Scrivi metadati. Devi attivare questa opzione per impostare un'intestazione Content-Type. per i tuoi messaggi.

  8. Specifica l'URL di un endpoint.

  9. Conserva tutti gli altri valori predefiniti.

  10. Fai clic su Crea.

gcloud

Per configurare una sottoscrizione con l'annullamento del wrapping del payload che include il Intestazioni HTTP, esegui questo comando gcloud pubsub subscriptions create :

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

Sostituisci quanto segue:

  • SUBSCRIPTION: il nome o l'ID della tua sottoscrizione pull.
  • TOPIC: l'ID dell'argomento.
  • PUSH_ENDPOINT: l'URL da utilizzare come endpoint abbonamento. Ad esempio, https://myproject.appspot.com/myhandler
  • --push-no-wrapper: consegna i dati del messaggio direttamente come corpo HTTP.

per configurare una sottoscrizione con l'annullamento del wrapping del payload e controllare l'uso del x-goog-pubsub-*, esegui questo comando:

gcloud pubsub subscriptions create SUBSCRIPTION \
  --topic TOPIC \
  --push-endpoint=PUSH_ENDPOINT \
  --push-no-wrapper \
  --push-no-wrapper-write-metadata
  • --push-no-wrapper-write-metadata: se true, scrive il parametro Metadati dei messaggi Pub/Sub in x-goog-pubsub-<KEY>:<VAL> intestazioni della richiesta HTTP. Scrive il messaggio Pub/Sub alle intestazioni <KEY>:<VAL> della richiesta HTTP.

Python

Prima di provare questo esempio, segui le istruzioni di configurazione di Python in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Python Pub/Sub.

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

Prima di provare questo esempio, segui le istruzioni di configurazione di Java in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Java Pub/Sub.

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

Prima di provare questo esempio, segui le istruzioni per la configurazione di C++ in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Pub/Sub 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";
}

Vai

Prima di provare questo esempio, segui le istruzioni di configurazione di Go in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Pub/Sub 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js in Guida rapida all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'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.`);
}

Imposta un'intestazione per tipo di contenuti nel messaggio

Dopo aver abilitato l'annullamento del wrapping del payload, Pub/Sub non Impostare automaticamente un campo di intestazione per un tipo di media nella richiesta. Se non impostare esplicitamente un campo intestazione Content-Type, il server web durante l'elaborazione della richiesta potrebbe essere impostato un valore predefinito application/octet-stream o interpretarla in modo imprevisto.

Se hai bisogno di un'intestazione Content-Type, assicurati di dichiararla esplicitamente al momento della pubblicazione di ogni singolo messaggio pubblicato. Per farlo, devi abilita Scrivi metadati. Questo risultato dell'abilitazione di Scrivi metadati è mostrato negli esempi forniti.

Passaggi successivi