是否可以触发pubsub消息来响应HTTP云功能?
在编辑订阅时,Google可以将消息推送到HTTPS端点,但是出于滥用的原因,人们必须能够证明您拥有域才能执行此操作,当然您不能证明您拥有Google自己的*.cloudfunctions.net
域,这是它们部署所在的域。
我要订阅的特定主题是公共主题projects/pubsub-public-data/topics/taxirides-realtime
。答案可能是使用后台功能,而不是使用HTTP触发的,但这由于不同的原因而无效:
gcloud functions deploy echo --trigger-resource projects/pubsub-public-data/topics/taxirides-realtime --trigger-event google.pubsub.topic.publish
ERROR: gcloud crashed (ArgumentTypeError): Invalid value 'projects/pubsub-public-data/topics/taxirides-realtime': Topic must contain only Latin letters (lower- or upper-case), digits and the characters - + . _ ~ %. It must start with a letter and be from 3 to 255 characters long.
这似乎表明只允许在我拥有的主题上使用,这是一个奇怪的限制。
答案 0 :(得分:0)
您收到的错误似乎是您在发出的gcloud命令中拼写错误。
ERROR: gcloud crashed (ArgumentTypeError): Invalid value 'projects/pubsub-public-data/topics/taxirides-realtime': Topic must contain only Latin letters (lower- or upper-case), digits and the characters - + . _ ~ %. It must start with a letter and be from 3 to 255 characters long
您要在命令中间放置换行符吗?
答案 1 :(得分:0)
当前,Cloud Functions不允许创建一个函数来接收其他项目中某个主题的消息。因此,指定包含“ projects / pubsub-public-data”的完整路径不起作用。用于为主题部署云功能的gcloud
命令仅需要主题名称(而不是完整的资源路径)。由于完整的资源路径包含“ /”字符,因此它不是有效的规范,并会导致您看到错误。
答案 2 :(得分:0)
可以从发布/订阅主题发布到云功能。我正在寻找一种从项目A中的主题发布到项目B中的函数的方法。使用常规主题触发器无法实现,但是使用http-trigger可以实现。遵循的步骤:
在项目A中的该主题上创建一个订阅。作为推送端点,从项目B中的函数中选择URL:
https://YOUR_REGION-YOUR_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME/?token=[randomstring] <-不要忘了最后的斜线!
选择一个您要用来发送实际消息的服务帐户。作为受众群体,您可以选择您的域(例如example.com)。
现在,您可能由于错误而无法保存您的订阅,这是因为端点未通过Google验证。因此,您需要在以下网址将功能URL列入白名单:API和服务>凭据>域验证。
接下来,我们需要在您的云函数中添加以下内容(python示例),以允许Google验证该函数:
if request.method == 'GET':
return '''
<html>
<head>
<meta name="google-site-verification" content="{token}" />
</head>
<body>
</body>
</html>
'''.format(token=config.SITE_VERIFICATION_CODE)
现在,我们需要保护端点。首先检查您在网址中提供的令牌:
if (request.args.get('token', '') != '[randomstring]'):
return 'Invalid request', 400
检查授权标头源自提供的服务帐户和受众:
try:
bearer_token = request.headers.get('Authorization')
token = bearer_token.split(' ')[1]
claim = id_token.verify_oauth2_token(token, requests.Request(), audience='example.com')
if claim['iss'] not in [
'accounts.google.com',
'https://accounts.google.com'
]:
raise ValueError('Wrong issuer.')
except Exception as e:
return 'Invalid token: {}\n'.format(e), 400
envelope = json.loads(request.data.decode('utf-8'))
payload = base64.b64decode(envelope['message']['data'])
瞧!现在应该可以使用了。
来源: https://github.com/googleapis/nodejs-pubsub/issues/118#issuecomment-379823198, https://cloud.google.com/functions/docs/calling/http