Michel
Michel

Reputation: 11761

Calling a cloud function from a firebase web app

I am trying to make use of a cloud function in a firebase web app and am facing some problems. If someone can point out some settings or other things I may be missing that would be helpful.

First here is the relevant code for the cloud function:

exports.myFunc = functions.https.onRequest(function(req, resp) {
  const from = req.body.sender;
  admin.auth().getUserByEmail(from)
      .then(function(userRecord) {
       console.log("Successfully fetched user data:", userRecord.toJSON());
      })
      .catch(function(error) {
        console.log("Error fetching user data:", error);
      });
});

Second here is the code in the web app calling the cloud function:

var xhr = new XMLHttpRequest();
xhr.open("POST", "https://us-central1-myapp.cloudfunctions.net/myFunc", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    from: "[email protected]"
}));
xhr.onload = function() {
    var data = JSON.parse(this.responseText);
    console.log('THE DATA:',data);
};

And finally this is the message I see in the web console after firing the call by hitting a button:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://us-central1-myapp.cloudfunctions.net/myFunc. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 408.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://us-central1-myapp.cloudfunctions.net/myFunc. (Reason: CORS request did not succeed). Status code: (null).

There is nothing relevant in the server logs at this point.

Upvotes: 0

Views: 1007

Answers (3)

Michel
Michel

Reputation: 11761

After much time spent I found out that if I write my cloud function this way, it works:

exports.myFunc = functions.https.onRequest(function(req, resp) {
  corsHandler(req, resp, async () => {
    const from = String(req.query.from); // Through the URL.
    admin.auth().getUserByEmail(from)
        .then(function(userRecord) {
          console.log("Successfully fetched user data:", 
                      userRecord.toJSON());
        })
        .catch(function(error) {
          console.log("Error fetching user data:", error);
        });
  });
});

Upvotes: 0

abraham
abraham

Reputation: 47923

Use HTTPS Callable function to let Firebase handle the request/response.

// function
exports.myFunc = functions.https.onCall((data, context) => {
  const from = data.sender;
  return admin.auth().getUserByEmail(from)
      .then(function(userRecord) {
       console.log("Successfully fetched user data:", userRecord.toJSON());
       return { user: userRecord.toJSON() }
      })
      .catch(function(error) {
        console.log("Error fetching user data:", error);
      });
});
// web
 import { initializeApp } from 'firebase/app';
 import { getFunctions } from 'firebase/functions';

const app = initializeApp({
     // ...
   });
const functions = getFunctions(app);
const myFunc = httpsCallable(functions, 'myFunc');
myFunc({ sender: '[email protected]' })
  .then((result) => {
    const data = result.data;
    console.log(data.user);
  });

Upvotes: 0

YTGS
YTGS

Reputation: 175

You need to install cors and use it something like this,

import * as cors from "cors"; 
const corsHandler = cors({ origin: true });
 
// allow cors in http function 
exports.myFunc = functions.https.onRequest((req, resp) => { 
      corsHandler(req, res, async () => { 
              // your method body 
      });
});

Upvotes: 2

Related Questions