Asool
Asool

Reputation: 14209

Trying to connect to firebase function from React app - cors issue?

I'm creating a react application. I have code like this

async componentDidMount() {
    const questions = await axios.get('getQuestions');
    console.log(questions);
}

(I have a baseURL set up for axios and all, so the URL is correct)

I created a firebase function as follows (typescript)

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();

exports.getQuestions = functions.https.onRequest(async (request, response) => {
    const questions = [];
    const querySnapshot = await db.collection('questions').get();
    const documents = querySnapshot.docs;
    documents.forEach(doc => {
        questions.push(doc.data());
    });
    response.json({ questions: questions });
});

Now when I build and run firebase deploy --only functions, and then visit the url directly, everything works. I see my questions.

But in the react app, I get the following error

Access to XMLHttpRequest at '.../getQuestions' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

After some googling, I tried

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();

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

exports.getQuestions = functions.https.onRequest(
    cors(async (request, response) => {
        const questions = [];
        const querySnapshot = await db.collection('questions').get();
        const documents = querySnapshot.docs;
        documents.forEach(doc => {
            questions.push(doc.data());
        });
        response.json({ questions: questions });
    })
);

But that just gave me an error when I ran firebase deploy --only functions

✔ functions: Finished running predeploy script. i functions: ensuring necessary APIs are enabled... ✔ functions: all necessary APIs are enabled i functions: preparing functions directory for uploading...

Error: Error occurred while parsing your function triggers.

TypeError: Cannot read property 'origin' of undefined at ...

And tbh, even if this command worked, I don't know if it is the correct solution

Upvotes: 2

Views: 3427

Answers (2)

Joel Jerushan
Joel Jerushan

Reputation: 655

This answer will help someone who facing cors error.

01 - Create Firebase Function Called BtnTrigger (You can name whatever you like)

// Include Firebase Function 
const functions =  require('firebase-functions');

// Include Firebase Admin SDK
const admin =  require('firebase-admin');
admin.initializeApp();

//cors setup include it before you do this 
//run npm install cors if its not in package.json file
const cors =  require('cors');

//set origin true
const corsHandler =  cors({ origin: true });

//firebase function 
export  const BtnTrigger =  functions.https.onRequest((request, response) => {
    corsHandler(request, response, async () => {
    //response.send("test");
    response.status(200).json({ data: request.body });
   });
});

Then Run firebase deploy --only functions this will create your firebase function. if you need you can check it from your Firebase Console.

02 - Create Function Trigger from your Application from your application code

i used same BtnTrigger name to understand it properly you can change variable here but httpsCallable params should same as your Firebase Function Name you created.

var BtnTrigger =firebase.functions().httpsCallable('BtnTrigger');
BtnTrigger({ key: value }).then(function(result) {
    // Read result of the Cloud Function.
    console.log(result.data)
    // this will log what you have sent from Application BtnTrigger 
    // { key: value}
});

Don't Forget to import 'firebase/functions' from your Application Code

Upvotes: 0

Asool
Asool

Reputation: 14209

Got it :) I was doing something silly

import * as cors from 'cors';
const corsHandler = cors({ origin: true });

exports.getQuestions = functions.https.onRequest(async (request, response) => {
    corsHandler(request, response, async () => {
        const questions = [];
        const querySnapshot = await db.collection('questions').get();
        const documents = querySnapshot.docs;
        documents.forEach(doc => {
            questions.push(doc.data());
        });
        response.status(200).json({ questions: questions });
    });
});

Upvotes: 4

Related Questions