Scrittura e risposta a messaggi Pub/Sub

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Non corrisponde a un paese o a una provincia, anche se alcuni ID regione possono apparire simili ai codici di paese e provincia di uso comune. Per le app create dopo febbraio 2020, REGION_ID.r è incluso negli URL di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.

Scopri di più sugli ID regione.

Pub/Sub fornisce messaggi asincroni affidabili, many-to-many, tra le applicazioni. Le applicazioni del publisher possono inviare messaggi a un argomento, mentre le altre applicazioni possono sottoscrivere quell'argomento per ricevere i messaggi.

Questo documento descrive come utilizzare la libreria client Cloud per inviare e ricevere messaggi Pub/Sub in un'app App Engine.

Prerequisiti

Clonazione dell'app di esempio

Copia le app di esempio nella tua macchina locale e vai alla directory pubsub:

Go

1.18 e versioni successive

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git
    cd golang-samples/appengine_flexible/pubsub

v1.15 e precedenti

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git
    cd golang-samples/appengine_flexible/go115_and_earlier/pubsub

Java

versione 11/17

git clone https://github.com/GoogleCloudPlatform/java-docs-samples
cd java-docs-samples/flexible/java-11/pubsub/

versione 8

git clone https://github.com/GoogleCloudPlatform/java-docs-samples
cd java-docs-samples/flexible/java-8/pubsub/

Node.js

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples
cd nodejs-docs-samples/appengine/pubsub

PHP

git clone https://github.com/GoogleCloudPlatform/php-docs-samples.git
cd php-docs-samples/pubsub

Python

3.8 e versioni successive

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/appengine/flexible/pubsub

3.7 e versioni precedenti

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/appengine/flexible_python37_and_earlier/pubsub

Ruby

Versione 3.2

git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
cd ruby-docs-samples/appengine/flexible/pubsub/

versione 3.1 e precedenti

git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
cd ruby-docs-samples/appengine/flexible/ruby31-and-earlier/pubsub/

.NET

versione 6

git clone  https://github.com/GoogleCloudPlatform/dotnet-docs-samples
cd dotnet-docs-samples/appengine/flexible/Pubsub/Pubsub.Sample

versione 3.1 e precedenti

git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples
git checkout flex-dotnet3-and-earlier
cd dotnet-docs-samples/appengine/flexible/Pubsub

Crea un argomento e una sottoscrizione

Crea un argomento e una sottoscrizione, che includa la specifica dell'endpoint a cui il server Pub/Sub deve inviare le richieste:

Go

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

Java

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

Node.js

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

PHP

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

Python

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

Ruby

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

.NET

# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Sostituisci YOUR_TOKEN con un token casuale del secret. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un'altra sottoscrizione:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'

Sostituisci YOUR-SERVICE-ACCOUNT-EMAIL con l'indirizzo email del tuo account di servizio.

Imposta le variabili di ambiente

Go

Modifica il file app.yaml per impostare le variabili di ambiente per l'argomento e il token di verifica:

env_variables:
  PUBSUB_TOPIC: your-topic
  # This token is used to verify that requests originate from your
  # application. It can be any sufficiently random string.
  PUBSUB_VERIFICATION_TOKEN: your-token

Java

Modifica il file app.yaml per impostare le variabili di ambiente per l'argomento e il token di verifica:

env_variables:
  PUBSUB_TOPIC: <your-topic-name>
  # This token is used to verify that requests originate from your
  # application. It can be any sufficiently random string.
  PUBSUB_VERIFICATION_TOKEN: <your-verification-token>

Node.js

Modifica il file app.yaml per impostare le variabili di ambiente per l'argomento e il token di verifica:

env_variables:
  PUBSUB_TOPIC: YOUR_TOPIC_NAME
  # This token is used to verify that requests originate from your
  # application. It can be any sufficiently random string.
  PUBSUB_VERIFICATION_TOKEN: YOUR_VERIFICATION_TOKEN

PHP

Modifica il file index.php per impostare le variabili di ambiente per l'argomento e la sottoscrizione:

