Firebase uses cloudfunctions.net instead of hosting rewrites rules - firebase

I have set up rewrites for named functions in firebase.json but still firebase.functions().httpsCallable() envokes [my-server].cloudfunctions.net/[function-name] instead of [my-server].com/
I am upgrading a current project that has been working fine with cloudfunctions.net, but I would like to limit the domain names being called because of some firewalls blocking that domain.
Reading the guide if thought this addition in firebase.json would be sufficient:
"rewrites": [
{
"source": "/getResponse",
"function": "getResponse"
}]
and then calling the function from my app with:
firebase.functions().httpsCallable('getResponse')
...But that envokes [my-server].cloudfunctions.net/getResponse instead of [my-server].com/getResponse
Opening [my-server].com/getResponse in my browser works, so I figure, there is some sort of explicit setting on firebase.functions() where I can force it to use custom domain?
Thanks you for any help

There is no way to configure the Firebase client SDK for callable functions to invoke anything other than the default URL for the function. If this is somehow important to you, you are free to file a feature request.

Related

Can I view the configuration for the Firebase functions used by my website using Firebase/Google Cloud's UI?

I deployed a new version of a web app that included some new Firebase functions. The new Firebase functions were inaccessible upon deployment.
I was able to find the root cause by familiarity with Firebase's configuration: the function requests were intended to route through the main app domain, and be redirected on the Firebase server to their final destination. (This should have been set up with Firebase's 'rewrites' section of firebase.json, but wasn't.)
A partial view of my rewrites section of firebase.json:
"rewrites": [
{
"source": "/getPlaces",
"function": "getPlaces"
},
...
{
"source": "**",
"destination": "/index.html"
}
]
In plain English, this says, "Firebase server: every time you get a request routing to https://my.app/getPlaces, I want you to not route to that address within my app; I want to invoke my Cloud function instead. Otherwise, route normally."
Yet when I look at the Functions tab of my Firebase console, all I see is this:
Under 'Request', it says https://us-central1-my-app.cloudfunctions.net/getPlaces. That gives me just one of the ways to access my function; the other is https://my.app/getPlaces, as defined in rewrites. I need to know all of the addresses that Firebase will respond to, not just the default one using cloudfunctions.net.
Is it possible to see the entire configuration for the deployed Firebase functions anywhere in the web UI, ie console.firebase.com or console.cloud.google.com, where redirects from rewrites like this can be seen?

can firebase callable functions be used to build an API?

I know that the difference between firebase's cloud callable functions and http functions have been clarified here. However, I still find myself confused in terms of the specific use case of building an API for CRUD operations to the firestore.
I know how to do this with http functions and express, but http functions don't pass a context with user tokens like how callable functions does.
Can/how do you create a router similar to how one would with express with http functions (see below) that allow you to create an API that can handle GET, POST, PUT, and DELETE requests for public and private routes with middleware all within one callable function? Or would you need to create a new callable function for each "route"?
// Define Routes
app.use('/api/users', require('./routes/users'));
app.use('/api/auth', require('./routes/auth'));
app.use('/api/contacts', require('./routes/contacts'));
Can you also hook up the callable function to be called from firebase hosting on particular routes like http functions can (see below)?
"hosting": {
"public": "client/build",
"rewrites": [
{
"source": "/api{,/**}",
"function": "api"
},
{
"source": "**",
"destination": "/index.html"
}
]
},
Or would it just be better to stick with passing an express app through http functions and authenticating by just passing the user token in the request headers?
After checking this Community Answer I saw that this is not possible, as you can see:
HTTP requests to callable functions don't really come "from" a URL. They come from anywhere on the internet. It could be a web site, Android or iOS app, or someone who simply knows the protocol to call the function.
So unless you workaround that by sending the URL in the data of the callable function, it will not work. And even if you do, it just would go against the principle of callable functions, so I would recommend that you use Http Functions for that purpose.

Is it possible to cache Cloud Function invocation result in Firebase Hosting rewrite indepedently of the requested URL?

