Flight Mode - Cookies

Thursday, May 23, 2013 6 minute read Tags: offline-storage flight-mode cookies
Hey, thanks for the interest in this post, but just letting you know that it is over 3 years old, so the content in here may not be accurate.

In the beginning there was a simple way to store data offline in an application, or more accurately, across sessions, and that is the HTTP Cookie.

Cookies are used for everything, they can track you for spammers, expose your secure connections for hackers and they can be used for legitimate purposes which I’m going to look at here.

The Cookie is the oldest form of offline storage available on the web, first emerging in the mid 90’s with Netscape. All browsers support them so it’s your most easily accessible cross-browser storage solution.

Benefits of Cookies for storage

There are a few aspects to cookies that make them appealing for storing offline data so let’s have a look at a few of them.

Since cookies are part of the HTTP Header they are included in every request that you make which can be useful if you want to sync the data that’s been created while the application is offline back to the server when the user reconnects. There’s no special AJAX request you’d need to create to handle the sync, any request would do, it’s just up to your server to handle said cookies. This has an obvious downside though, the more you store in cookies the bigger your request/response payload is going to be, so keep that in mind if you want to use cookies for storing data, particularly when limited data connections are applicable, such as on mobile devices).

Expiry is another benefit that cookies bring to the table. If you’re storing data offline you may be wanting to get rid of it after a certain time period to prevent it from becoming stale. Cookies have an expiry date built into them when they are created, meaning that when you first set up your stored data you can determine just how long you want it to hang around. Admitted it won’t “magically” disappear if the user is offline at the time, but it will expire through new requests that are done.

Drawbacks of Cookies for storage

Unsurprisingly there are some drawbacks to using cookies, some pretty major ones to be exact too, the first main drawback is that cookies are simply not designed to be used this way. While it might sound great to be able to have your offline data sent to the server without you needing to do anything it really starts to come apart when you want to store much data. Cookies can only handle which means that they’re best used for little flags, maybe tracking a simple preference like which theme to use.

Another major drawback is that cookies have the laxest cross-origin restrictions of all the offline storage options we’ll be looking at. As I mentioned earlier cookies were a common tool in the spammers toolbox and that was because you could very easy get data out of them without owning the domain, sure you still had to get your code into the page but if your serving ads then you’re part of the way there already.

Finally the API for cookies really does leave a lot to be desired. Don’t get me wrong there’s a myriad of wrapper APIs for the document.cookies object that’ll help you add/remove cookies but it doesn’t solve the fundamental problem, cookies are only strings, meaning if you want to store an object of some description it’s serializing to JSON for you. This really starts to fall over when you want to be able to query the data. If you’ve got lots of objects you’ll have to get them all back out and do in-memory querying of the data.

While it’s an exercise in reinventing the wheel we’ll have a look at how to create a very simple key/value storage API on top of cookies.

We’ll be using our FlightMode API and creating a new adapter which internally uses PPK’s cookie API.

First things first, how are we storing our data across two types cookies, one is going to be a cookie to track the IDs of the items in the store and the other will be storing the individual items. The reasons for this is we want to avoid exceeding the limits of what we can store in each cookie and additionally we want to be easily able to look up values based on a key.

When we create a new store we’ll check if there’s a tracker cookie, if not we’ll create one:

var CookieAdapter = function (storeName) {
    this.storeName = storeName;

    var cookie = readCookie(storeName);

    if (!cookie) {
        cookie = [];
        createCookie(storeName, JSON.stringify(cookie));
    } else {
        cookie = JSON.parse(cookie);
    }

    this.cookie = cookie;
};

Now before we create an add method we’ll need to be able to create IDs, we could do this a couple of ways, we could use the length of our tracking cookie or instead I’m going to use a GUID, here’s a simple function to generate one:

function guid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0;
        var v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

Ultimately all we will be storing is JSON representations of the objects that we push into our store, here’s how an add method would come together:

CookieAdapter.prototype.add = function(obj) {
    var id = guid();
    createCookie(id, JSON.stringify(obj));
    this.cookie.push(id);
    createCookie(this.storeName, JSON.stringify(this.cookie));
    return id;
};

First off we’ll generate a new GUID, then insert the record as a new cookie using that ID as the cookie name. Finally we’ll update tracker with the new value.

You can find the rest of the implementation in the github repository.

Conclusion

In this part we’ve taken a look at the idea of using cookies as a storage model for when our application is offline. We’ve seen that they have the advantage of automatically being sent to our server as they are part of the HTTP header.

We’ve also seen that there’s some really big warning signs that say using cookies for more than just really simple state is a bad idea, they are all just stored as strings meaning that any manipulation has to be done in memory after deserializing all the data.

If you’re curious to see an implementation of cookies for storage in the wild you can check out Qantas, they use cookies to store information like your recent search options. There’s a usercontext cookie that contains the information about where you are that could be wanting to start a flight from.

All in all cookies are not really a good option when it comes to store data for our offline application.