繁体   English   中英

声明单独的 Firebase Cloud Functions 并仍然使用 Express.js

[英]Declare separate Firebase Cloud Functions and still use Express.js

在 Firebase 云函数中使用 Express 的例子很多

在我发现的每个示例中,代码都将 Express 应用程序公开为单个 Cloud Function:

exports.app = functions.https.onRequest(app);

For one's Firebase Project Functions that means they will see one entry called "app" and all logs for all Express.js HTTP listeners will go to one place in Firebase. 这也意味着,无论 Express.js 应用程序有多大,Firebase 都会在生产环境中为该应用程序部署一个 function。

或者,当使用firebase-functions.https.onRequest时,您会为每个导出获得单独的函数,例如,在 Typescript 中:

export const hello = functions.https.onRequest(async (req, res) => {
  res.status(200).send('hello world');
});

在 Firebase 控制台中,我的 index.js 中有我的你好 function 和另一个 function:

在此处输入图像描述

这也意味着 Firebase 将为每个 function 创建不同的节点/实例: helloemphemeralKey

我将在 Firebase 控制台中为每个 function 获得单独的日志记录。

I would like to use middleware to ensure that valid auth tokens are being passed to my endpoint Cloud Functions like this Firebase example but I would prefer not to use a single "app" single Cloud Function, I would prefer a dedicated function for function export in我的 index.js。

感谢Doug Stevenson的回答和帮助。 我想提供自己的答案。

所以我的问题的答案一般来说是:不,你不能。

正如道格所指出的那样,对于许多人的扩展需求来说,这不是问题。 Firebase将创建多达1,000个要扩展的功能实例。

我想提供一个稍微不同的答案,然后Doug将如何编写Express应用程序并为项目使用不同的Firebase云功能:

const payment = express()
const order = express()
payment.get('/route', ...)
order.get('/route', ...)
export const payment = functions.https.onRequest(payment)
export const order = functions.https.onRequest(order)

这里的优点是我可以开始表达REST或RPC路由,如:

  • / payment / someaction(RPC)
  • /订单(获取,放置,发布等)

另一个好处是我可以为信用卡支付/处理等事项提供“测试”API和“实时”API:

// [START Express LIVE App]


// [START get user]
app.get('/user', async (req, res) => {
  await handleGetUser(req, res, paymentServiceLive);
});
// [END get user]

// [START claim]
app.post('/claim', async (req, res) => {
  await handleClaim(req, res, claimEmailTo);
});
// [END claim]

// [START user]
app.post('/user', async (req, res) => {
  await handleUserPost(req, res, paymentServiceLive);
});
// [END user]

// [START ephemeralKey]
app.post('/ephemeralKey', async (req, res) => {
  await handleEphemeralKey(req, res, paymentServiceLive);
});
// [END ephemeralKey]


// [START charge]
app.post('/charge', async (req, res) => {
  await handleCharge(req, res, paymentServiceLive);
});
// [END charge]

// [START purchase]
app.post('/purchase', async (req, res) => {
  await handlePurchase(req, res, paymentServiceLive);
});
// [END purchase]

//Expose Express API as a single Cloud Function:
exports.app = functions.https.onRequest(app);

// [END Express LIVE App]



// [START Express TEST App]

// [START get user]
appTest.get('/user', async (req, res) => {
  console.log('appTest /user get', req);
  await handleGetUser(req, res, paymentServiceTest);
});
// [END get user]

// [START claim]
appTest.post('/claim', async (req, res) => {
  await handleClaim(req, res, claimEmailToTest, true);
});
// [END claim]


// [START user]
appTest.post('/user', async (req, res) => {
  console.log('appTest /user post', req);
  await handleUserPost(req, res, paymentServiceTest);
});
// [END user]

// [START ephemeralKey]
appTest.post('/ephemeralKey', async (req, res) => {
  await handleEphemeralKey(req, res, paymentServiceTest)
});
// [END ephemeralKey]


// [START charge]
appTest.post('/charge', async (req, res) => {
  await handleCharge(req, res, stripeTest);
});
// [END charge]

// [START purchase]
appTest.post('/purchase', async (req, res) => {
  await handlePurchase(req, res, paymentServiceTest);
});
// [END purchase]

//Expose Express API as a single Cloud Function:np
exports.apptest = functions.https.onRequest(appTest);

// [END Express TEST App]

这使我可以拥有开发环境和实时环境。 在我的应用程序配置文件中,我只有一个不同的API网址:

/us-central1/apptest

要么

/us-central1/app

如果您有一个快速应用程序,则无法在项目中的不同逻辑功能之间拆分其路径。 如果您必须尝试在多个功能之间分配负载,则可以根据需要部署相同的快速应用程序。

const app = express()
app.get('/route1', ...)
app.get('/route2', ...)
export const f1 = functions.https.onRequest(app)
export const f2 = functions.https.onRequest(app)
// etc

现在,您可以尝试解决不同功能(及其不同结果URL)之间的不同路由。 但是,您并没有固有地限制某些路由在不同的函数中被调用。 由您来确保客户端正在使用您想要的功能。

如果您出于性能原因尝试执行此拆分,我会考虑这种过早优化。 云功能可以根据需要无缝扩展您的应用程序,而不仅仅是单个服务器实例。 如果您希望超出记录的限制 ,那么拆分这样的功能可能有助于扩展,但我希望这种情况并不常见。 如果你的应用程序没有理解实际观察到的性能特征,那就不可能了。 如果超过了极限, 联系技术支持 ,以帮助解释没有发生,你期待与您的部署方式。

如果您发现云功能的基本日志记录在监控每个路由时无用,那么您应该查看自定义StackDriver日志记录 ,这将有助于您更好地组织和监视函数生成的不同类型的日志。

有趣的讨论。

我选择了相同的方法:一个“端点”(也就是像“/ posts”,“/ users”这样的根路径)==一个专用的云功能(因为已经被唤起的原因+它更像是“μservicelike”而且它是什么“ lambda函数“对我来说”。

为了“干”我的所有功能都导入了一个“快速”发生器。 我在一个地方配置我的快递实例。

const express = () => {
  const express = require("express");
  const cors = require("cors")({ origin: true });
  const morgan = require("morgan");
  const helmet = require("helmet");

  const app = express();

  app.use(helmet());
  app.use(helmet.noCache());
  app.use(cors);
  app.use(morgan("combined"));

  return app;
};

module.exports = express;

我的“你好”终点:

const app = require("./../../express")();

/**
 * /hello
 */

app.get("/", (req, res) => {
  return res.send("Hello World");
});

module.exports = app;

我的index.js(主要出口):

const helloApi = require("./api/hello");

const https = functions.region("europe-west1").https;

module.exports.hello = https.onRequest(helloApi);

似乎对我们有用:)

只是觉得留下这个注册很有用,因为它对我有用,如果你觉得它有用,你可以做这样的事情:

const app = express();

export const appGetUser = functions.https.onRequest(
  app.get("/users/:userId", getUser)
);

这样,它是一个整体的 Express 应用程序,但每个 API 端点将被视为一个单独的 Firebase 云 Function。 您需要通过https://.../myFirebaseProject/us-central1/appGetUser/users/{userId}类的方式访问它们。

然后,如果您希望减少冗余端点:

export const users = functions.https.onRequest(
  app.get("/:userId", getUser)
);

现在将是https://.../myFirebaseProject/us-central1/users/{userId}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM