Skip to content
Advertisement

Flask, setting JSON in a cookie, and decoding it on the client (in javascript)

I’m setting a cookie in Flask like follows :

response.set_cookie('notice', value = json.dumps(someObject), max_age=None)

If i print json.dumps(someObject) on the server I get :

{"message": "hello", "type": "success"}

On the client side it becomes :

"{"message": "hello"54 "type": "success"}"

I want to decode it on a javascript client what format is it exactly ?

I’d like to decode it and pass it to angular.fromJson(), it looks like there is at least unescaping (of the the “) to do, but I’m surprize to see 54 (the octal ASCII code for the comma)

Advertisement

Answer

The cookie value is quoted by the Werkzeug library to be safe for use in Cookie headers; this includes quoting any commas, semicolons, double quotes and backslashes:

cookie_quoting_map = {
    b',' : b'\054',
    b';' : b'\073',
    b'"' : b'\"',
    b'\' : b'\\',
}

Anything else outside of letters, digits and the characters !#%&'~_`><@,:/$*+-.^|)(?}{= is encoded to an octal codepoint as well. If there are any escaped values in the cookie, the whole cookie is also surrounded by double quotes.

If you need access to the cookie value in JavaScript, you’ll have to decode this again. Values that start with a slash and 3 digits are octal values; a String.replace() call should do:

function decode_flask_cookie(val) {
    if (val.indexOf('\') === -1) {
        return val;  // not encoded
    }
    val = val.slice(1, -1).replace(/\"/g, '"');
    val = val.replace(/\(d{3})/g, function(match, octal) { 
        return String.fromCharCode(parseInt(octal, 8));
    });
    return val.replace(/\\/g, '\');
}

Demo:

> // recreate properly escaped value
> var cookie = ""{\"message\": \"hello\"\054 \"type\": \"success\"}""
> cookie
""{"message": "hello"54 "type": "success"}""
> decode_flask_cookie(cookie)
"{"message": "hello", "type": "success"}"
> JSON.parse(decode_flask_cookie(cookie))
Object {message: "hello", type: "success"}

Advertisement