Getting a 404 Error Dealing With File Uploads To Storage In Firebase?

I am a huge proponent of Firebase and interestingly, up until recently, I had never used Firebase Storage. Instead, I usually opt for Amazon’s S3 service which I am familiar with. Wanting to keep everything in the one service is appealing to me, so I started to add in file upload functionality in a Firebase Cloud Function.

It was not as straightforward as I would have hoped. I am using Express with Firebase and the Google Cloud NPM package as documented in code examples and numerous tutorials.

After adding in the @google-cloud/storage package into my Cloud Function file, I plumbed it all in and figured it would work. Then I got this vague error.

{
    "errors": [
        "domain": "global",
        "reason": "notFound",
        "message": "Not Found"
    ]
}

Even with an error message, I was left scratching my head. I had nothing I could really Google, looking through the documentation failed to give me the answer and then out of frustration and trial and error, I discovered the cause.

This is the code that I had setting up my storage object and bucket instance. Tell me if you can spot the problem.

import { Storage } from '@google-cloud/storage';
const storage = new Storage();

const bucket = storage.bucket('steem-engine-dex');

The problem is with the bucket name, I also had to add in the project ID as well.

storage.bucket('steem-engine-dex.appspot.com', {
    userProject: 'steem-engine-dex'
});

The bucket name in Firebase requires adding .appspot.com into the bucket name and sure enough, if you go into Firebase itself and into the Storage section, you’ll notice something that points to this.

The bucket name after the protocol gs:// actually has the bucket name with appspot.com in it. Unless I am blind, nowhere does it mention any of this in the documentation, it really tripped me up.

I wasted a lot of time working this out. So, hopefully, if you have experienced the same issue, this blog post saved you a few hours or days worth of wasted work. Happy coding.

Solving The Issue: Firebase App named ‘[DEFAULT]’ already exists

Recently whilst I was attempting to port over a TypeScript/Webpack based Aurelia application to work with Aurelia’s newly released server-side rendering functionality, I encountered an annoying error with Firebase Firebase App named '[DEFAULT]' already exists.

Previously, my code looked like this:

import * as firebase from 'firebase';

const config = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: ""
};

export default firebase.initializeApp(config);

Because of the way server-side rendering works, it meant that Firebase was being spun up multiple times in my app. This previously wasn’t a problem because of one codebase. To fix it, you just need to alter your default export a little bit.

Firebase has a little unknown array of apps, which allows us to check its length. If there are no apps, the length will be zero so we initialise our app, otherwise, we export our Firebase app instance.

import * as firebase from 'firebase';

const config = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: ""
};

export default !firebase.apps.length ? firebase.initializeApp(config) : firebase.app();

Save the above in a file called firebase.js or firebase.ts and then import it into parts of your app where you need Firebase.

How To Alias Cloud Functions In Firebase

Firebase Cloud Functions are fantastic, but the URL that you get to run them isn’t so nice. You’ll get given a URL that looks like the following when you create some cloud functions:

https://us-central1-demoapp.cloudfunctions.net/functionName

If you are wanting to use Firebase to build an API for your application for example (like I wanted to), then you would probably prefer your URL looks like this:

https://myapp.com/functionName

Fortunately, you can. The only downside is you have to use Firebase hosting if you want to be able to alias your functions to your name. If you’re self-hosting your own site somewhere else and using Firebase, then you can’t alias cloud functions.

To alias cloud functions, open up your firebase.json file and inside of the hosting and rewrites section add in your rule. My example showcases an API endpoint which gets sent to a Firebase cloud function called api which handles the request.

{
    "database": {
        "rules": "database.rules.json"
    },
    "hosting": {
        "public": "public",
        "rewrites": [
            { "source":"/api/**", "function":"api" },
            {
                "source": "**",
                "destination": "/index.html"
            }
        ]
    }
}

In my instance, I have a single page application so I have created a wildcard rewrite to send all requests to the index.html file so my Javascript framework can take over.

All you have to remember is source and function where source is your URL pattern (which supports wildcards and matchers) and function is the name of your created function inside of functions/index.js.

I highly recommend installing and using Express to handle your routing needs inside of cloud functions if you’re wanting to work with aliases, especially for Firebase driven API’s.

In a future article I’ll show you how you can create an API using Firebase and alias the functions.

Exciting New Firebase Features Announced at Google IO 2017

Admittedly, Google’s developer event IO has grown to be quite interesting the last couple of years. This year (2017) I was excited to see what would be announced in the world of Firebase.

