Configuring a reverse-proxy-like Firebase Hosting solution - firebase

This is what I currently have
domain.com -> website A with its own firebase host (domain.firebase.com)
me.domain.com -> website B with its own firebase host (domain-me.firebase.com)
This wasn't hard to set up, just multiple sub-domains redirecting to different Firebase hosts. Now, what I want, is a reverse proxy takes a request and has the option of routing traffic to various servers while keeping the client URL only on the main domain of domain.com. I'm not sure if this is possible specifically with Firebase, as there are tons of NGINX implementation examples, But basically, I want this:
domain.com/ -> website A with its own firebase host (domain.firebase.com)
domain.com/me -> website B with its own firebase host (domain-me.firebase.com)
Firebase has very intricate redirect options, but redirects also overwrites the client URL. So with a redirect, the client will see domain-me.firebase.com instead of domain.com/me, which isn't what I want.
As far as I've figured, I can use Firebase Cloud functions to serve as a middleware, and have it serve either site as needed. However, this introduces a lot of latency as both Cloud functions and Firebase hosted websites have warm-up times from cold starts.
It's totally fine to not give me a complete and detailed answer, I really just want to know if this is possible to begin with, and where I can find relevant resources. Thanks!

To answer my own question and building on Doug's answer of using Cloud Run. There is a quick and painless way to set up a reverse-proxy-like implementation with 2 apps. To do this:
1) Build both apps and have them in separate folders, such as folder A and folder B. You only need the build folders of the apps, you don't need the source code.
2) Create a new Express app at the root of folders A and B.
3) Have Express manage routes using app.get and serve files back using res.sendFile.
4) Containerize the entire Express app following Google's tutorial here, you can ignore the sample application since your new Express app is the application.
5) Upload to Cloud Run as a new service. Keep in mind that while the Google tuts don't specify, you will need to give your user permission to upload to the storage bucket. You will need the command
gsutil iam ch user:[user]:objectViewer gs://us.artifacts.[project-name].appspot.com
Also make sure to switch to the current project using command gcloud config set project [project-name] if you have multiple projects.
6) Use Google domain mapping to map to your root domain, so domain.com.
You must use domain mapping as the URL used by Cloud Run is ephemeral...'cause it's serverless.
Your folder structure should be something like
my-awesome-project
index.js <- Express app and Docker entry point
/package.json <- for your Express app
/A
/B
/Dockerfile
/node_modules
Example router would be
app.get('/me/*', (req,res) =>{
res.sendFile(path.join(__dirname+'/B/index.html'));
});
app.get('/*', (req,res) =>{
res.sendFile(path.join(__dirname+'/A/index.html'));
});
Setting your apps up on subdomains instead works pretty much the same way. Containerize each individual app using step 4, then map each domain separately using Google Domain Mapping.

Integration with Cloud Functions and Cloud Run are pretty much your only options here. There's nothing in the config that will let you proxy your requests directly to other endpoints other than indirectly through HTTP redirects.

Related

Setup Organization/Company subdomain in firebase without setting up DNS

I have an app hosted on firebase that is deployed to my Cloud Domains.
let's say https://example.com
Now, for every custom domain or subdomain I want to add to firebase, I require to manually setup the DNS on of my Cloud Domain with the required records.
But, I would like to create workspace for organization in my app (like for example Jira does doing myOrg.atlassian.com).
So the result would be
organization.example.com
organization2.example.com
Is it possible to allow this without having to manually set DNS for each organization joining our app ?
Would it be possible to dynamically create and setup on firebase and link those subdomain to my cloud domain ?
Thank you
Currently, there is no way to add custom domains automatically. Firebase Hosting doesn’t have such an API through which it can be done. Also I couldn’t find a workaround to dynamically achieve this feature. So the only way to do this is to go to the Firebase Console and set it up as described here. You can go through this similar StackOverFlow thread to know more about it.

Firebase - restrict API key for web application

