26

I've a PWA built using polymer 2.0 and polymerfire and is my web application. I've an express app acting as a cloud function (microservice). Example: exports.register=functions.https.onRequest(app);

How to add the rewrite rules to map say /fns/register and /fns/verify to the above app register.

I've updated my firebase.json file in the cloudfunction microservice project, but when I run firebase deploy --only functions:register it says there is no public folder for deploying the hosting configuration!

{
    "hosting": {
        "rewrites": [{
            "source": "/fns/**", "function": "register"
        }]
    }    
}

Maintaining the rewrite rules in the original web applicaiton could be one option, but still, is not ideal IMHO. If I've to do it in my original web application, I tried that as well, but couldn't make it. Following is my updated firebase.json in my original web application:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "build/default/public",
    "rewrites": [
      {
        "source": "/fns/**",
        "function": "register"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}
Phani
  • 1,851
  • 2
  • 15
  • 28

3 Answers3

61

Maintaining just one project for all resources (Hosting, Functions and Database) is the ideal, I think is the right way to manage Firebase projects.

You are trying to change just one parameter (rewrites) of the hosting service, and it's not the way it works. When you deploy the firebase.json, all the others configurations are overwritten. So, the error you got is because Firebase don't look the last configuration file and check what's different to update, it just tries to overwrite all the last configuration file and get an error because "public" is a required parameter for hosting.

That explained, now you are expecting that Firebase rewrites /fns/register to just /register, but it'll not occur. Your function gonna receive the "full" url /fns/register.

The best way, I think, is to create a root route:

var functions = require('firebase-functions');
var express = require('express');

var app = express();
var router = express.Router();

router.post('/register', registerFunction);
router.post('/verify', verifyFunction);

app.use('/fns', router);

exports.fns = functions.https.onRequest(app);

And rewrites all functions to fns function:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "build/default/public",
    "rewrites": [
      {
        "source": "/fns/**",
        "function": "fns"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Now you can use https://<your-project-id>.firebaseapp.com/fns/register to reach your register function and https://<your-project-id>.firebaseapp.com/fns/verify to reach your verify function.

Marcos V.
  • 733
  • 4
  • 8
  • Thank you @Marcos V for the answer. But the continuous suggestion from google IO 2017 is to go for microservices. Hence having just one project is not really a nice solution that I am looking for. I want to embark on microservice style for its agility, scalability, and localization of errors. Hence I couldn't accept your answer. – Phani Aug 06 '17 at 17:06
  • 3
    @Phani Your question's title does not mention the requirement for separate projects at all. Maybe you could accept this answer (which answers your main question) and open up another question of how to be able to maintain rewrite rules and functions in separate projects? – Motin Oct 23 '17 at 07:41
  • I can't accept this as a solution @Motin because maintaining all the hosting, functions and database in one project is not ideal in a microservice world. I would rather be OK to accept that the hosting file can only be in one main project (though not ideal). But the functions can be in any number of other projects and database can be in another project altogether. This is the approach of a microservice and I am following this already. – Phani Oct 23 '17 at 08:15
  • 1
    You clearly seem to confuse microservices with projects, but nevertheless I think it's unfair to not accept this great answer. – Sanjay Verma Sep 29 '22 at 02:39
-1

This question is already answered here Firebase Hosting with dynamic cloud functions rewrites

I agree with you that it is best to keep the SPA in one project and the microservice in a different one but @Marcos V its correct about using a root function

martosoler
  • 423
  • 1
  • 5
  • 10
-6

I've up-voted for the answer from Marcos V. but I can't really accept that as an answer. Primarily because in microservice world you won't create a monolith with all the functionality in one place. You would rather break into manageable chunks and make as many appropriate microservices as necessary/ reasonable for the application.

With the current set-up with firebase-hosting, you have to have the host configuration file in one project alone. Also, the hosting shall be in one project because all the HTML, JS, CSS related to your site would have inter-dependencies and hence are inseparable (at least as of now).

Whereas cloud functions are better deemed as microservices serving a definitive purpose and hence needs to be in separate project/microservice as needed. Which can be deployed easily with the firebase deploy --only functions:YOUR_FN_NAME

Whenever you need to have a mapping added for the new cloud functions microservice, go ahead and make the routing change in the main hosting application and deploy the same. With this approach, we can at least have the back end part being microservices.

Now maintaining database rules in the same hosting application or a separate project is left to the designers who can decide based on their usecase.

Phani
  • 1,851
  • 2
  • 15
  • 28
  • 2
    I think you've misunderstood the difference between services and projects. There's no more need to break microservices into separate projects than there is to write each one on a different laptop. It's not about separation for the sake of it. – Rob Hogan Jan 12 '21 at 22:27
  • @RobHogan I am not advocating separation for the sake of it! When it comes to microservices at least the practice we follow is to differentiate them based on the business function they are addressing and not just the entity they are dealing with. With this we get separation needed for localizing the changes and testing needs when there are updates to the respective business function. This has been faring well with our teams dealing with multiple points of concern and has reduced our testing efforts drastically! Having all back-end logic in one single monolith service can bite you some day! – Phani Jan 15 '21 at 01:17
  • 1
    Separate GCP projects has nothing to do with any of that. GCP can host any number of microservices within one project, usually you only need to split projects for billing reasons, or ease of access management. But if you’ve found a system that works for you, fair enough and good luck with it. – Rob Hogan Jan 16 '21 at 03:13