$container->set('topic', 'php-example-topic');
$container->set('subscription', 'php-example-subscription');

Python

Modifica il file app.yaml per impostare le variabili di ambiente per l'ID progetto, l'argomento e il token di verifica:

env_variables:
    PUBSUB_TOPIC: your-topic
    # This token is used to verify that requests originate from your
    # application. It can be any sufficiently random string.
    PUBSUB_VERIFICATION_TOKEN: 1234abc

Ruby

Modifica il file app.yaml per impostare le variabili di ambiente per l'ID progetto, l'argomento e il token di verifica:

env_variables:
    PUBSUB_TOPIC: <pubsub-topic-name>
    # This token is used to verify that requests originate from your
    # application. It can be any sufficiently random string.
    PUBSUB_VERIFICATION_TOKEN: <verification-token>

.NET

versione 6

Modifica il file app.yaml per impostare le variabili di ambiente per l'argomento e il token di verifica:

runtime: aspnetcore
env: flex

runtime_config:
  operating_system: ubuntu22

env_variables:
  TEST_PROJECT_ID: your-project-id
  TEST_VERIFICATION_TOKEN: your-token
  TEST_TOPIC_ID: your-topic
  TEST_SUBSCRIPTION_ID: your-sub
  TEST_AUTH_SUBSCRIPTION_ID: your-auth-sub
  TEST_SERVICE_ACCOUNT_EMAIL: your-service-account-email

versione 3.1 e precedenti

Modifica il file appsettings.json per impostare l'ID progetto:

