skip to Main Content

I’m trying the 2nd generation Cloud Functions for Firebase. I have makeUppercase() firing with onDocumentCreated(). Now I’m trying to get an Angular app to call a callable cloud function.

index.ts

import * as logger from "firebase-functions/logger";
import { onCall } from "firebase-functions/v2/https";
import { defineSecret } from "firebase-functions/params";
const apiKey = defineSecret("12345abcde");
import { initializeApp } from "firebase-admin/app";
initializeApp();

export const CallUppercaseMe2ndGen = onCall({ secrets: [apiKey] }, (request) => {
    if (request.data != undefined) {
        if (request.auth != undefined) {
            const text = request.data.text;
            const uid = request.auth.uid;
            logger.log("Uppercasing", uid, text);
            const uppercase = text.toUpperCase();
            return uppercase;
        } else {
            return null;
        }
    } else {
        return null;
    }
});

angular.component.ts

async callMe() {
    const upperCaseMe = httpsCallable(this.functions, 'CallUppercaseMe2ndGen');
    // const upperCaseMe = httpsCallableFromURL(this.functions, 'http://localhost:5001/my-project/us-central1/CallUppercaseMe2ndGen');
    // const upperCaseMe = httpsCallableFromURL(this.functions, 'https://us-central1-my-project.cloudfunctions.net/CallUppercaseMe2ndGen');
    upperCaseMe({
      text: 'hello world',
    })
      .then((result) => {
        console.log(result)
      })
      .catch((error) => {
        console.error(error);
      });
}

This throws a CORS error:

Access to fetch at 'https://us-central1/my-project.cloudfunctions.net/CallUppercaseMe2ndGen' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.

I know a few ways to fix a CORS error in a cloud function.

  1. Use an IAM service account. This is my preference in 1st generation cloud functions. In the 2nd generation cloud function I put in my API key. I suspect the problem is that I need to put in more than the API key to connect a cloud function to an IAM service account. How do I do this?

  2. Set "Access-Control-Allow-Origin" in firebase.json. This works in a deployed cloud function but not in the emulator.

  3. Import cors with onRequest. This works with onRequest, not with onCall. I don’t use HTTP requests to call cloud functions.

  4. Use httpsCallableFromURL instead of httpsCallable. Doug Stevenson has discouraged me from this solution but it sometimes fixes the CORS error.

  5. New in the 2nd generation cloud functions, you can configure CORS in onRequest. I’m using onCall, not onRequest. I tried replacing the parameter {secrets: [apiKey]} with {cors: true} but that didn’t help.

On request I’ll show code for each of these five solutions.

2

Answers


  1. Chosen as BEST ANSWER

    I deployed my functions to the Firebase cloud, they worked the first time. It's just the emulator that throws CORS errors with onCall functions. I'm pretty sure I remember the same problem with 1st generation cloud functions.

    I tried the same function with { secrets: [apiKey], with { cors: true }, and with neither. All three worked.


  2. Had the same problem. I’m not sure which one of these actions (or all of them) solved the problem, but here’s what I did.

    1. Specify a region.

      import { setGlobalOptions } from 'firebase-functions/v2'
      
      // locate all functions closest to users
      setGlobalOptions({ region: "us-central1" })
      
    2. Create a newly named function that’s just a copy of your previous function, but includes {cors: true}

      export const myFunctionCopy = onCall({ cors: true }, async (request) => 
      {
      ...
      }
      
    3. Point your front-end code to this newly named function accordingly.

    4. Deploy

    I suspect there’s some sort of cache / propagation issue going on with Google’s backend. Renaming the function (as opposed to just updating the code) avoids this.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search