I'm rewriting multiple paths in Firebase Hosting to a Cloud Function that always returns the same result. I need to invoke the function once, cache its result, and return it for any subsequent requests to any of these paths. However, as the documentation states, the cached content is served based on:
The hostname
The path
The query string
The content of the request headers specified in the Vary header
So, if a different URL is requested, the function will be invoked again. But is there a way to avoid that? Setting the Cache-Control header does prevent the function from invoking again when the same URL is requested, but not when a different one is.
Here is my Hosting and Functions configuration:
firebase.json:
{
"hosting": {
"rewrites": [
{
"source": "**",
"function": "myFunction"
}
]
}
}
functions/index.ts:
import * as functions from "firebase-functions"
export const myFunction = functions.https.onRequest((req, res) => {
res.set("Cache-Control", "public, max-age=31536000")
res.send("This is a Cloud Function.")
})
The caching behavior of Firebase Hosting (and web browsers) is always dependent on the URL path.
There are a couple ways you could try to work around this, depending on your goals:
Use a redirect (for instance, to /) instead of the rewrite. The the cloud function can then serve content only on a known (and cacheable) path.
Serve a static page instead of a cloud function on every path, then have that static page use javascript to call your cloud function on a known, cached path. The initial static page wouldn't be cached, but it should be faster than a function.
The integration between Firebase Hosting and Cloud Functions/Cloud Run allows your (Cloud Functions/Cloud Run) code to control the content of the URL that was requested from Firebase Hosting.
You can modify other hosted files, but will have to call the Firebase Hosting API for this. For an example of this, see How to update a file that I deployed to Firebase Hosting?

Is there a way to normalise differences in request.url when http firebase-functions running under emulator and deploy

For firebase tools 6.9.2:
When using firebase emulators:start --only functions, hosting where the functions are invoked via a hosting rewrite rule, the functions are invoked with different request url path prefixes than if the functions were deployed to the cloud. For example given a firebase.json hosting snippet such as:
{
"target": "myapi",
"public": "./dist/hosting/myapi",
"rewrites": [{
"source": "/api/myapi/*",
"function": "myapi"
}
]
},
When deployed to firebase, the myapi function will be called with a request url that starts with:
/api/myapi/
but if run in the emulator it ends up looking like:
/[firebase-project-id]/[firebase-region]/myapi/api/myapi/
This doesn't make a difference if the function doesn't look at the request path but in my case, the function is a handler for an express (koa) handler with routes so knowing the base path is important.
I've looked to see if anything is available in process.env but only the GCLOUD_PROJECT name and a few FIREBASE_CONFIG params are there.
I could not find any documentation on more advanced control of the rewrite to a function in firebase.json.
I can work around it in testing by setting an environment variable to match the prefix the functions are running at locally and taking it into account during request handling. Unfortunately the request url prefix is not available until after the emulators are started and the function urls are logged.
I am hoping to find a better solution for testing.
This turned out to be a bug and is was resolved for my case in firebase-tools 6.10.0.
https://github.com/firebase/firebase-tools/issues/1279
This related issue was also opened:
https://github.com/firebase/firebase-tools/issues/1312

How to perform domain verification for Firebase functions

I'd like to use Google's Webmaster Tools to add domain verification for my "site", which is entirely made up of Cloud Functions for Firebase:
https://us-central1-<project-id>.cloudfunctions.net/
However I cannot figure out how to do this in a way that would work successfully.
The recommended way is to download and serve an HTML file with a verification key. However, I cannot seem to create a function with a dot.
exports['googleKEY.html'] = functions...
This fails when trying to deploy.
An alternative is to put a meta tag in my "homepage", but that also does not work as I cannot seem to create an index page.
exports[''] = functions...
and
exports['index.html'] = functions...
Also fail.
Is there a way to do this domain verification just through functions? I'd appreciate guidance.
I had the same problem: I wanted to validate my Domain Ownership in the Google Search Console. But the domain is actually a Firebase Cloud Functions domain (https://*.cloudfunctions.net). I found a super easy solution today:
1) When adding a property in Google Search Console, select the method "URL prefix" and enter the url of the function you will create in step 3 (i.e. https://foobar.cloudfunctions.net/googleDomainVerification).
2) Select the method "HTML tag" and copy the meta-tag.
3) Create a https function that you push on Firebase Cloud Function. Don't forget to copy your meta-tag from step 2:
exports.googleDomainVerification = functions.https.onRequest((req, res) => {
res.status(200).send('<!DOCTYPE html> <html> <head> YOUR_META_TAG_HERE </head> <body> </body> </html>')
})
4) Wait a minute then press "Verify" on the Google Search Console
That's it. Everything should work now :)
So... I think I finally may have a solution.
There is no direct way to verify a Firebase Functions domain (https://*.cloudfunctions.net) BUT verifying Firebase Hosting domain (https://*.firebaseapp.com) is easy (using verification file). So let's start with that.
There is a config option in Hosting to setup url rewrite to serve a Function. (Documented here)
This is a modified example config from the link above, opening url https://<your-project-id>.firebaseapp.com/covertFnBigben to invoke Function bigben.
{
"hosting": {
"public": "public",
// Add the following rewrites section *within* "hosting"
"rewrites": [
{
"source": "/covertFnBigben", "function": "bigben"
}
]
}
}
So after successfull verification of your Firebase Hosting domain you can use that domain to call Firebase Functions.

Resources