Writing and responding to Pub/Sub messages

Region ID

TheREGION_ID is an abbreviated code that Google assignsbased on the region you select when you create your app. The code does notcorrespond to a country or province, even though some region IDs may appearsimilar to commonly used country and province codes. For apps created after February 2020,REGION_ID.r is included in App Engine URLs. For existing apps created before this date, the region ID is optional in the URL.

Learn moreabout region IDs.

Pub/Sub providesreliable, many-to-many, asynchronous messaging between applications. Publisherapplications can send messages to atopic, and other applications cansubscribe to that topic to receive the messages.

This document describes how to use theCloud Client Libraries to send and receive Pub/Sub messages in an App Engine app.

Prerequisites

Cloning the sample app

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

Go

gitclonehttps://github.com/GoogleCloudPlatform/golang-samples.gitcdgolang-samples/appengine/go11x/pubsub/authenicated_push

Java

No example available for this runtime.

Note that Java demo apps are available in theflexible environment.

Node.js

gitclonehttps://github.com/GoogleCloudPlatform/nodejs-docs-samplescdnodejs-docs-samples/appengine/pubsub

PHP

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

Python

gitclonehttps://github.com/GoogleCloudPlatform/python-docs-samplescdpython-docs-samples/appengine/standard_python3/pubsub

Ruby

gitclonehttps://github.com/GoogleCloudPlatform/ruby-docs-samplescdruby-docs-samples/appengine/pubsub

Create a topic and subscription

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

Go

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

Java

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

Node.js

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

PHP

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

Python

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

Ruby

# Configure the topicgcloudpubsubtopicscreateYOUR_TOPIC_NAME# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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

ReplaceYOUR_TOKEN with a secret random token. The push endpoint uses thisto verify requests.

To use Pub/Sub with authentication, create another subscription:

# Configure the push subscriptiongcloudpubsubsubscriptionscreateYOUR_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 service agent# `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"gcloudprojectsadd-iam-policy-binding${PROJECT_ID}\--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\--role='roles/iam.serviceAccountTokenCreator'

ReplaceYOUR-SERVICE-ACCOUNT-EMAIL with yourservice account email.

Setting environment variables

Go

Edit theapp.yaml file to set the environment variables for your topic andverification token:

# Copyright 2020 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##     https://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.runtime:go122env_variables:# This token is used to verify that requests originate from your# application. It can be any sufficiently random string.PUBSUB_VERIFICATION_TOKEN:check123

Java

Edit theapp.yaml file to set the environment variables for your topic andverification token:

env_variables:PUBSUB_TOPIC:<your-topic-name>PUBSUB_VERIFICATION_TOKEN:<your-verification-token>

Node.js

Edit yourapp.yaml file to set the environment variables for your topic andverification 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

PHP

Edit yourindex.php file to set the environment variables for your topic andsubscription:

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

Python

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

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_VERIFICATION_TOKEN>'

Ruby

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

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

Code review

The sample app uses thePub/Sub Client Library.

Go

The sample app uses the environment variables you set in theapp.yaml file(PUBSUB_TOPIC andPUBSUB_VERIFICATION_TOKEN) for configuration.

The messages received by this instance are stored in a slice:

messages[]string
Note: This tutorial is using an instance level global variable,messages, to store messages received from Pub/Sub. In production, that should be converted to an external storage solution, such as Firestore.

ThereceiveMessagesHandler functionreceives pushed messages, verifies the token, andadds the message to themessages slice:

// receiveMessagesHandler validates authentication token and caches the Pub/Sub// message received.func(a*app)receiveMessagesHandler(whttp.ResponseWriter,r*http.Request){ifr.Method!="POST"{http.Error(w,http.StatusText(http.StatusMethodNotAllowed),http.StatusMethodNotAllowed)return}// Verify that the request originates from the application.// a.pubsubVerificationToken = os.Getenv("PUBSUB_VERIFICATION_TOKEN")iftoken,ok:=r.URL.Query()["token"];!ok||len(token)!=1||token[0]!=a.pubsubVerificationToken{http.Error(w,"Bad token",http.StatusBadRequest)return}// Get the Cloud Pub/Sub-generated JWT in the "Authorization" header.authHeader:=r.Header.Get("Authorization")ifauthHeader==""||len(strings.Split(authHeader," "))!=2{http.Error(w,"Missing Authorization header",http.StatusBadRequest)return}token:=strings.Split(authHeader," ")[1]// Verify and decode the JWT.// If you don't need to control the HTTP client used you can use the// convenience method idtoken.Validate instead of creating a Validator.v,err:=idtoken.NewValidator(r.Context(),option.WithHTTPClient(a.defaultHTTPClient))iferr!=nil{http.Error(w,"Unable to create Validator",http.StatusBadRequest)return}// Please change http://example.com to match with the value you are// providing while creating the subscription.payload,err:=v.Validate(r.Context(),token,"http://example.com")iferr!=nil{http.Error(w,fmt.Sprintf("Invalid Token: %v",err),http.StatusBadRequest)return}ifpayload.Issuer!="accounts.google.com" &&payload.Issuer!="https://accounts.google.com"{http.Error(w,"Wrong Issuer",http.StatusBadRequest)return}// IMPORTANT: you should validate claim details not covered by signature// and audience verification above, including://   - Ensure that `payload.Claims["email"]` is equal to the expected service//     account set up in the push subscription settings.//   - Ensure that `payload.Claims["email_verified"]` is set to true.ifpayload.Claims["email"]!="test-service-account-email@example.com"||payload.Claims["email_verified"]!=true{http.Error(w,"Unexpected email identity",http.StatusBadRequest)return}varprpushRequestiferr:=json.NewDecoder(r.Body).Decode(&pr);err!=nil{http.Error(w,fmt.Sprintf("Could not decode body: %v",err),http.StatusBadRequest)return}a.messagesMu.Lock()defera.messagesMu.Unlock()// Limit to ten.a.messages=append(a.messages,pr.Message.Data)iflen(a.messages) >maxMessages{a.messages=a.messages[len(a.messages)-maxMessages:]}fmt.Fprint(w,"OK")}

