Firebase Hosting with dynamic cloud functions rewrites

前端 未结 3 1402
忘了有多久
忘了有多久 2020-12-05 02:57

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 rout

相关标签:
3条回答
  • 2020-12-05 03:34

    Another option, if you want both cloudFunction and hosted URLS to work is to check if the URL is coming from the hosted URL.

    You'd use this function at any time you wanted the params.

    export const splitParams = (req: any): string[] => {
      let params = req.params[0];
      const vals: string[] = [];
    
      // If params starts with a '/' remove it
      params = params.startsWith('/')
        ? params.substr(1, params.length - 1)
        : params;
      params = params.split('/');
    
      // For hosted URLs the parameters need to be shifted
      if (
        req.headers['x-forwarded-host'] === 'myURL' 
      ) {
        params.shift();
      }
    
      for (const param of params) {
        if (param !== '') {
          vals.push(param);
        }
      }
    
      return vals;
    };
    
    0 讨论(0)
  • 2020-12-05 03:38

    You can use a single Firebase hosting rewrite rule with a complementing rewrite middleware in Express.

    1. Add a rewrite in your firebase.json file.

      {
        "source": "/api/**",
        "function": "api"
      }
      
    2. Include an app.use() middleware to rewrite the request 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);
      
    0 讨论(0)
  • 2020-12-05 03:52

    What seems to be the main issue is that this:

    {
        "source": "/api",
        "function": "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.

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

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

    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.

    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);
    
    0 讨论(0)
提交回复
热议问题