如何在 firebase 托管的 webapp 中获取 firebase 函数 URL?

Posted

技术标签:

【中文标题】如何在 firebase 托管的 webapp 中获取 firebase 函数 URL?【英文标题】:How to get the firebase functions URL in a firebase hosted webapp? 【发布时间】:2019-06-27 18:43:32 【问题描述】:

我正在开展一个项目,其中我们有与 Firebase 一起使用的预先存在的云功能。我们正在使用 Firebase 云托管添加一个小型 React SPA,该 SPA 将与一些现有的公共云功能进行交互。

到目前为止,我们的工作方式是在 Firebase 中有一个开发项目和一个生产项目。对于云功能,这很好用,我们使用firebase functions:config:set 设置了特定于环境的配置,用于区分生产服务器和开发服务器。

问题在于托管的 SPA 与云功能联系。我已经看到很多关于如何在托管代码中访问环境配置的问题,例如这个:How to reference Firebase Functions config variables from a Firebase-hosted application? 答案似乎是有返回环境变量值的 firebase 函数,但对我来说这个只是将问题进一步向后移动。我完全理解,由于 SPA 在浏览器中运行,因此让该代码可以访问环境变量将是一个巨大的安全问题。

对于托管 SPA,我真正需要的唯一环境特定配置是云功能的基址。

例如,如果在我的云功能中我有

const functions = require('firebase-functions');
const express = require('express');
const test = express();
test.on('/hello/:target', (req, res) => 
  res.send(`Hello $req.params.target`);
)
exports.test = functions.https.onRequest(test);

部署后,此云功能可在 https://us-central1-DEV-PROJECT-NAME.cloudfunctions.net/test/hello/world 和 https://us-central1-PROD-PROJECT-NAME.cloudfunctions.net/test/hello/world 使用。我如何才能最好地为 SPA 部署到的项目获取适当的根 URL(https://us-central1-DEV-PROJECT-NAME.cloudfunctions.net 或 https://us-central1-PROD-PROJECT-NAME.cloudfunctions.net)?

例如。是否有一些全局我可以在前端 js 代码中访问,我可以在其中执行以下操作:

const url = `$__FIREBASE_GLOBALS__.cloudFunctions.baseUrl/test/hello/$input`;

是否根据托管应用部署到的项目正确定义了 url?

【问题讨论】:

【参考方案1】:

我在这里假设您没有在 SPA 中以任何其他方式使用 Firebase,除了调用 Cloud Functions(因为您没有另外说)。

阅读Firebase web setup docs for Firebase Hosting,尤其是SDK imports and implicit initialization 部分。当您使用 Firebase 托管托管网站时,有一些特殊的 URL 可为您提供该项目的配置。有一些特殊的脚本可以让您访问 Firebase 产品。特别要注意,相对路径 URI /__/firebase/init.js 将生成 javascript,该 JavaScript 会使用项目的默认设置初始化 Firebase JavaScript SDK。继续并在指向您的 Web 应用程序的浏览器中访问它。您可能对配置的 projectId 属性感兴趣。

如果您想保留该值,可以使用 Firebase SDK,该 SDK 将由上面第一个链接中包含的脚本初始化。至少,您可以添加:

<script src="/__/firebase/5.8.2/firebase-app.js"></script>
<script src="/__/firebase/init.js"></script>

然后(see API docs):

firebase.app().options.projectId

获取 Firebase 托管提供内容的项目的 ID。您可以使用它来构建函数的 URL。

您还可以方便地将 HTTP 函数移植到 callable functions 并使用 Firebase SDK 从网站调用它们来调用 kthem。或者不。

【讨论】:

谢谢 Doug,您说得对,我们没有在 SPA 中使用任何其他 firebase 功能。因此,当我添加这些脚本时,我确实可以从配置的 firebase 应用程序中的 options 属性中获取 projectId,但是据我所知,这只是相关 URL 的一部分,另一部分是某种服务器位置/区域标识符(us-central1 在我原来的问题中)。这似乎没有包含在选项对象中,你知道我会从哪里获得它吗? 是的,您必须知道那是什么,即使您使用可调用对象。没办法。 哦,这看起来很奇怪,所以没有什么好的方法可以让托管应用程序不知道它的项目配置吗?感觉好像在同一个项目的托管应用程序中获取云函数 URL 肯定是一个简单的解决方案的常见需求。 Cloud Functions 与 Hosting 没有任何关系,除了 URL 重写,该函数必须绝对部署到 us-central1。 firebase.app().options 返回nullundefined【参考方案2】:

我能够从环境变量中获取 region 和 appId。

例如:

console.log(process.env);

检查您的 Firebase 日志

 ...
  ENTRY_POINT: 'server',
  X_GOOGLE_FUNCTION_TRIGGER_TYPE: 'HTTP_TRIGGER',
  FIREBASE_CONFIG: '"projectId":"pid","databaseURL":"https://pid.firebaseio.com","storageBucket":"pid.appspot.com","locationId":"europe-west"',
  X_GOOGLE_FUNCTION_NAME: 'server',
  FUNCTION_TRIGGER_TYPE: 'HTTP_TRIGGER',
  X_GOOGLE_GCLOUD_PROJECT: 'pid',
  FUNCTION_NAME: 'server',
  X_GOOGLE_GCP_PROJECT: 'pid',
  X_GOOGLE_FUNCTION_REGION: 'us-central1',
  FUNCTION_REGION: 'us-central1',
  X_GOOGLE_ENTRY_POINT: 'server',
  GCLOUD_PROJECT: 'pid',
  GCP_PROJECT: 'pid',
  ... ommited

这些GCP_PROJECTGCLOUD_PROJECTFUNCTION_REGIONFUNCTION_NAME 应该可以工作。所以例如。 process.env.FUNCTION_REGION

不确定这有多可靠。

【讨论】:

以上是关于如何在 firebase 托管的 webapp 中获取 firebase 函数 URL?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Firebase 托管的 webapp 获取没有 CORS 标头的外部数据?

使用自己的服务器 node.js 托管 Firebase

如何使用 Firebase 身份验证和托管将登录用户重定向到子域?

Flutter 现有项目到 WebApp + Firebase (Firestore + Hosting)

如何使用 Firebase 托管来托管图像?

如何在 webapp 中实现 firebase 云消息传递? [关闭]