具有动态云功能的 Firebase 托管重写 [英] Firebase Hosting with dynamic cloud functions rewrites

查看:14
本文介绍了具有动态云功能的 Firebase 托管重写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在名为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