I just got a mail from the Firebase support that my current API key restrictions for the Firebase API key lead to malfunctions for the Firebase Installation API. Since, I have a web application and not an iOS or an Android app, I´m assuming that this is not a real issue for me at the moment.
However, this got me wondering if I enabled all necessary HTTP referrers (websites) in the Google Cloud Platform to ensure a working environment for my web application. Let´s say my domain is called www.domain.com and my Firebase project is called projectx. I currently have these two entries in the HTTP referrers for the Application restrictions:
www.domain.com/*
projectx.firebaseapp.com/*
Is there anything else I should enable? Because I saw that Firebase also enables multiple domains such as projectx.web.app by default.
It's fairly simple: you need to enable the domains that your app uses.
The two domains you have are the defaults for cases where you have a common domain:
www.yourdomain.com/* is the custom domain that you typically share out with people.
projectx.firebaseapp.com is the default domain generated by Firebase, and is typically also used in sign-in screens (although you can change this).
You may also want to add:
projectx.web.app, which is a newer default domain that Firebase creates. But this is not required, so only add it if you expect to hand it out to folks.
localhost, which is handy for local testing

Accessing firebase hosting files from firebase function triggers

I have 2 repos one for firebase functions and another for static firebase hosting react site. They both use same firebase project.
myfirebaseproject
--- firebase functions
--- firebase hosting
------index.html
Can I read my firebase-hosting files from firebase-function?
let indexHTML = fs.readFileSync('pathToFirebaseHosting/index.html').toString();
One important thing to realize is that Firebase Hosting and Cloud Functions are completely different products, and there is not a simple local path for Hosting files available in a very temporary and transient Cloud Functions instance. Everything is not bundled up together in one place (that wouldn't scale at all).
Since Hosting files are all public, what Frank says is right - just make an HTTP request for what you need. I suggest using the request-promise module instead, as it gives you a promise-based interface that's easier to work with in Cloud Functions.
Please note that if you want to make an outgoing HTTP request like this, you will have to enable billing on your project. Otherwise, Cloud Functions will not allow the request to happen. Also note that the egress and ingress from both Cloud Functions and Hosting will have additional billing. So if you make this request frequently, expect some costs associated with it.
If you just want some static files available in Cloud Function without having to make an external request, simply copy those files in to your functions folder and deploy them all along with your code. You will be able to read them locally, you won't need to enable billing to try it, and you won't incur egress and ingress charges. It'll also be faster.
While there is a REST API for Firebase Hosting API, it is focused on deploying updates, and does not have a call to access the deployed files.
But since all deployed files are publicly accessible, you can read them from the public internet with a regular HTTP request:
request('https://yourproject.firebaseapp.com/index.html', (err, res, body) => {
if (err) { return console.log(err); }
console.log(body);
});

App Engine and Firebase Hosting in One Domain

I have a custom domain (travelbox.id) that connected to Firebase Hosting already. I also have an App Engine application to serve as my API. I want to host the App Engine application on api-dev.travelbox.id. I mapped the custom domain to App Engine following this docs but domain connection to Firebase Hosting stop working. If you access api-dev.travelbox.id it is connected to App Engine. But if you access travelbox.id it doesn't connected to Firebase Hosting.
Is that impossible to achieve what I want?
I had the same issue and contacted Google Cloud support, here's their answer:
App Engine doesn't need to have the A records on the root domain if
you are only serving from a subdomain. App Engine should work
properly for you with just the one CNAME on subdomain.example.com.
I found the solution myself, here you go!
On the fourth step in this docs, i didn't add A records, just add AAAA records. Suprisingly, it works! :D

How to access environment-specific Firebase Function endpoints from Firebase Hosted application?

I have three Firebase projects representing Development, Staging and Production environments hosted on Firebase hosting. Each environment utilizes its own deployed Firebase functions like so:
Dev function endpoint: https://us-central1-my-app-dev.cloudfunctions.net/someFunction
Staging function endpoint: https://us-central1-my-app-staging.cloudfunctions.net/someFunction
Production function endpoint: https://us-central1-my-app.cloudfunctions.net/someFunction
I can't figure out how the static, Firebase-hosted client React application should invoke these functions because the URI endpoints of each changes depending on which environment the code is executing from.
Ideally I could set environment-specific configuration for each Firebase Hosting environment; unfortunately the only way to do this in Firebase Hosting is from within Firebase Functions themselves.
How can I retrieve the environment-specific endpoint for each Firebase Function?
You have a couple options here.
First, you could just configure your React app any way you like. It's necessarily not a bad thing for each system component (backend, frontend) to have its own configuration.
Second, since you're using Firebase Hosting to serve your static content, you can also use it to serve your functions API endpoints. This means that both your static content and API endpoints are all served through the same hostname, which means you no longer have to specify the host when making a request. All the requests can be relative to that host. You can achieve this via Hosting rewrite rules.

Resources