Writing and Responding to Pub/Sub Messages

Google Cloud Pub/Sub provides reliable, many-to-many, asynchronous messaging between applications. Publisher applications can send messages to a topic, and other applications can subscribe to that topic to receive the messages.

This document describes how to use the Google Cloud Client Library to send and receive Google Cloud Pub/Sub messages in an app running in the flexible environment.

Prerequisites

  • Follow the instructions in "Hello, World!" for Node.js on App Engine to set up your environment and project, and to understand how App Engine Node.js apps are structured.
  • Write down and save your project ID, because you will need it to run the sample application described in this document.

    Clone the sample app

    Copy the sample apps to your local machine, and navigate to the pubsub directory:

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

    Create a topic and subscription

    Create a topic and subscription, which includes specifying the endpoint to which the Pub/Sub server should send requests:

    gcloud beta pubsub topics create YOUR_TOPIC_NAME
    gcloud beta pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
        --topic YOUR_TOPIC_NAME \
        --push-endpoint \
        https://YOUR_APP_ID.appspot.com/pubsub/push?token=YOUR_TOKEN \
        --ack-deadline 10
    

    Replace YOUR_TOKEN with a secret random token. The push endpoint uses this to verify requests.

    Edit app.yaml

    Edit app.yaml to set the environment variables for your project ID, topic, and verification token:

    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

    Code review

    The sample app uses the Google Cloud Client Libaries.

    The sample app uses the values you set in the app.yaml file to configure environment variables. The push request handler uses these values to confirm that the request came from Pub/Sub and originated from a trusted source:

    // The following environment variables are set by app.yaml when running on GAE,
    // 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.GCLOUD_PROJECT
    });
    var topic = pubsub.topic(process.env.PUBSUB_TOPIC);
    

    The sample app maintains a global list to store messages received by this instance:

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

    This method receives pushed messages and adds them to the messages global list:

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

    This method interacts with the App Engine web app to publish new messages and display received messages:

    app.get('/', (req, res) => {
      res.render('index', { messages: messages });
    });
    
    app.post('/', formBodyParser, (req, res, next) => {
      if (!req.body.payload) {
        res.status(400).send('Missing payload');
        return;
      }
    
      topic.publish({
        data: req.body.payload
      }, (err) => {
        if (err) {
          next(err);
          return;
        }
        res.status(200).send('Message sent');
      });
    });

    Run the sample locally

    When running locally, you can use the Google Cloud SDK to provide authentication to use Google Cloud APIs. Assuming you set up your environment as described in Prerequisites, you have already run the gcloud init command, which provides this authentication.

    Then set environment variables before starting your application:

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

    Simulate push notifications

    The application can send messages locally, but it is not able to receive push messages locally. You can, however, simulate a push message by making an HTTP request to the local push notification endpoint. The sample includes the file sample_message.json.

    You can use curl or httpie to send an HTTP POST request:

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

    Or

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

    Response:

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

    After the request completes, you can refresh localhost:8080 and see the message in the list of received messages.

    Run on App Engine

    To deploy the demo app to App Engine by using the gcloud command-line tool, you run the following command from the directory where your app.yaml is located:

    gcloud app deploy
    

    You can now access the application at https://[YOUR_PROJECT_ID].appspot.com. You can use the form to submit messages, but there's no guarantee of which instance of your application will receive the notification. You can send multiple messages and refresh the page to see the received message.

Monitor your resources on the go

Get the Google Cloud Console app to help you manage your projects.

Send feedback about...

App Engine flexible environment for Node.js docs