{
  "Pubsub": {
    "ProjectId": "your-project-id",
    "VerificationToken": "your-secret-token",
    "TopicId": "your-topic",
    "SubscriptionId": "your-subscription",
    "AuthSubscriptionId": "your-auth-subscription",
    "ServiceAccountEmail": "your-service-account-email"
  },

  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Revisione del codice

L'app di esempio utilizza la libreria client di Pub/Sub.

Go

L'app di esempio utilizza le variabili di ambiente impostate nel file app.yaml (PUBSUB_TOPIC e PUBSUB_VERIFICATION_TOKEN) per la configurazione.

I messaggi ricevuti da questa istanza vengono archiviati in una sezione:

messages   []string

La funzione pushHandler riceve i messaggi di cui viene eseguito il push, verifica il token e lo aggiunge alla sezione messages:


func pushHandler(w http.ResponseWriter, r *http.Request) {
	// Verify the token.
	if r.URL.Query().Get("token") != token {
		http.Error(w, "Bad token", http.StatusBadRequest)
		return
	}
	msg := &pushRequest{}
	if err := json.NewDecoder(r.Body).Decode(msg); err != nil {
		http.Error(w, fmt.Sprintf("Could not decode body: %v", err), http.StatusBadRequest)
		return
	}

	messagesMu.Lock()
	defer messagesMu.Unlock()
	// Limit to ten.
	messages = append(messages, string(msg.Message.Data))
	if len(messages) > maxMessages {
		messages = messages[len(messages)-maxMessages:]
	}
}

La funzione publishHandler pubblica nuovi messaggi nell'argomento.


func publishHandler(w http.ResponseWriter, r *http.Request) {
	ctx := context.Background()

	msg := &pubsub.Message{
		Data: []byte(r.FormValue("payload")),
	}

	if _, err := topic.Publish(ctx, msg).Get(ctx); err != nil {
		http.Error(w, fmt.Sprintf("Could not publish message: %v", err), 500)
		return
	}

	fmt.Fprint(w, "Message published.")
}

Java

L'app di esempio utilizza i valori impostati nel file app.yaml per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta provenga da Pub/Sub e da una fonte attendibile:

String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN");

L'app di esempio gestisce un'istanza di database Cloud Datastore per archiviare i messaggi. Il servlet PubSubPush riceve i messaggi inviati tramite push e li aggiunge all'istanza del database messageRepository:

versione 11/17

@WebServlet(value = "/pubsub/push")
@MultipartConfig()
public class PubSubPush extends HttpServlet {

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN");
    // Do not process message if request token does not match pubsubVerificationToken
    if (pubsubVerificationToken == null
        || pubsubVerificationToken.compareTo(req.getParameter("token")) != 0) {
      resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }
    // parse message object from "message" field in the request body json
    // decode message data from base64
    Message message = getMessage(req);
    try {
      messageRepository.save(message);
      // 200, 201, 204, 102 status codes are interpreted as success by the Pub/Sub system
      resp.setStatus(HttpServletResponse.SC_OK);
    } catch (Exception e) {
      System.out.println(e);
      resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
  }

versione 8

@WebServlet(value = "/pubsub/push")
public class PubSubPush extends HttpServlet {

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN");
    // Do not process message if request token does not match pubsubVerificationToken
    if (req.getParameter("token").compareTo(pubsubVerificationToken) != 0) {
      resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }
    // parse message object from "message" field in the request body json
    // decode message data from base64
    Message message = getMessage(req);
    try {
      messageRepository.save(message);
      // 200, 201, 204, 102 status codes are interpreted as success by the Pub/Sub system
      resp.setStatus(HttpServletResponse.SC_OK);
    } catch (Exception e) {
      resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
  }

Il servlet PubSubPublish interagisce con l'app web App Engine per pubblicare nuovi messaggi e visualizzare i messaggi ricevuti:

@WebServlet(name = "Publish with PubSub", value = "/pubsub/publish")
public class PubSubPublish extends HttpServlet {

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    Publisher publisher = this.publisher;
    try {
      String topicId = System.getenv("PUBSUB_TOPIC");
      // create a publisher on the topic
      if (publisher == null) {
        publisher = Publisher.newBuilder(
            ProjectTopicName.of(ServiceOptions.getDefaultProjectId(), topicId))
            .build();
      }
      // construct a pubsub message from the payload
      final String payload = req.getParameter("payload");
      PubsubMessage pubsubMessage =
          PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8(payload)).build();

      publisher.publish(pubsubMessage);
      // redirect to home page
      resp.sendRedirect("/");
    } catch (Exception e) {
      resp.sendError(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
    }
  }

Node.js

L'app di esempio utilizza i valori impostati nel file app.yaml per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta provenga da Pub/Sub e da una fonte attendibile:

// The following environment variables are set by the `app.yaml` file when
// running on App Engine, but will need to be manually set when running locally.
var PUBSUB_VERIFICATION_TOKEN = process.env.PUBSUB_VERIFICATION_TOKEN;
var pubsub = gcloud.pubsub({
    projectId: process.env.GOOGLE_CLOUD_PROJECT
});
var topic = pubsub.topic(process.env.PUBSUB_TOPIC);

L'app di esempio gestisce un elenco globale per archiviare i messaggi ricevuti da questa istanza:

// List of all messages received by this instance
var messages = [];

Questo metodo riceve i messaggi di cui viene eseguito il push e li aggiunge all'elenco globale messages:

app.post('/pubsub/push', jsonBodyParser, (req, res) => {
  if (req.query.token !== PUBSUB_VERIFICATION_TOKEN) {
    res.status(400).send();
    return;
  }

  // The message is a unicode string encoded in base64.
  const message = Buffer.from(req.body.message.data, 'base64').toString(
    'utf-8'
  );

  messages.push(message);

  res.status(200).send();
});

Questo metodo interagisce con l'app web App Engine per pubblicare i nuovi messaggi e visualizzare i messaggi ricevuti:

app.get('/', (req, res) => {
  res.render('index', {messages, tokens, claims});
});

app.post('/', formBodyParser, async (req, res, next) => {
  if (!req.body.payload) {
    res.status(400).send('Missing payload');
    return;
  }

  const data = Buffer.from(req.body.payload);
  try {
    const messageId = await topic.publishMessage({data});
    res.status(200).send(`Message ${messageId} sent.`);
  } catch (error) {
    next(error);
  }
});

PHP

L'app di esempio utilizza i valori impostati nel file app.yaml per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta provenga da Pub/Sub e da un'origine attendibile:

runtime: php
env: flex

L'app di esempio gestisce un elenco globale per archiviare i messaggi ricevuti da questa istanza:

$messages = [];

Il metodo pull recupera i messaggi dall'argomento che hai creato e li aggiunge all'elenco dei messaggi:

// get PULL pubsub messages
$pubsub = new PubSubClient([
    'projectId' => $projectId,
]);
$subscription = $pubsub->subscription($subscriptionName);
$pullMessages = [];
foreach ($subscription->pull(['returnImmediately' => true]) as $pullMessage) {
    $pullMessages[] = $pullMessage;
    $messages[] = $pullMessage->data();
}
// acknowledge PULL messages
if ($pullMessages) {
    $subscription->acknowledgeBatch($pullMessages);
}

Il metodo publish pubblica nuovi messaggi nell'argomento:

if ($message = (string) $request->getBody()) {
    // Publish the pubsub message to the topic
    $pubsub = new PubSubClient([
        'projectId' => $projectId,
    ]);
    $topic = $pubsub->topic($topicName);
    $topic->publish(['data' => $message]);
    return $response->withStatus(204);
}

Python

L'app di esempio utilizza i valori impostati nel file app.yaml per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta provenga da Pub/Sub e da un'origine attendibile:

app.config['PUBSUB_VERIFICATION_TOKEN'] = \
    os.environ['PUBSUB_VERIFICATION_TOKEN']
app.config['PUBSUB_TOPIC'] = os.environ['PUBSUB_TOPIC']

L'app di esempio gestisce un elenco globale per archiviare i messaggi ricevuti da questa istanza:

MESSAGES = []

Il metodo pubsub_push() riceve i messaggi inviati tramite push e li aggiunge all'elenco globale di MESSAGES:

@app.route("/pubsub/push", methods=["POST"])
def pubsub_push():
    if request.args.get("token", "") != current_app.config["PUBSUB_VERIFICATION_TOKEN"]:
        return "Invalid request", 400

    envelope = json.loads(request.data.decode("utf-8"))
    payload = base64.b64decode(envelope["message"]["data"])

    MESSAGES.append(payload)

    # Returning any 2xx status indicates successful receipt of the message.
    return "OK", 200

Il metodo index() interagisce con l'app web di App Engine per pubblicare i nuovi messaggi e visualizzare i messaggi ricevuti:

@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "GET":
        return render_template("index.html", messages=MESSAGES)

    data = request.form.get("payload", "Example payload").encode("utf-8")

    # publisher = pubsub_v1.PublisherClient()
    topic_path = publisher.topic_path(
        current_app.config["PROJECT"], current_app.config["PUBSUB_TOPIC"]
    )

    publisher.publish(topic_path, data=data)

    return "OK", 200

Ruby

L'app di esempio utilizza i valori impostati nel file app.yaml per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta provenga da Pub/Sub e da un'origine attendibile:

topic = pubsub.topic ENV["PUBSUB_TOPIC"]
PUBSUB_VERIFICATION_TOKEN = ENV["PUBSUB_VERIFICATION_TOKEN"]

L'app di esempio gestisce un elenco globale per archiviare i messaggi ricevuti da questa istanza:

# List of all messages received by this instance
messages = []

Questo metodo riceve i messaggi di cui viene eseguito il push e li aggiunge all'elenco globale messages:

post "/pubsub/push" do
  halt 400 if params[:token] != PUBSUB_VERIFICATION_TOKEN

  message = JSON.parse request.body.read
  payload = Base64.decode64 message["message"]["data"]

  messages.push payload
end

Questo metodo interagisce con l'app web App Engine per pubblicare i nuovi messaggi e visualizzare i messaggi ricevuti:

get "/" do
  @claims = claims
  @messages = messages

  slim :index
end

post "/publish" do
  topic.publish params[:payload]

  redirect "/", 303
end

.NET

versione 6

[HttpGet]
[HttpPost]
public async Task<IActionResult> IndexAsync(MessageForm messageForm)
{
    var model = new MessageList();
    if (!_options.HasGoodProjectId())
    {
        model.MissingProjectId = true;
        return View(model);
    }
    if (!string.IsNullOrEmpty(messageForm.Message))
    {
        // Publish the message.
        var pubsubMessage = new PubsubMessage()
        {
            Data = ByteString.CopyFromUtf8(messageForm.Message)
        };
        pubsubMessage.Attributes["token"] = _options.VerificationToken;
        await _publisher.PublishAsync(pubsubMessage);
        model.PublishedMessage = messageForm.Message;
    }
    // Render the current list of messages.
    model.Messages = s_receivedMessages.ToArray();
    model.AuthMessages = s_authenticatedMessages.ToArray();
    return View(model);
}

versione 3.1 e precedenti

[HttpGet]
[HttpPost]
public IActionResult Index(MessageForm messageForm)
{
    var model = new MessageList();
    if (!_options.HasGoodProjectId())
    {
        model.MissingProjectId = true;
        return View(model);
    }
    if (!string.IsNullOrEmpty(messageForm.Message))
    {
        // Publish the message.
        var pubsubMessage = new PubsubMessage()
        {
            Data = ByteString.CopyFromUtf8(messageForm.Message)
        };
        pubsubMessage.Attributes["token"] = _options.VerificationToken;
        _publisher.PublishAsync(pubsubMessage);
        model.PublishedMessage = messageForm.Message;
    }
    // Render the current list of messages.
    model.Messages = s_receivedMessages.ToArray();
    model.AuthMessages = s_authenticatedMessages.ToArray();
    return View(model);
}

Esecuzione dell'esempio in locale

Durante l'esecuzione in locale, puoi utilizzare Google Cloud CLI per fornire l'autenticazione per l'utilizzo delle API Google Cloud. Supponendo che tu abbia configurato l'ambiente come descritto nella sezione Prerequisiti, hai già eseguito il comando gcloud init, che fornisce questa autenticazione.

Go

Imposta le variabili di ambiente prima di avviare l'applicazione:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-token]
export PUBSUB_TOPIC=[your-topic]
go run pubsub.go

Java

mvn clean package

Imposta le variabili di ambiente prima di avviare l'applicazione:

export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
mvn jetty:run

Node.js

Imposta le variabili di ambiente prima di avviare l'applicazione:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
npm install
npm start

PHP

Installa le dipendenze utilizzando Composer:

composer install

Imposta quindi le variabili di ambiente prima di avviare l'applicazione:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
php -S localhost:8080

Python

Installare le dipendenze, preferibilmente in un ambiente virtuale.

Mac OS / Linux

  1. Crea un ambiente Python isolato:
    python3 -m venv env
    source env/bin/activate
  2. Se non ti trovi nella directory che contiene il codice campione, vai alla directory che contiene il codice campione hello_world. Quindi installa le dipendenze:
    cd YOUR_SAMPLE_CODE_DIR
    pip install -r requirements.txt

Windows

Utilizza PowerShell per eseguire i tuoi pacchetti Python.

  1. Individua l'installazione di PowerShell.
  2. Fai clic con il tasto destro del mouse sul collegamento a PowerShell e avvialo come amministratore.
  3. Crea un ambiente Python isolato.
    python -m venv env
    .\env\Scripts\activate
  4. Naviga alla directory del progetto e installa le dipendenze. Se non ti trovi nella directory che contiene il codice campione, vai a quella che contiene il codice campione hello_world. Quindi, installa le dipendenze:
    cd YOUR_SAMPLE_CODE_DIR
    pip install -r requirements.txt

Imposta quindi le variabili di ambiente prima di avviare l'applicazione:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
python main.py

Ruby

Installa le dipendenze:

bundle install

Imposta quindi le variabili di ambiente prima di avviare l'applicazione:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
bundle exec ruby app.rb -p 8080

.NET

Esegui i seguenti comandi dalla directory principale della tua applicazione:

    dotnet restore
    dotnet run

Nel browser Web, inserisci http://localhost:5000/. Per uscire dal server web, premi Ctrl+C nella finestra del terminale.

Simulazione di notifiche push

L'applicazione può inviare messaggi in locale, ma non può ricevere messaggi push localmente. Tuttavia, puoi simulare un messaggio push inviando una richiesta HTTP all'endpoint di notifica push locale. L'esempio include il file sample_message.json.

Go

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/push-handlers/receive_messages?token=[your-token]"

Oppure

http POST ":8080/push-handlers/receive_messages?token=[your-token]" < sample_message.json

Risposta:

HTTP/1.1 200 OK
Date: Tue, 13 Nov 2018 16:04:18 GMT
Content-Length: 0

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

Java

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/push-handlers/receive_messages?token=[your-token]"

Oppure

http POST ":8080/push-handlers/receive_messages?token=[your-token]" < sample_message.json

Risposta:

HTTP/1.1 200 OK
Date: Wed, 26 Apr 2017 00:03:28 GMT
Content-Length: 0
Server: Jetty(9.3.8.v20160314)

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

Node.js

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/push-handlers/receive_messages?token=[your-token]"

Oppure

http POST ":8080/push-handlers/receive_messages?token=[your-token]" < sample_message.json

Risposta:

HTTP/1.1 200 OK
Connection: keep-alive
Date: Mon, 31 Aug 2015 22:19:50 GMT
Transfer-Encoding: chunked
X-Powered-By: Express

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

PHP

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -i --data @sample_message.json "localhost:4567/push-handlers/receive_messages?token=[your-token]"

Oppure

http POST ":4567/push-handlers/receive_messages?token=[your-token]" < sample_message.json

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

Python

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[your-token]"

Oppure

http POST ":8080/pubsub/push?token=[your-token]" < sample_message.json

Risposta:

HTTP/1.0 200 OK
Content-Length: 2
Content-Type: text/html; charset=utf-8
Date: Mon, 10 Aug 2015 17:52:03 GMT
Server: Werkzeug/0.10.4 Python/2.7.10

OK

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

Ruby

Puoi utilizzare curl o un client httpie per inviare una richiesta POST HTTP:

curl -i --data @sample_message.json "localhost:4567/push-handlers/receive_messages?token=[your-token]"

Oppure

http POST ":4567/push-handlers/receive_messages?token=[your-token]" < sample_message.json

Risposta:

HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Content-Length: 13
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Server: WEBrick/1.3.1 (Ruby/2.3.0/2015-12-25)
Date: Wed, 20 Apr 2016 20:56:23 GMT
Connection: Keep-Alive

Hello, World!

Una volta completata la richiesta, puoi aggiornare localhost:8080 e vedere il messaggio nell'elenco dei messaggi ricevuti.

.NET

Per inviare una richiesta POST HTTP:

Get-Content -Raw .\sample_message.json | Invoke-WebRequest -Uri
http://localhost:5000/Push?token=your-secret-token -Method POST -ContentType
'text/json' -OutFile out.txt

Una volta completata la richiesta, puoi aggiornare localhost:5000 e vedere il messaggio nell'elenco dei messaggi ricevuti.

In esecuzione su App Engine

Per eseguire il deployment dell'app demo in App Engine utilizzando lo strumento a riga di comando gcloud:

Go

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy

Java

Per eseguire il deployment della tua app utilizzando Maven, esegui questo comando:

mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

Sostituisci PROJECT_ID con l'ID del tuo progetto Google Cloud. Se il file pom.xml specifica già il tuo ID progetto, non è necessario includere la proprietà -Dapp.deploy.projectId nel comando che esegui.

Node.js

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy

PHP

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy

Python

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy

Ruby

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy app.yaml

.NET

Esegui questo comando dalla directory in cui si trova il file app.yaml:

gcloud app deploy

Ora puoi accedere all'applicazione all'indirizzo https://PROJECT_ID.REGION_ID.r.appspot.com. Puoi utilizzare il modulo per inviare messaggi, ma non vi è alcuna garanzia di quale istanza della tua richiesta riceverà la notifica. Puoi inviare più messaggi e aggiornare la pagina per vedere il messaggio ricevuto.