具有动态云功能的 Firebase 托管重写 [英] Firebase Hosting with dynamic cloud functions rewrites
问题描述
我在名为 api
的函数中的 firebase 上有一个基于 express.js 的云函数应用程序.要使用自定义域,我正在尝试使用 Firebase 托管重写将特定 URL 路由到函数.我正在关注此处关于云函数和 Firebase 托管的官方文档,https://firebase.google.com/docs/hosting/functions,并尝试了许多组合,包括以下:
I have an express.js based cloud functions app on firebase in a function named api
. To use a custom domain, I'm trying to use Firebase Hosting rewrites to route the specific URL to the function.
I'm following the official documentation about cloud functions and Firebase hosting here, https://firebase.google.com/docs/hosting/functions, and have tried many combinations including the following:
"rewrites": [
{
"source": "/api/**",
"function": "api"
}
]
"rewrites": [
{
"source": "/api/:path1/:dat1/dat",
"function": "api/:path1/:dat1/dat"
}
]
"rewrites": [
{
"source": "/api/path1/dat1/dat",
"function": "api"
}
]
"rewrites": [
{
"source": "/api/*/*/*",
"function": "api"
}
]
遗憾的是,它似乎不适用于任何可能的组合.我的 express 应用有以下我打算使用的 GET 路径:
Sadly, It doesn't seem to work for any possible combination. My express app has the following GET paths I plan on using:
'/api/users/:userId/:userData'
'/api/users/:userId/:userData/json'
'/api/users/:userId/'
和其他类似的.:userId 和 :userData 是我请求中的参数,因为它适用于 express.js
and others similar to these. the :userId and :userData are the params in my request, as it works with express.js
所需的功能在
https://my-firebase-app.cloudfunctions.net
但它们不适用于
https://my-app.firebaseapp.com
请告诉我这些应该如何工作以及我做错了什么.
Please tell me how these are supposed to work and what I'm doing wrong.
这是我的云函数导出的示例
Here is a sample of what my cloud functions export looks like
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/users/:userId/:userData/json', (req, res) => {
// Do App stuff here
}
// A couple more app.get in the same format
exports.api = functions.https.onRequest(app);
编辑 2:在@DougStevenson 的建议下,我尝试了以下配置
EDIT 2: After @DougStevenson's suggestion, I tried the following configuration
我在 firebase.json 中尝试了以下内容,
I tried the following in my firebase.json ,
{
"hosting": {
"rewrites": [
{
"source": "/api",
"function": "api"
}
],
"public": "public"
}
}
但我遇到了同样的问题,该函数从未被调用.我读到重写如何是最后的选择,如果托管中存在文件,它不会转到指定的功能.(我尝试寻找提到这个 ws 的 SO 帖子,但我找不到它)所以我从托管的公共目录中删除了 404.html 和 index.html 文件,因为无论如何我都不需要它们.但问题仍然存在.
But I got the same problem, the function is never called. I read about how the rewrites are last resort options and if there are files present in the hosting, it will not go to the specified function.(I tried looking for the SO post where this ws mentioned but I can't find it) So I removed the 404.html and index.html files from hosting's public directory, since I don't need them anyway. But the problem still remained.
编辑 2:好的,经过大量的反复试验,我只需要按以下格式对路径进行硬编码:
EDIT 2: Okay, so after a lot of trial and error, I just had to hard code the paths in the following format:
rewrites : [
{
"source": "/users/**/**/json",
"function": "api"
},
{
"source": "/api/users/**/**/json",
"function": "api"
}
]
在此之后,express 应用程序配置如下:
After this, the express app is configured something like this:
app.get('/users/:userId/:userData/json', Foo)
我仍然希望有人可以提出更好的方法来实现这一点,而不是在托管重写中手动放入每个必需的 Uri.
I still would prefer if someone could suggest a better way to accomplish this rather than manually putting in each required Uri in the hosting rewrites.
推荐答案
似乎主要问题是:
{
"source": "/api",
"function": "api"
}
实际上是重写为 https://my-firebase-app.cloudfunctions.net/api/api
而不是 https://my-firebase-app.cloudfunctions.net/api
就像你期望的那样.注意 api
是如何重复的.
is actually rewriting to https://my-firebase-app.cloudfunctions.net/api/api
instead of https://my-firebase-app.cloudfunctions.net/api
like you'd expect. Notice how api
is repeated.
我的解决方案是创建一个 main
函数来承载所有其他顶级函数:
My solution to this is to create a main
function which hosts all other top-level functions:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/users/:userId/:userData/json', (req, res) => {
// Do App stuff here
}
// A couple more app.get in the same format
// Create "main" function to host all other top-level functions
const main = express();
main.use('/api', app);
exports.main = functions.https.onRequest(main);
您现在可以使用此 main
函数委托给所有其他函数,而不会破坏您的 URL 结构:
You can now use this main
function to delegate to all other functions without breaking your URL structure:
{
"source": "/api/**", // "**" ensures we include paths such as "/api/users/:userId"
"function": "main"
}
瞧!您现在可以像预期的那样通过 https://my-app.firebaseapp.com/api/users/:userId/:userData
访问所有 api
函数调用.
And voila! You can now access all api
function calls via https://my-app.firebaseapp.com/api/users/:userId/:userData
just like you'd expect.
调用此端点,现在重写为 https://my-firebase-app.cloudfunctions.net/main/api
,这在技术上是正确的.然后,如果您愿意,您可以通过简单地将它们添加到您的 main
函数来添加更多顶级函数:
Calling this endpoint, now rewrites to https://my-firebase-app.cloudfunctions.net/main/api
which is technically correct. You can then add more top-level functions by simply adding them to your main
function if you wish:
const hooks = express();
main.use('/hooks/, hooks);
这篇关于具有动态云功能的 Firebase 托管重写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!