julio
julio

Reputation: 6748

how to encode cookie data

I'm setting a cookie with some query string values for a page I've built, so that when you revisit the page you will have option set for you.

So if the URL is http://mysite.com/index.php?setting1=blue&orientation=horizontal&background=paper the cookie will store the setting1=blue, orientation=horizontal, and background=paper values to be read back on the next visit.

It seems like most people advise json encoding these values prior to storing in the cookie. However, I'm getting way bigger cookie sizes (like 4-5x bigger!) when json encoding vs. just saving these values in a standard query string format and parsing them later.

Any best practice for this situation?

Upvotes: 3

Views: 9215

Answers (5)

Tim Wickstrom
Tim Wickstrom

Reputation: 5701

If you want to convert a query string to an object take a look at

myQueryString.parseQueryString() // returns object of key value pairs

Requires mooTools More Strings: http://mootools.net/docs/more/Types/String.QueryString

However i like the idea of Base64 more! See below

Credit goes to Ryan Florence for this but this is what i use:

var cookieData = DATATOENCODE.toBase64() // base64 encodes the data

cookieData.decodeBase64() // to decode it

The magic:

/*
---

script: Base64.js

description: String methods for encoding and decoding Base64 data

license: MIT-style license.

authors: Ryan Florence (http://ryanflorence.com), webtoolkit.info

requires:
- core:1.2.4: [String]

provides: [String.toBase64, String.decodeBase64]

...
*/


(function(){

    // Base64 string methods taken from http://www.webtoolkit.info/
    var Base64 = {

    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        encode : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = Base64._utf8_encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                };
                output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
            };
            return output;
        },

        decode : function (input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
            while (i < input.length) {
                enc1 = this._keyStr.indexOf(input.charAt(i++));
                enc2 = this._keyStr.indexOf(input.charAt(i++));
                enc3 = this._keyStr.indexOf(input.charAt(i++));
                enc4 = this._keyStr.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                };
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                };
            };
            output = Base64._utf8_decode(output);
            return output;
        },

        // private method for UTF-8 encoding
        _utf8_encode : function (string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
            for (var n = 0; n < string.length; n++) {
                var c = string.charCodeAt(n);
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                } else if((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                } else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                };

            };
            return utftext;
        },


        _utf8_decode : function (utftext) {
            var string = "";
            var i = 0;
            var c = c1 = c2 = 0;
            while ( i < utftext.length ) {
                c = utftext.charCodeAt(i);
                if (c < 128) {
                    string += String.fromCharCode(c);
                    i++;
                } else if((c > 191) && (c < 224)) {
                    c2 = utftext.charCodeAt(i+1);
                    string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                    i += 2;
                } else {
                    c2 = utftext.charCodeAt(i+1);
                    c3 = utftext.charCodeAt(i+2);
                    string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                    i += 3;
                };
            };
            return string;
        }

    };

    String.implement({
        toBase64: function(){
            return Base64.encode(this);
        },

        decodeBase64: function(){
            return Base64.decode(this);
        }
    });

})();

Upvotes: 1

MattiSG
MattiSG

Reputation: 4026

Well, if you're using MooTools, simply use Hash.Cookie, it's nifty and will get you rid of your headaches by abstracting this stupid cookie storage stuff  :)

Upvotes: 1

Tom van der Woerdt
Tom van der Woerdt

Reputation: 29985

If they're that much bigger, you're probably doing something wrong. setting1=blue can be represented as {"setting1":"blue"} - adding orientation=horizontal gives {"setting1":"blue","orientation":"horizontal"} - it definitely takes more space in the cookie but not that much.

Also, I'd personally recommend against using JSON. It's too easy for an attacker from a different website to set a cookie on your domain which could then get executed as JSON. The NVP "encoding" is more effective if you're only doing key/value storage.

Upvotes: 0

simshaun
simshaun

Reputation: 21476

I don't know if there is a best practice for this, but I would advise using the query string format since it's smaller.

Cookies are transferred with every page request. Less data transferred is almost always better.

Upvotes: 0

alex
alex

Reputation: 490607

Query string format is fine, if it's easy for you to parse them back.

Upvotes: 1

Related Questions