Java

No example available for this runtime.

Note that a Java demo app is available in theflexible environment.

Node.js

The sample app uses the values you set in yourapp.yaml file toconfigure environment variables. The push request handler uses these values toconfirm that the request came from Pub/Sub and originated from a trustedsource:

// 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.varPUBSUB_VERIFICATION_TOKEN=process.env.PUBSUB_VERIFICATION_TOKEN;varpubsub=gcloud.pubsub({projectId:process.env.GOOGLE_CLOUD_PROJECT});vartopic=pubsub.topic(process.env.PUBSUB_TOPIC);

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

// List of all messages received by this instancevarmessages=[];
Note: This tutorial is using an instance level global variable,messages, to store messages received from Pub/Sub. In production, that should be converted to an external storage solution, such as Firestore.

This methodreceives pushed messages and adds them to themessagesglobal 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.constmessage=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 newmessages and display received messages:

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;}constdata=Buffer.from(req.body.payload);try{constmessageId=awaittopic.publishMessage({data});res.status(200).send(`Message${messageId} sent.`);}catch(error){next(error);}});

PHP

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

runtime:php81handlers:-url:/pubsub\.jsstatic_files:pubsub.jsupload:pubsub\.js

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

$messages = [];
Note: This tutorial is using an instance level global variable,$messages, to store messages received from Pub/Sub. In production, that should be converted to an external storage solution, such as Firestore.

Thepull method retrieves messages from the topic you created and adds themto the messages list:

// 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 messagesif ($pullMessages) {    $subscription->acknowledgeBatch($pullMessages);}

Thepublish method publishes new messages to the topic:

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

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

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

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

MESSAGES=[]
Note: This tutorial is using an instance level global variable,MESSAGES, to store messages received from Pub/Sub. In production, that should be converted to an external storage solution, such as Firestore.

Thereceive_messages_handler() methodreceives pushed messages and adds them to theMESSAGESglobal list:

@app.route("/pubsub/push",methods=["POST"])defreceive_pubsub_messages_handler():# Verify that the request originates from the application.ifrequest.args.get("token","")!=current_app.config["PUBSUB_VERIFICATION_TOKEN"]:return"Invalid request",400envelope=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

Theindex() method interacts with the App Engine web app to publishnew messages and display received messages:

@app.route("/",methods=["GET","POST"])defindex():ifrequest.method=="GET":returnrender_template("index.html",messages=MESSAGES,tokens=TOKENS,claims=CLAIMS)data=request.form.get("payload","Example payload").encode("utf-8")# Consider initializing the publisher client outside this function# for better latency performance.publisher=pubsub_v1.PublisherClient()topic_path=publisher.topic_path(app.config["GOOGLE_CLOUD_PROJECT"],app.config["PUBSUB_TOPIC"])future=publisher.publish(topic_path,data)future.result()return"OK",200

Ruby

The sample app uses the values you set in theapp.standard.yaml file to configureenvironment variables. The push request handler uses these values to confirmthat the request came from Pub/Sub and originated from a trusted source:

publisher=pubsub.publisherENV["PUBSUB_TOPIC"]PUBSUB_VERIFICATION_TOKEN=ENV["PUBSUB_VERIFICATION_TOKEN"]

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

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

This methodreceives pushed messages and adds them to themessagesglobal list:

Note: This tutorial is using an instance level global variable,messages, to store messages received from Pub/Sub. In production, that should be converted to an external storage solution, such as Firestore.
post"/pubsub/push"dohalt400ifparams[:token]!=PUBSUB_VERIFICATION_TOKENmessage=JSON.parserequest.body.readpayload=Base64.decode64message["message"]["data"]messages.pushpayloadend

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

get"/"do@claims=claims@messages=messagesslim:indexendpost"/publish"dopublisher.publishparams[:payload]redirect"/",303end

