1
votes

I built a small web application (www.suntax.de) with vuejs and hosted on Google Firebase. I use the Firebase Hosting, Database and Functions. I use Functions to do some calculation on the backend.

Everything is running now, but I had some trouble getting there and some things I would like to improve regarding my workflow. Thus, I would like to explain you what I did and where I struggle now.

First I set up the vuejs applicationd deployed it to firebase. I added my custom domain and everything was doing fine. Later I implemented the cloud function and want to make a call from my vuejs app. After firebase deploy, I can call this function in the browser and it just works fine: https://us-central1-suntax-6d0ea.cloudfunctions.net/calcEEGcompensation?year=2013&month=1&size=10

Now I thought, that I just call the URL of the function from my vuejs app. But then I got the following error message: [Error] Origin * is not allowed by Access-Control-Allow-Origin.

I was then reading that I had to add a rewritesection in the firebase.json:

Now my firebase.json looks like this:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    // Add the following rewrites section *within* "hosting"
   "rewrites": [ {
      "source": "/calcEEGcompensation", "function": "calcEEGcompensation"
    } ]
  }
}

Now I was able to call my firebase function with the following URL: https://www.suntax.de/calcEEGcompensation?year=2013&month=1&size=10

After integrating the above URL in my vuejs application, the application is running fine after deployment to firebase server.

As I want to keep improving the application, I would like to test everything locally before deploying.

I know that I can run firebase hosting and functions locally by: firebase serve --only functions,hosting

However, now my application has the hard coded call to my function https://www.suntax.de/calcEEGcompensation?year=2013&month=1&size=10 and this again leads to the error [Error] Origin * is not allowed by Access-Control-Allow-Origin.

But also changing the URL to the local function http://localhost:5001/suntax-6d0ea/us-central1/calcEEGcompensation?year=2013&month=1&size=10 leads to the error message [Error] Origin * is not allowed by Access-Control-Allow-Origin.

Some further reading brought me to the solution with cors. So I changed my function to:

const functions = require('firebase-functions');
const cors = require('cors')({origin: true});

exports.calcEEGcompensation = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        const yearOfCommissioning = req.query.year;
        const monthOfCommissioning = req.query.month;
        const pvsystemsize = req.query.size;

        ...

        res.send("hello");
    });
});

This helped and everything works now: - The deployed application is still running fine. - I can run the application locally while calling the local function as well as the deployed function. I just have to change the URL of the function.

But this is now my question: Can I solve this issue in a better way? If I test the vuejs application and the function locally, I have to change the function URL before deployment. And then I have to change it back while testing locally. I was not able to test my application and function locally without cors.

My ideal solution would be to have a setup, that can be fully tested locally and which can be easily deployed with firebase deploy without any changes of URLs. Is this possible?

Thanks and best regards, Christoph

2

2 Answers

2
votes

I found the solution which is pretty simple and does exactly what I want. I have no idea why I did not figure it out before. Here is what I did:

I just call the relative URL from my firebase hosting:

calcEEGcompensation?year=2013&month=1&size=10

and everything works fine if the rewrites are properly set in firebase.json:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    // Add the following rewrites section *within* "hosting"
   "rewrites": [ {
      "source": "/calcEEGcompensation", "function": "calcEEGcompensation"
    } ]
  }
}

After setting up everything like this, I can just execute firebase serve --only functions,hosting and I can test everything locally. After executing firebase deploy, everything runs smoothly on the server.

I do not need cors.

Thanks @wonsuc for your answers.

1
votes

Update(For Firebase Hosting):
Currently there is no workaround you can solve it with Firebase Hosting SDK.
But there is alternative way you can achieve this.

Try below code in your hosting source.

if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
    console.log('It's a local server!');
}

In my opinion, these are best way to check dev environment currently.
Therefore you should use location.hostname in your Firebase Hosting, and server.address() in Cloud Functions.

And define your Functions end point with constant variable.

const DEBUG = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
const FUNCTIONS_ENDPOINT_DEV = 'http://localhost:5001/';
const FUNCTIONS_ENDPOINT_PRD = 'https://us-central1-something.cloudfunctions.net/';
const FUNCTIONS_URL_CALC = 'calcEEGcompensation?year=2013&month=1&size=10';

var endpoint;
if (DEBUG) {
    endpoint = FUNCTIONS_ENDPOINT_DEV + FUNCTIONS_URL_CALC;
} else {
    endpoint = FUNCTIONS_ENDPOINT_PRD + FUNCTIONS_URL_CALC;
}

Original answer(For Cloud Functions for Firebase):
Have you tried node.js net module's server.address() function?
This method will tell you if your functions code is running on localhost or real deployed server.

For examples, you can use like this.

const server = app.listen(function() {
    let host = server.address().address;
    let port = server.address().port;

    if (!host || host === '::') {
        host = 'localhost:';
    }

    console.log('Server is running on %s%s', host, port);
});