0

Let's say I want a cloud function to have a path such as:

https://[MY_DOMAIN]/login/change_password

How do I achieve the "login/" part in Node?

Or even something more complicated such as

login/admin/get_data

?

I tried using

module.exports = {
    "login/change_password" = [function]
}

But I got an error when deploying and "change_password" was omitted, so it only tried to deploy a "login" function.

Another thing I tried was using express routers but that resulted in only deploying a single function, which routed to the right path (e.g. myfunction/login/change_password) which is problematic as I have to deploy in bulk every time and can't deploy a function individually.

RedKnight91
  • 340
  • 3
  • 17

2 Answers2

3

If you want the flexibility to define routes (paths) that are more complex than just the name of the function, you should provide an Express app to Cloud Functions. The express app can define routes that add path components to the base name of the function you export from index.js. This is discussed in the documentation for HTTP functions. For example:

const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/some/other/path', (req, res) => { ... });
exports.foo = functions.https.onRequest(app);

In that case, all your paths will hang off of the path prefix "foo".

There is also an official samples illustrating use of Express apps: https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Thank you Doug, I noted I tried (and am actually currently using) this approach in my edit to the question. The problem I have with this is that it mushes all the App's routes to a single function, which is slow for deploying if I just made changes to a single route. Ideally each route would be a function, but this would mean setting up several express apps? – RedKnight91 Nov 21 '19 at 23:41
  • What's slow about it? Deploying a single function with a single Express app (even if multiple routes) is almost always going to be faster than deploying multiple functions, each with its own app (which you could do, but I don't think it's worthwhile). In fact, I don't think that adding Express to a function is going to slow the deployment down much at all. Curious to see your performance numbers that show significant slowdown. – Doug Stevenson Nov 22 '19 at 00:17
  • I have a test project where I created several functions the "regular" way (exports.date = functions.https.onRequest((req, res) => {   // ... });) and it's faster (sorry don't have figured handy) than deploy my project with only one function routing to different routes. Let's say I make a change in the twitter/login route, I don't want to redeploy the main function with all its routes, I want to only redeploy the twitter/login function, but in my case I can't unless there's something I'm missing – RedKnight91 Nov 22 '19 at 07:57
  • Please post a new question with your followup concerns, explaining what isn't working the way you expect, or how you're blocking on implementing what you want. – Doug Stevenson Nov 22 '19 at 08:17
  • Actually I perfected my search terms based on your input and found an answer on Stack Overflow (which you also answered to by the way), so I am detailing the answer and my final approach. Thanks again! – RedKnight91 Nov 22 '19 at 09:20
2

Thanks to the discussion with Doug Stevenson I was able to better phrase my question and find that it was already answered in this question.

So this would be an example of my implementation:

const functions = require('firebase-functions');
const express = require('express');
const login = require('./login.js');
const edit_data = require('./edit-data.js');

const login_app = express();
login_app.use('/get_uuid', login.getUUID);
login_app.use('/get_credentials', login.getCredentials);
login_app.use('/authorize', login.authorize);

const edit_data_app = express();
edit_data_app.use('/set_data', edit_data.setData);
edit_data_app.use('/get_data', edit_data.getData);
edit_data_app.use('/update_data', edit_data.updateData);
edit_data_app.use('/remove_data', edit_data.removeData);

exports.login = functions.https.onRequest(login_app);
exports.edit_data = functions.https.onRequest(edit_data_app);

My takeaway from this is that there is a one-to-one Express app to HTTP function correspondence, so if I wanted to have 3 different functions I would need 3 Express apps.

A good balance is to have one app and one function per module (as shown above), which also means you can separate out your functions across several modules/javascript files for ease of maintenance.

In the above example, we can then trigger those HTTP functions using

https://[DOMAIN]/login/get_uuid/

or, from the firebase functions shell

login.get("/get_uuid")

RedKnight91
  • 340
  • 3
  • 17