What are Cloud Functions?

What are Cloud Functions?

Resizing Images after Upload

Resizing Images after Upload

Creating a REST Endpoint with Cloud Functions

Creating a REST Endpoint with Cloud Functions

Reacting to Database Events

Reacting to Database Events

# Creating a REST API with Cloud Functions

One cool feature of Firebase Cloud Functions is that you can build a RESTful API with them. Without having to write the whole overhead code regarding routing etc.

Instead, you define the URL as part of your function name and then simply write the code that should be executed whenever a request hits that endpoint. Any filtering regarding allowed HTTP verbs has to be done inside the function then though.

The best thing is, that you can easily use Express.js in your cloud function code - that really allows you to build powerful REST APIs in a serverless manner - with all the advantages serverless brings.

# Creating a REST API Endpoint Function

You create a REST API endpoint function by listening to the https object on the functions object exposed by the firebase-functions package:

exports.uploadFile = functions.https.onRequest((req, res) => {
  ...
});

Please note the req and res parameters of the function. These will be passed in automatically by Firebase. That's Express.js in action!

How would you reach this function then?

The exact endpoint will be given to you by Firebase once you deploy the function. The path will be /uploadFile though - because you named the function uploadFile (=> exports.uploadFile).

Inside the function, you can do whatever you want to do, you can run your normal Node.js/ Express.js code in there.

The following example function takes a file and stores it on cloud storage. This allows you to send files (and store them) via a REST API instead of just the Firebase SDK (which you'd normally have to use).

const functions = require("firebase-functions");
const os = require("os");
const path = require("path");
const cors = require("cors")({ origin: true });
const Busboy = require("busboy");
const fs = require("fs");

const gcconfig = {
  projectId: "fb-cloud-functions-demo",
  keyFilename: "my-fb-key.json"
};

const gcs = require("@google-cloud/storage")(gcconfig);

exports.uploadFile = functions.https.onRequest((req, res) => {
  cors(req, res, () => {
    if (req.method !== "POST") {
      return res.status(500).json({
        message: "Not allowed"
      });
    }
    const busboy = new Busboy({ headers: req.headers });
    let uploadData = null;

    busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
      const filepath = path.join(os.tmpdir(), filename);
      uploadData = { file: filepath, type: mimetype };
      file.pipe(fs.createWriteStream(filepath));
    });

    busboy.on("finish", () => {
      const bucket = gcs.bucket("fb-cloud-functions-demo.appspot.com");
      bucket
        .upload(uploadData.file, {
          uploadType: "media",
          metadata: {
            metadata: {
              contentType: uploadData.type
            }
          }
        })
        .then(() => {
          res.status(200).json({
            message: "It worked!"
          });
        })
        .catch(err => {
          res.status(500).json({
            error: err
          });
        });
    });
    busboy.end(req.rawBody);
  });
});

It's worth noting that we also use some Express.js middleware in this function (CORS).