web-dev-qa-db-ja.com

動的なクラウド機能を使用したFirebase Hostingの書き換え

apiという名前の関数で、firebaseにexpress.jsベースのクラウド関数アプリがあります。カスタムドメインを使用するには、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"
      }
    ]

悲しいことに、可能な組み合わせでは機能しないようです。私のエクスプレスアプリには、使用する予定の次のGETパスがあります。

'/api/users/:userId/:userData'
'/api/users/:userId/:userData/json'
'/api/users/:userId/'

およびこれらに類似した他の。 :userIdおよび:userDataは、express.jsで機能するため、リクエストのパラメーターです。

必要な機能は、

https://my-firebase-app.cloudfunctions.net

しかし、彼らはで動作しません

https://my-app.firebaseapp.com

これらがどのように機能するのか、私が間違っていることを教えてください。

編集:これは私のクラウド機能のエクスポートがどのように見えるかのサンプルです

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の提案の後、私は次の構成を試しました

Firebase.jsonで次のことを試しました。

{
  "hosting": {
    "rewrites": [
      {
        "source": "/api",
        "function": "api"
      }
    ],
    "public": "public"
  }
}

しかし、同じ問題が発生しました。関数が呼び出されることはありません。書き換えがラストリゾートオプションであり、ホスティングにファイルが存在する場合、指定された関数に移動しないことを読みました(このwsが言及されているSOポストを探してみました見つけられない)だから、ホストのパブリックディレクトリから404.htmlとindex.htmlファイルを削除しました、とにかくそれらは必要ないのですが、問題はまだ残っていました。

編集2:さて、多くの試行錯誤の後、次の形式でパスをハードコーディングする必要がありました:

rewrites : [
      {
        "source": "/users/**/**/json",
        "function": "api"
      },
      {
        "source": "/api/users/**/**/json",
        "function": "api"
      }
]

この後、エクスプレスアプリは次のように構成されます。

app.get('/users/:userId/:userData/json', Foo)

誰かがホスティングの書き換えに必要な各ウリを手動で入れるのではなく、これを達成するためのより良い方法を提案できるなら、私はまだ好むでしょう。

14
Aditya Aggarwal

主な問題であると思われるのは、これです:

{
    "source": "/api",
    "function": "api"
}

実際に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);

これで、このmain関数を使用して、URL構造を壊さずに他のすべての関数に委任できます。

{
    "source": "/api/**", // "**" ensures we include paths such as "/api/users/:userId"
    "function": "main"
}

そして出来上がり!これで、期待どおりにhttps://my-app.firebaseapp.com/api/users/:userId/:userData経由ですべてのapi関数呼び出しにアクセスできます。

このエンドポイントを呼び出すと、技術的に正しいhttps://my-firebase-app.cloudfunctions.net/main/apiに書き換えられるようになりました。必要に応じて、main関数に追加するだけで、トップレベルの関数を追加できます。

const hooks = express();
main.use('/hooks/, hooks);
24
Pkmmte

Expressでは、単一のFirebaseホスティング書き換えルールと補完的な書き換えミドルウェアを使用できます。

  1. firebase.jsonファイルに rewrite を追加します。

    {
      "source": "/api/**",
      "function": "api"
    }
    
  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);
    
8
Sam