Running the sample locally

When running locally, you can use the Google Cloud CLI to provide authenticationto use Google Cloud APIs. Assuming you set up your environment as described inPrerequisites, you have already run thegcloud init command,which provides this authentication.

Go

Set environment variables before starting your application:

exportGOOGLE_CLOUD_PROJECT=[your-project-id]exportPUBSUB_VERIFICATION_TOKEN=[your-token]exportPUBSUB_TOPIC=[your-topic]gorunpubsub.go

Java

Set environment variables before starting your application:

exportPUBSUB_VERIFICATION_TOKEN=[your-verification-token]exportPUBSUB_TOPIC=[your-topic]

To run your application locally, use the development tools that youusually use.

Node.js

Set environment variables before starting your application:

exportGOOGLE_CLOUD_PROJECT=[your-project-id]exportPUBSUB_VERIFICATION_TOKEN=[your-verification-token]exportPUBSUB_TOPIC=[your-topic]npminstallnpmstart

PHP

Install dependencies using Composer:

composer install

Then set environment variables before starting your application:

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

Python

Install dependencies, preferably in a virtual environment.

Mac OS / Linux

  1. Create anisolated Python environment:
    python3-mvenvenvsourceenv/bin/activate
  2. If you're not in the directory that contains the sample code, navigate to the directory that contains thehello_world sample code. Then install dependencies:
    cdYOUR_SAMPLE_CODE_DIRpipinstall-rrequirements.txt

Windows

Use PowerShell to run your Python packages.

  1. Locate your installation ofPowerShell.
  2. Right-click on the shortcut to PowerShell and start it as an administrator.
  3. Create anisolated Python environment.
    python-mvenvenv.\env\Scripts\activate
  4. Navigate to your project directory and install dependencies. If you're not in the directory that contains the sample code, navigate to the directory that contains thehello_world sample code. Then, install dependencies:
    cdYOUR_SAMPLE_CODE_DIRpipinstall-rrequirements.txt

Then set environment variables before starting your application:

exportGOOGLE_CLOUD_PROJECT=[your-project-id]exportPUBSUB_VERIFICATION_TOKEN=[your-verification-token]exportPUBSUB_TOPIC=[your-topic]pythonmain.py

Ruby

Install dependencies:

bundleinstall

Then set environment variables before starting your application:

exportGOOGLE_CLOUD_PROJECT=[your-project-id]exportPUBSUB_VERIFICATION_TOKEN=[your-verification-token]exportPUBSUB_TOPIC=[your-topic]bundleexecrubyapp.rb-p8080

Simulating push notifications

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

Go

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

Response:

HTTP/1.1200OKDate:Tue,13Nov201816:04:18GMTContent-Length:0

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

Java

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

Node.js

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

Response:

HTTP/1.1200OKConnection:keep-aliveDate:Mon,31Aug201522:19:50GMTTransfer-Encoding:chunkedX-Powered-By:Express

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

PHP

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

Python

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

Response:

HTTP/1.0200OKContent-Length:2Content-Type:text/html;charset=utf-8Date:Mon,10Aug201517:52:03GMTServer:Werkzeug/0.10.4Python/2.7.10OK

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

Ruby

You can usecurl orahttpie client tosend an HTTPPOST request:

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

Or

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

Response:

HTTP/1.1200OKContent-Type:text/html;charset=utf-8Content-Length:13X-Xss-Protection:1;mode=blockX-Content-Type-Options:nosniffX-Frame-Options:SAMEORIGINServer:WEBrick/1.3.1(Ruby/2.3.0/2015-12-25)Date:Wed,20Apr201620:56:23GMTConnection:Keep-AliveHello,World!

After the request completes, you can refreshlocalhost:8080 and see themessage in the list of received messages.

Running on App Engine

To deploy the demo app to App Engine using thegcloud command-linetool:

Go

Run the following command from the directory where yourapp.yaml file is located:

gcloudappdeploy

Java

Run thegcloud command from the directory where yourapp.yaml file islocated:

gcloudappdeploy

To deploy your app using Maven, run the following:

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

ReplacePROJECT_ID with the ID of your Google Cloud project. Ifyourpom.xml file alreadyspecifies yourproject ID, you don't need to include the-Dapp.deploy.projectId property in thecommand you run.

Node.js

Run the following command from the directory where yourapp.yaml fileis located:

gcloudappdeploy

PHP

Run the following command from the directory where yourapp.yaml file is located:

gcloud app deploy

Python

Run the following command from the directory where yourapp.yaml file is located:

gcloudappdeploy

Ruby

Run the following command from the directory where yourapp.yaml file is located:

gcloudappdeployapp.standard.yaml

You can now access the application athttps://PROJECT_ID.REGION_ID.r.appspot.com.You can use the form to submit messages, but there's no guarantee of whichinstance of your application will receive the notification. You can sendmultiple messages and refresh the page to see the received message.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.