Call Cloud Functions From Web/JavaScript (Axios or Firebase)

May 24, 2019

There are 2 main approaches:

NOTE: Need to solve CORS issues if the domain for cloud functions and website differ.

Axios Ajax Call

Add JavaScript library

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

or

Use npm package

npm install axios
import axios from 'axios';

axios({
  method: 'post',
  url: '/functions/test_message_json', // or https://us-central1-PROJECT_NAME.cloudfunctions.net/test_message_json
  data: {
    message: 'Hello'
  }
})
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.log(error);
  });

Sample cloud functions.

const functions = require('firebase-functions');

exports.test_message_json = functions.https.onRequest((request, response) => {
  const message = request.body.message;
  response.status(200).json({
    message: message
  });
});

Cloud Functions for Firebase client SDK

Add Firebase to Web app

Add JavaScript library

<script src="https://www.gstatic.com/firebasejs/6.0.2/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.0.2/firebase-functions.js"></script>

or

Use npm package

npm install firebase --save

NOTE: I believe firebase-js-sdk is used for web (as in browser client) while firebase-functions is meant for Node.js (as in server and cloud functions).

// https://firebase.google.com/docs/functions/callable
import firebase from 'firebase/app';
import 'firebase/functions';
const firebaseConfig = {
  apiKey: "AIza...",
  authDomain: "PROJECT_NAME.firebaseapp.com",
  databaseURL: "https://PROJECT_NAME.firebaseio.com",
  projectId: "PROJECT_NAME",
  storageBucket: "PROJECT_NAME.appspot.com",
  messagingSenderId: "2401...",
  appId: "1:2401..."
};
const app = firebase.initializeApp(firebaseConfig);
const functions = firebase.functions();

// functions.useFunctionsEmulator('/functions');
const testMessage = functions.httpsCallable('test_message_firebase_json');
testMessage({message: 'Hello'}).then((result) => {
  console.log(result.data);
}).catch((error) => {
  // Getting the Error details.
  // var code = error.code;
  // var message = error.message;
  // var details = error.details;
  console.log(error);
});

NOTE: firebaseConfig is from Firebase Console -> Project Overview -> + Add app -> Web.

Sample cloud functions.

const functions = require('firebase-functions');

exports.test_message_firebase_json = functions.https.onRequest((req, res) => {
  const message = req.body.data.message;
  res.status(200).json({
    data: {
      message: message
    }
  });
});

NOTE: Note data input and output need to wrapped around data if using Cloud Functions for Firebase client SDK. Refer to Create Compatible Cloud Functions for Firebase With Python (Callable from Cloud Functions for Firebase client SDK).

NOTE: Cloud Functions for Firebase client SDK comes with certain convinience such as Firebase Authentication integration.

Firebase Hosting Rewrites Request

If you are using Firebase Hosting - hosting requests to cloud functions, you will realize the SDK will always call https://us-central1-PROJECT_NAME.cloudfunctions.net/test_message_firebase_json and the rewrite to /functions/test_message_firebase_json would not work.

Check the source will uncover that the url is pretty much hardcoded, and the only opportunity to change it is via useFunctionsEmulator.

NOTE: firebase.functions.Functions docs.

_url(name: string): string {
  const projectId = this.app_.options.projectId;
  const region = this.region_;
  if (this.emulatorOrigin !== null) {
    const origin = this.emulatorOrigin;
    return `${origin}/${projectId}/${region}/${name}`;
  }
  return `https://${region}-${projectId}.cloudfunctions.net/${name}`;
}

useFunctionsEmulator(origin: string) {
  this.emulatorOrigin = origin;
}

Use the following code to call /functions/nuanxindan/us-central1/test_message_firebase_json.

functions.useFunctionsEmulator('/functions');
const testMessage = functions.httpsCallable('test_message_firebase_json');

Edit rewrites in Firebase Hosting firebase.json.

{
  "hosting": {
    ...
    "rewrites": [
      {
        "source": "/functions/nuanxindan/us-central1/test_message_firebase_json",
        "function": "test_message_firebase_json"
      },
      {
        "source": "/functions/test_message_json",
        "function": "test_message_json"
      }
    ]
  },
  ...
}
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.