Rerouting Firebase Hosting to Express Cloud Functions - node.js

I can't seem to configure routes to connect firebase hosting to my cloud function express app. I tried to setup as shown here but the behaviour seems to be different. I can't seem to figure out what I am doing wrong. Please send help, I'm going insane.
index.js
const functions = require("firebase-functions");
const app = require('./app');
exports.api = functions.https.onRequest(app);
app.js
const app = express();
// ...
app.use(cors());
app.use('/params', paramsRoutes);
module.exports = app;
firebase.json
{
"hosting": {
// ...
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
// ...
]
}
}

There is appropriate documentation that lists your requirement of hosting the Cloud Functions in Firebase Hosting using a custom domain.
Make sure that you have the latest version of the Firebase CLI and
that you've initialized Firebase Hosting.
Initialize Cloud Functions by running the following command from the
root of your project directory: firebase init functions
Also as per documentationwe can use rewrites to serve requests for a specific firebase hosting URL to a function. To do that you need to use "/api". You don't have to add the entire URL because you are redirecting from firebase hosting. So, when you add "/api" you are indicating to redirect requests going to "PROJECT_ID.web.app/api and PROJECT_ID.firebaseapp.com/api" to the function you specified.
If you want redirect every single URL to your host to an express app in Cloud Functions, you will need to do the following:
Make sure there is no index.html in your public hosting folder
(otherwise it will always be served with the path /).
Your Express routes need to exactly match the incoming URL, not just
the wildcard part.
You can read more in the docs or follow this medium post for more details.
Check these links for similar implementation:
How to write redirect rules for Firebase hosting and express
How to redirect all server requests to a function in firebase

Related

Firebase Functions With Express Failed to decode param %CO

There is a solution to this error without the use of Firebase here when using app.listen(8080) however this does not work while serving in cloud functions with exports.app = functions.https.onRequest(app)
Here is a simple reproduction code
const app = express();
app.get('**', (req, res) => res.send('working'));
app.use((err, req, res, next) => res.redirect('/404'));
exports.app = functions.https.onRequest(app) // doesnt work
// app.listen(5000) // works
How do you go about catching this error in firebase functions? I would like the redirect to work.
firebase test: firebase serve --only functions
express serve: node index.js
URL to test: http://localhost:5000/%CO
Note that the additional %CO is the one that cannot be decoded by express. This error is caught while serving with the express method but not with the firebase functions method.
As this seems like a bug, I have also created an issue here on github incase I find no workaround on it.
Try changing the name of app in exports.
exports.newApp = functions.https.onRequest(app)
According to the documentation, the correct way of using an Express app with Firebase Functions is to pass the application to a Function like:
// Expose Express API as a single Cloud Function:
exports.app = functions.https.onRequest(app);
Listening to a port for requests does not apply when running through Firebase Functions. As for how to catch errors when passing your app to a function, it’s done in the same way as the question you referenced as far as I have reviewed. You can catch errors by using Express middleware while using Cloud Functions.
Moreover, implementing redirects with Firebase Functions is explained in this related question, which makes use of the documentation to configure how to redirect by modifying the firebase.json file.

Getting started with parse server and node.js basics

I have installed bitnami parse server from the AWS market place to provide the backend for an iOS app. In the iOS app the API is configured under http://myURL.com/parse and when I go to what I thought would be the homepage, http://myURL.com, it instead redirects me to the parse dashboard located at http://myURL.com/apps. I would like to have http://myURL.com serve a homepage for my app instead of redirecting to the parse dashboard so that a web application can be constructed that shares the same data the app uses. This is my first project using node.js so I am hoping someone could point me in the right direction on a couple of topics. My previous web application work was always on a LAMP stack so I am curious:
Am I correct to assume that the parse backend that iOS uses can also be the backend for a web application accessed through a browser?
When I analyze the code in server.js at /home/bitnami/apps/parse/htdocs I don't see a function that is redirecting to myURL.com/apps, is there a different area I should be focussed on to understand how myURL.com gets redirected to the apps folder?
I noticed that a folder exists at /home/binami/apps/rockmongo with installation instructions of php scripts, can my AWS instance run php AND the node.js or will installing a LAMP stack interfere with the node.js stack?
I am sure there is some great documentation and/or tutorials on this, can you help me get started by providing the correct way to phrase google searches or even better any links to tutorials themselves?
For context my iOS lets users log on and lets them upload images to parse server classes, I simply want to let the users log on and upload an image from a web browser using the same parse server which has the user/file classes.
For Reference below is the server.js which appears to somehow be directing requests from myURL.com to myURL.com/apps:
require('dotenv').config();
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var app = express();
// Specify the connection string for your mongodb database
// and the location to your Parse cloud code
var api = new ParseServer({
databaseURI: "mongodb://root:9dh********#127.0.0.1:27017/bitnami_parse",
cloud: "./node_modules/parse-server/lib/cloud-code/Parse.Cloud.js",
appId: "19defd7********",
masterKey: "cd8********",
fileKey: "3bce6********",
serverURL: "http://54.**.**.**:80/parse",
filesAdapter: {
"module": "#parse/s3-files-adapter",
"options": {
"bucket": process.env.S3_BUCKET,
}
},
});
// Serve the Parse API on the /parse URL prefix
app.use('/parse', api);
var port = 1337;
app.listen(port, function() {
console.log('parse-server running on port ' + port);
});
//Parse Dashboard
var ParseDashboard = require('parse-dashboard');
var dashboard = new ParseDashboard({
apps: [
{
appName: "My Bitnami Parse API",
appId: "19defd7********",
masterKey: "cd8d*******",
fileKey: "3bce6********",
production: true,
serverURL: "http://54.**.**.**:80/parse"
}
],
users: [
{
user: process.env.ADMIN_USER,
pass: process.env.ADMIN_PASSWORD
}
], useEncryptedPasswords: true
});
var allowInsecureHTTP = true;
// Serve the Parse Dashboard on the /parsedashboard URL prefix
app.use('/', dashboard);
var portdash = 4040;
app.listen(portdash, function() {
console.log('parse-dashboard running on port ' + portdash);
});
Mount point for Parse Dashboard is definded in this line:
app.use('/', dashboard);
When you want to use a separate mount point for dashboard you can do this:
app.use('/dashboard', dashboard);
After changing if you hit http://myURL.com/dashboard it will load the dashboard in /dashboard/apps. '/apps' endpoint is handled by parse dashboard itself.
Now if you want to load your website in root route (/) or the http://myURL.com, you need to create another route (assuming you want to serve a static site for now)
app.use('/public', express.static(path.join(__dirname, '/public'), {
etag: true
}));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/public/index.html'));
});
To serve a static site you need to create a folder from where you will server the static site. In this case, I created a folder named as public and place all of my html,css,js there. Now I need to specify the static folder in express. That's what I did in the first line. After that, I simply serve the index.html by creating a 'GET' route.
You can do a lot of other things too like creating APIs or serve a dynamic website as well as using parse server. But to do that you must understand express framework with nodejs first.
Update:
Parse API and Dashboard are two separate things. You can run only parse-server without dashboard and vice-versa. In your code, you mount the parse-server in /parse endpoint. Look at this line
app.use('/parse', api);
So now the parse-server is available in /parse endpoint. You can change it to anything. Make separate endpoints for both parse-server and dashboard.

