Avoid CORS preflight for Firebase callable function
After combing through Firebase docs and JS SDK source I've decided this is not possible without using/overriding private APIs.
The solution I've used is to replicate the JS SDK code but specifying a URL that goes via Firebase Hosting so it's on the same domain as my app.
Same Cloud Function, same app code, no CORS preflight đđŒ
- Create a normal Firebase Callable Cloud Function
- Add a rewrite to
firebase.json
{
...
"hosting": {
...
"rewrites": [
{
"source": "myFunction",
"function": "myFunction"
}
]
}
}
- Instead of calling it with
firebase.functions().httpsCallable('myFunction')
send a POST request to your own new URL
const token = await firebase.auth().currentUser.getIdToken()
const response = await fetch(
'https://myapp.web.app/myFunction',
{
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + token
},
method: 'post',
body: JSON.stringify({ data })
}
)
Now the URL is within your domain so no CORS issues
For users who have the CORS preflight problem with the firebase local emulator, if you're using Webpack or Vue (vue-cli
), you can resolve the situation with a proxy:
my-firebase-initialize-file.js (client side)
firebase.initializeApp(...); // your config
firebase.functions().useFunctionsEmulator('http://localhost:1234/api'); // Client url + /api
webpack.config.js or vue.config.js (client side, at the root, next to package.json
)
module.exports = {
devServer: {
proxy: {
"^/api": {
target: "http://localhost:5001", // Emulator's url
pathRewrite: {
"^/api": ""
},
ws: true,
changeOrigin: true
}
}
}
};
Now every http://localhost:1234/api
will be proxied to http://localhost:5001
, so
you don't need CORS preflight anymore.
Of course you need to adapt these local urls to your case.