Home > Software design >  Firebase Cloud Function does not execute when called from web client
Firebase Cloud Function does not execute when called from web client

Time:10-27

I have been trying to invoke a Firebase Cloud Function without success.

The sucessfully deployed function is:

functions.logger.info("Hello logs!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); // this logs
exports.createAuthToken = functions.https.onRequest((request, response) => {
    functions.logger.info("Hello logs!", { structuredData: true }); // this doesn't log
    response.send("Hello from Firebase!");
});

The first line of the code shows up in the logs, but the third line doesn't when called from an external web client. When I test / run the function from the Google Cloud console, both logs show up.

In the web client, I get the error message:

Access to fetch at 'https://us-central1-my-project.cloudfunctions.net/create-auth-aoken?ot-auth-code=xyz' from origin 'https://my-client-url' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

So I resolve the cors issue as the documentation suggests like this:

const cors = require('cors')({
    origin: true,
});

functions.logger.info("Hello logs!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); // this logs
exports.createAuthToken = functions.https.onRequest((request, response) => {
    cors(request, response, () => {
        functions.logger.info("Hello logs >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>!", { structuredData: true }); // this still doesn't 
        response.send("Hello from Firebase!");
    });
});

I am calling the function like this: https://us-central1-my-project.cloudfunctions.net/create-auth-token?ot-auth-code=${code}&id-token=${token} I have tried resolving the cors problem in every way I can possibly find, but it will not work.

How should I configure this exactly to make it work?

CodePudding user response:

This could be addressed in several ways, one is by sending your request to a proxy server. Your request would look like this:

https://cors-anywhere.herokuapp.com/https://joke-api-strict-cors.appspot.com/jokes/random

This is an easy solution and works for dev environmeent as it is implemented on browser-to-server communication. The downsides are that your request may take a while to receive a response as high latency makes it appear to be slow, and may not be not ideal for production environment.

Another option is to try using CORS with Express. Check the Node.js code below:

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/jokes/random', (req, res) => {
  request(
    { url: 'https://joke-api-strict-cors.appspot.com/jokes/random' },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).json({ type: 'error', message: err.message });
      }

      res.json(JSON.parse(body));
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

This one would act as a middleware to apply Access-Control-Allow-Origin: * header to every request from the server. Same-origin policy will not step in to block the request even though the domains are different.

You may check the full documentations on how to fix CORS error:

CodePudding user response:

It certainly is possible; I use this solution for firebase which I rolled myself to simply respond to CORS requests:

 function MakeCORSRequest(func) {
  return functions.https.onRequest((req, res) => {
    res.set('Access-Control-Allow-Origin', '*');
    if (req.method === 'OPTIONS') {
      // Send response to OPTIONS requests
      res.set('Access-Control-Allow-Methods', 'GET, POST');
      res.set('Access-Control-Allow-Headers', 'Content-Type');
      res.set('Access-Control-Max-Age', '3600');
      res.status(204).send('');
    } else {
      return func(req, res);
    }
  });
}

All it does is intercept CORS OPTIONS request and respond with 'Yes you can' - other requests (such as GET/POST) it just passes forward to the given function. It can be used to wrap your endpoint and respond correctly to CORS calls coming from the browser.

So the actual end point is expressed like this:

exports.myFunction = MakeCORSRequest(async (req, response) => {
   //Do your stuff here
})
  • Related