Firebase托管与动态云功能重写

Adi*_*wal 14 express firebase firebase-hosting google-cloud-functions

我在一个名为的函数中的firebase上有一个基于express.js的云函数应用程序api.要使用自定义域,我正在尝试使用Firebase Hosting重写将特定URL路由到该功能.我在这里关注云功能和Firebase托管的官方文档,https: //firebase.google.com/docs/hosting/functions ,并尝试了许多组合,包括以下内容:

"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"
      }
    ]
Run Code Online (Sandbox Code Playgroud)

可悲的是,它似乎不适用于任何可能的组合.我的快递应用程序具有以下我计划使用的GET路径:

'/api/users/:userId/:userData'
'/api/users/:userId/:userData/json'
'/api/users/:userId/'
Run Code Online (Sandbox Code Playgroud)

和其他类似的.:userId和:userData是我的请求中的参数,因为它与express.js一起使用

所需的功能按预期工作

https://my-firebase-app.cloudfunctions.net
Run Code Online (Sandbox Code Playgroud)

但他们没有合作

https://my-app.firebaseapp.com
Run Code Online (Sandbox Code Playgroud)

请告诉我这些应该如何工作以及我做错了什么.

编辑:这是我的云功能导出的示例

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);
Run Code Online (Sandbox Code Playgroud)

编辑2:在@ DougStevenson的建议之后,我尝试了以下配置

我在firebase.json中尝试了以下内容,

{
  "hosting": {
    "rewrites": [
      {
        "source": "/api",
        "function": "api"
      }
    ],
    "public": "public"
  }
}
Run Code Online (Sandbox Code Playgroud)

但是我遇到了同样的问题,这个函数从未调用过.我读到了重写是最后的选项如何,如果主机中有文件存在,它将不会转到指定的功能.(我试着寻找这个ws提到的SO帖子,但我找不到它)所以我从托管的公共目录中删除了404.html和index.html文件,因为我无论如何都不需要它们.但问题仍然存在.

编辑2:好的,经过大量的试验和错误后,我只需要按以下格式对路径进行硬编码:

rewrites : [
      {
        "source": "/users/**/**/json",
        "function": "api"
      },
      {
        "source": "/api/users/**/**/json",
        "function": "api"
      }
]
Run Code Online (Sandbox Code Playgroud)

在此之后,Express应用程序配置如下:

app.get('/users/:userId/:userData/json', Foo)
Run Code Online (Sandbox Code Playgroud)

我仍然希望有人能提出更好的方法来实现这一点,而不是手动将每个必需的Uri放入托管重写中.

Pkm*_*mte 25

似乎主要问题是:

{
    "source": "/api",
    "function": "api"
}
Run Code Online (Sandbox Code Playgroud)

实际上是重写https://my-firebase-app.cloudfunctions.net/api/api而不是https://my-firebase-app.cloudfunctions.net/api像你期望的那样.注意如何api重复.

我的解决方案是创建一个main托管所有其他顶级函数的函数:

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);
Run Code Online (Sandbox Code Playgroud)

您现在可以使用此main功能委派所有其他功能,而不会破坏您的URL结构:

{
    "source": "/api/**", // "**" ensures we include paths such as "/api/users/:userId"
    "function": "main"
}
Run Code Online (Sandbox Code Playgroud)

瞧!您现在可以像您期望的那样访问所有api函数调用https://my-app.firebaseapp.com/api/users/:userId/:userData.

调用此端点,现在重写https://my-firebase-app.cloudfunctions.net/main/api为技术上正确的.main如果您愿意,可以通过简单地将它们添加到您的函数中来添加更多顶级函数:

const hooks = express();
main.use('/hooks/, hooks);
Run Code Online (Sandbox Code Playgroud)

  • @MuhammadHassan 这就是 Firebase 出于某种原因在内部工作的方式。我也不同意。它说“嘿,你想将 `/api` 重定向到你的 `api` 函数吗?好吧,我会把它作为 `api + /api` 传递到那里”。也许他们这样做是为了你可以将类似 `/cat` 的内容重定向到一个名为 `animals` 的函数,就像这样:`animals/cat`。 (3认同)
  • 这为我在app引擎上托管api节省了大量的时间和金钱.非常感谢! (3认同)
  • @Pkmmte我不明白为什么{“ source”:“ / api”,“ function”:“ api”}导致网址中重复/ api / api (2认同)
  • `"source": "/api/**"` 将捕获对 `/api/xyz` 和 `/api/` 发出的请求,但不会捕获对 `/api` 发出的请求。为了使其具有包容性,请使用 `"source": "/api{,/**}"`。来源:https://firebase.google.com/docs/hosting/full-config#rewrites (2认同)

小智 11

您可以在Express中使用单个Firebase托管重写规则和补充重写中间件.

  1. 在文件中添加重写firebase.json.

    {
      "source": "/api/**",
      "function": "api"
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 包含app.use()中间件以重写请求URL.

    const functions = require('firebase-functions');
    const express = require('express');
    
    const API_PREFIX = 'api';
    const app = express();
    
    // Rewrite Firebase hosting requests: /api/:path => /:path
    app.use((req, res, next) => {
        if (req.url.indexOf(`/${API_PREFIX}/`) === 0) {
            req.url = req.url.substring(API_PREFIX.length + 1);
        }
        next();
    });
    
    app.get('/users/:userId/:userData/json', (req, res) => {
        // Do App stuff here
    });
    
    exports[API_PREFIX] = functions.https.onRequest(app);
    
    Run Code Online (Sandbox Code Playgroud)

  • 这确实有效。Firebase 应该为他们不直观的文档感到羞耻,并且需要制作这样的噱头以使其在本地和生产中以相同的方式工作。谢谢! (2认同)