How to host a static landpage and react on the same node server?

Currently, I have a static landing page hosted on firebase on the url "mycompany.com" (not the actual URL).
My node server (using express) runs on heroku and it contains my backend API and my react frontend (using react-router). In order to make everything run, I had to point this to a subdomain: app.mycompany.com
What I really wanted to do, was to have my landing page on "/" and have that to be the default redirect, all hosted in my node server (without having to have two servers and point to a subdomain).
I'm struggling to understand how could I set up this, or if have to change something to make this work.
Thanks in advance!
If you make a static build of your react app you can serve this build folder along with your static landing page. You'll still have to specify the path where you want your app traffic to go:
const express = require('express');
const app = express();
const staticLandingPage = express.static(path.join(__dirname, "./path/to/landingpage"));
const reactApp = express.static(path.join(__dirname, "./path/to/reactBuild"));
app.use("/", staticLandingPage);
app.use("/app", reactApp);

How to create a node based server to serve REST API and also deploy the application.

I am new to nodeJS server area, need help in understanding how to work with REST API (using express) and deploy the angular application over a singe node server and same ports.
By deploying i want to understand if user hit below url http://localhost:8000/<page_name> then the specified page should open.
And is user hit below url using get or post request
http://localhost:8000/api/<api_name> then a json or a text will be returned.
How to run both the thing over a single node server.
Lets assume, you have all your static files in the /public folder of you app. Generally spoken, if you are using express.static, you should also get your index.html because this is handled by default for each directory.
In your case, as you are using Angular, the routing is handled from the client side (SPA). You should only have one single index.html after building your Angular app. All files from your dist folder should then be placed into your /public folder. Then you need to make sure, that initial file serving provides your index.html like so:
In this example static files are served first, then your API and if nothing is found, you are getting back you index file.
const express = require('express');
const app = express();
// serve static files
app.static(__dirname + '/public'));
// serve your API
app.get('/api/welcome', function (req, res) {
res.send('Welcome');
});
// fallback routing (server side handling)
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + ‘/public/index.html‘
});
app.listen(3000);
Next time please make sure, to give all necessary information in your question ;-)
With the help from Sebastian, so far I can find a solution but its not working when i am hitting URL for different pages.
const express = require('express');
const app = express();
app.use(express.static('public'))
Please provide your suggestions.

Express app using firebase functions

Im trying to run an Express app into firebase, i'm following the steps of this official video:
Node.js apps on Firebase hosting crash course
My Express app is actually running on this URL
http://localhost:5001/my-app/us-central1/app/test
But on the video, the demostration is running on this url
http://localhost:5000/test
So, i'm really confused about this, i'been made everything as the tutorial shows
this is my code on functions/index.js
const functions = require('firebase-functions');
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
res.send(`Well if i'm reading this the app is working`)
})
exports.app = functions.https.onRequest(app)
And this is firebase.json
{
"hosting": {
"public": "public",
"rewrite":[{
"source": "/test",
"function": "app"
}],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
What i'm doing wrong? if i enter to localhost:5000 i just get the public static index.html, i just want to control the app by myself.
I hope you can give me a little help to get documented, thanks!
The issue here is that Firebase Hosting will serve static content that matches any paths before using any rewrites. If you want to control a path with Cloud Functions, you will have to make sure that there is no static content that matches the path.
For single page apps in particular, it's critical to remove index.html, as that will always be served as static content.

Resources