ColdFusion 11 Will Not Accept Incoming Empty Cookie Values
I've been doing a lot of work with cookies lately and I ran into a really odd breaking change in ColdFusion 11. It seems that ColdFusion 11 will not accept or acknowledge incoming cookies (in the request headers) that have empty values. This worked in ColdFusion 10; but, suddenly stopped working in ColdFusion 11.
Demonstrating this is quite easy. In the following code, I'm check to see if a cookie exists. If it doesn't exist, I create it. And, if it does exist, I'm going to set its value to the empty string. Keep in mind that we are never deleting the cookie; in both cases, we're just setting its value.
<cfscript>
if ( structKeyExists( cookie, "nickname" ) ) {
writeOutput( "Cookie exists, clearing it." );
// NOTE: We are NOT DELETING the cookie here, we are simply setting the
// value of the cookie to an empty string.
cookie.nickname = "";
} else {
writeOutput( "Cookie missing, creating it." );
cookie.nickname = "Sonic Boom";
}
</cfscript>
Now, when we run this page a few times in ColdFusion 10, we get the following (concatenated) output:
Cookie missing, creating it.
Cookie exists, clearing it.
Cookie exists, clearing it.
Cookie exists, clearing it.
As you can see, the cookie still exists even when the request headers send it as an empty value:
Now, when we run the same page a few times in ColdFusion 11, we get the following (concatenated) output:
Cookie missing, creating it.
Cookie exists, clearing it.
Cookie missing, creating it.
Cookie exists, clearing it.
As you can see, the very existence of the cookie - from the point of view of the ColdFusion 11 server - is toggling with each request. And, when we look at the network activity, we can clearly see that an empty value in the request headers results in a missing cookie:
While this breaking behavior is unfortunate, we can move toward consistent behavior by changing the way we think about cookies. Instead of thinking about existing vs. non-existing values, we can shift our thinking toward empty vs. non-empty values. If you remember how the CGI scope works, it never throws an error when accessing non-existing keys; rather, it just returns the empty string. We can mimic this behavior by moving the cookie access into a method that safely accesses the cookie scope:
<cfscript>
if ( len( getCookieValueSafely( "hello" ) ) ) {
writeOutput( "Cookie populated, clearing it." );
cookie.hello = "";
} else {
writeOutput( "Cookie empty, populating it." );
cookie.hello = "world";
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I safely return the cookie value with the given name. If the cookie exists, the
* value is returned. If the cookie doesn't exist, the empty string is returned.
*
* @name I am the name of the cookie being accessed.
* @output false
*/
public string function getCookieValueSafely( required string name ) {
var cookieValue = structKeyExists( cookie, name )
? cookie[ name ]
: ""
;
return( cookieValue );
}
</cfscript>
Now, this isn't exactly the same demo as the first one; but, it produces consistent behavior in both ColdFusion 10 and ColdFusion 11. As you can see, we've shifted the thinking from "existence" toward "population." In doing so, we can get around the breaking change in ColdFusion 11. And, when we run this page a few times, we get the (concatenated) output in both ColdFusion 10 and ColdFusion 11:
Cookie empty, populating it.
Cookie populated, clearing it.
Cookie empty, populating it.
Cookie populated, clearing it.
As a final note, I should say that when you set the cookie value to the empty string, neither ColdFusion 10 nor ColdFusion 11 is sending an "expires" header back the browser. Meaning, ColdFusion 11 is not looking at the empty string as an "intent to delete" the cookie. As such, I definitely consider this a bug in the way ColdFusion 11 is parsing the cookies on the server-side.
Want to use code from this post? Check out the license.
Reader Comments
@All,
Looking at the response headers, I wonder if the bug is actually in how ColdFusion 11 represents the empty-string in the HTTP response headers. In ColdFusion 10, the response is:
NICKNAME=""
... and in ColdFusion 11, the response is:
NICKNAME=
Notice that in ColdFusion 11, the empty string is not wrapped in double-quotes. I wonder if that is causing the value to be nullified on the server? Not sure. There's definitely a bug here; but, it's unclear as to whether or not the bug is in the sending of the cookie response or in the parsing of the cookie request.
@All,
Looks like Steve Vail may have reported a similar bug a few months ago:
https://bugbase.adobe.com/index.cfm?event=bug&id=4043038