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.
-
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?
-
Set "Access-Control-Allow-Origin" in
firebase.json
. This works in a deployed cloud function but not in the emulator. -
Import
cors
withonRequest
. This works withonRequest
, not withonCall
. I don’t use HTTP requests to call cloud functions. -
Use
httpsCallableFromURL
instead ofhttpsCallable
. Doug Stevenson has discouraged me from this solution but it sometimes fixes the CORS error. -
New in the 2nd generation cloud functions, you can configure CORS in
onRequest
. I’m usingonCall
, notonRequest
. 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
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.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.
Specify a region.
Create a newly named function that’s just a copy of your previous function, but includes
{cors: true}
Point your front-end code to this newly named function accordingly.
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.