I’ve been using Firebase on and off for the last couple of years. Recently, I’ve found a renewed sense of excitement in using Firebase again (especially after cloud functions were released).

A few of the new features are more mobile-oriented, Firebase likes to focus on mobile developers and applications but it has value for all platforms.

Cloud functions now support custom domains

Cloud functions are great, but the one thing I hated about them was the silly long CDN URL that you get. This meant you couldn’t use cloud functions as an API.

I have an application I wanted to create an RSS feed on. I didn’t want to tell my users to access the CDN URL that Google provides, so I hacked something else together.

There is a way you can use a custom domain using a third-party proxy, but honestly, I hate having so many moving parts in my applications and that approach is hacky.

With the new announcement, you can now use a custom domain and point a URL at a cloud function only if you use Firebase hosting. In your Firebase configuration file, you pass in a rewrite array and tell it what function to run when a certain URL is accessed.

This means if you’re using Firebase hosting, you can now create API endpoints and even pre-render pages for single page applications without using a third-party service. Neat!

You still cannot add a custom domain to cloud functions if you don’t want to use Firebase hosting. But this is a great start and hopefully, they expand upon it.

Phone authentication

This is a great feature the Firebase team have rolled into their core offering. After acquiring the Fabric team from Twitter a few months back, the newly introduced phone authentication is a continuation of Fabric’s Digits product.

This now makes Firebase’s already great authentication even better with another addition more oriented towards mobile applications. Still, for desktop applications, it is convenient or hybrid applications.

Open sourcing SDK’s

One of the biggest criticisms of Firebase is the public SDK’s are not open source. Currently, you get a minified alphabet soup mess of code, that all changes with Firebase SDK’s going public.

Overall a pretty safe announcement from the Firebase team. But, a good sign that Google are committed to Firebase and it isn’t going anywhere anytime soon.

Enabling CORS Middleware In Firebase Cloud Functions

Firebase Cloud Functions are great, but there might come a time where you need CORS support. This can be enabled easily by using the CORS middleware.

The documentation does detail part of the process, but it doesn’t mention you need to install the cors package and also specify origin: true as a configuration option. If you’re new to Node.js, this might catch you off guard.

Go into your functions directory in your application and in your terminal: npm install cors --save this will add the CORS middleware package to your package.json.

Open up your index.js file in the functions directory and add in the following:

const cors = require('cors')({
  origin: true
});

exports.helloWorld = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        res.send("Hello from Firebase!");
    });
});

Notice how we use the CORS middleware function inside of our request handler? You’ve just added in CORS. Essentially what is happening here is, you’re taking the actual response and then running it through the cors middleware which then makes it a cross-origin request.

It is possible to set the headers manually on your request without the cors package, but the easiest and cleanest solution is using the cors middleware instead.

Convert A Firebase Database Snapshot/Collection To An Array In Javascript

Because Firebase is a NoSQL JSON data store, you might have noticed that when you get some data from Firebase that it is an object. If the title wasn’t obvious enough, we are talking about using Firebase Realtime Database in a web application.

Take the following example:

firebase.database().ref('/posts').on('value', function(snapshot) {
    console.log(snapshot.val());
});

Let’s imagine that we have 20 posts in our database. You’ll get back an object containing keys and objects for all of our imaginary posts.

If you’re working with a Javascript framework or library such as Aurelia, then you’ll know that iterating an object opposed to an array is more complicated (especially HTML templating).

So, here is a function I ended up writing which I use quite a lot in my Firebase applications:

function snapshotToArray(snapshot) {
    var returnArr = [];

    snapshot.forEach(function(childSnapshot) {
        var item = childSnapshot.val();
        item.key = childSnapshot.key;

        returnArr.push(item);
    });

    return returnArr;
};

I am a big fan of verbose functions, although using the power of modern spec Javascript you can create a more condensed shorthand equivalent of the above function.

To use our newly created function

firebase.database().ref('/posts').on('value', function(snapshot) {
    console.log(snapshotToArray(snapshot));
});

If you are using a transpiler like Babel, writing using TypeScript or targeting evergreen browsers like Chrome and Firefox, a nicer solution is:

const snapshotToArray = snapshot => Object.entries(snapshot).map(e => Object.assign(e[1], { key: e[0] }));

You call our shorthand function the same, but it’s a less verbose and harder to understand one-line function. Special thank you to the commenters below who have proposed their own solutions as well.