web-dev-qa-db-fra.com

Hébergement Firebase avec fonctions de cloud dynamique réécrit

J'ai une application de fonctions cloud basée sur express.js sur firebase dans une fonction nommée api. Pour utiliser un domaine personnalisé, j'essaie d'utiliser les réécritures de Firebase Hosting pour router l'URL spécifique vers la fonction. Je suis ici la documentation officielle sur les fonctions cloud et l'hébergement Firebase, https://firebase.google.com/docs/hosting/functions , et j'ai essayé de nombreuses combinaisons, y compris les suivantes:

"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"
      }
    ]

Malheureusement, cela ne semble pas fonctionner pour une combinaison possible. Mon application express a les chemins GET suivants que je prévois d'utiliser:

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

et d'autres similaires à ceux-ci. les: userId et: userData sont les paramètres de ma demande, car cela fonctionne avec express.js

Les fonctions requises fonctionnent comme prévu dans

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

mais ils ne fonctionnent pas avec

https://my-app.firebaseapp.com

Veuillez me dire comment ceux-ci sont censés fonctionner et ce que je fais mal.

EDIT: Voici un exemple de ce à quoi ressemble l'export de mes fonctions cloud

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);

EDIT 2: Après la suggestion de @ DougStevenson, j'ai essayé la configuration suivante

J'ai essayé ce qui suit dans mon firebase.json,

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

Mais j'ai le même problème, la fonction n'est jamais appelée. J'ai lu comment les réécritures sont des options de dernier recours et s'il y a des fichiers présents dans l'hébergement, il n'ira pas à la fonction spécifiée. (J'ai essayé de chercher le SO poste où cela a été mentionné) mais je ne le trouve pas) J'ai donc supprimé les fichiers 404.html et index.html du répertoire public de l'hébergement, car je n'en ai pas besoin de toute façon. Mais le problème restait.

EDIT 2: D'accord, donc après beaucoup d'essais et d'erreurs, je n'ai eu qu'à coder en dur les chemins dans le format suivant:

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

Après cela, l'application express est configurée quelque chose comme ceci:

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

Je préférerais toujours que quelqu'un suggère une meilleure façon d'accomplir cela plutôt que de mettre manuellement chaque Uri requis dans les réécritures d'hébergement.

14
Aditya Aggarwal

Ce qui semble être le principal problème est que ceci:

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

est en train de réécrire dans https://my-firebase-app.cloudfunctions.net/api/api au lieu de https://my-firebase-app.cloudfunctions.net/api comme vous vous y attendez. Remarquez comment api est répété.

Ma solution est de créer une fonction main qui héberge toutes les autres fonctions de niveau supérieur:

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);

Vous pouvez maintenant utiliser cette fonction main pour déléguer à toutes les autres fonctions sans casser votre structure d'URL:

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

Et le tour est joué! Vous pouvez désormais accéder à tous les appels de fonction api via https://my-app.firebaseapp.com/api/users/:userId/:userData comme vous vous en doutez.

L'appel de ce point de terminaison est désormais réécrit en https://my-firebase-app.cloudfunctions.net/main/api ce qui est techniquement correct. Vous pouvez ensuite ajouter d'autres fonctions de niveau supérieur en les ajoutant simplement à votre fonction main si vous le souhaitez:

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

Vous pouvez utiliser une seule règle de réécriture d'hébergement Firebase avec un middleware de réécriture complémentaire dans Express.

  1. Ajoutez un réécriture dans votre firebase.json fichier.

    {
      "source": "/api/**",
      "function": "api"
    }
    
  2. Incluez un middleware app.use () pour réécrire l'url de la requête.

    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