Using structDelete() With Cookies Does Not Alter Cookie Scope In ColdFusion
For years, I've known that using structDelete() with the Cookie scope, in ColdFusion, will send HTTP response headers to expire the given cookie in the user's browser. However, I don't think I ever thought about what this action was actually doing to the Cookie scope itself. Until yesterday, when I was baffled by the existence of a cookie on the server. After a little investigation, it looks like calling structDelete() on the Cookie scope doesn't actually alter the Cookie scope.
To see this in action, I've put together a small demo that creates a cookie, if it doesn't exist, and then tries to delete it and subsequently check to see if it exists:
<cfscript>
// If the cookie doesn't exist, create it.
if ( ! structKeyExists( cookie, "hello" ) ) {
cfcookie(
name = "hello",
value = "world",
preserveCase = true
);
}
// Delete the cookie from the SPECIAL cookie scope.
// --
// NOTE: Behind these scenes this is actually sending a "Set-Cookie" header with
// an "Expires" date in the past so that the browser knows to flush the cookie
// from the local cache.
structDelete( cookie, "hello" );
// Check to see if structDelete() actually deleted the cookie.
writeOutput( "Cookie exists after structDelete() operation: " );
writeOutput( structKeyExists( cookie, "hello" ) );
</cfscript>
As you can see, I'm using the structDelete() to try to delete the cookie and then using structKeyExists() to see if the cookie scope has been altered. When we run this code, we get the following output:
Cookie exists after structDelete() operation: YES
As you can see, even after the structDelete() call, the cookie still exists in the cookie scope. Considering that the cookie scope acts like a standard scope, this behavior tripped me up a little bit.
Now, if you look in the CFCookie documentation, you will see that it does mention that setting an expires="now" value with the CFCookie tag will set the expiration but not alter the cookie scope:
Expires: now: deletes cookie from client cookie.txt file (but does not delete the corresponding variable the Cookie scope of the active page).
Of course, I'm not setting the "expires" value using the CFCookie tag - I'm deleting the cookie from the scope. But, behind the scenes this seems to be doing (almost) the same thing.
For posterity, I ran the same experiment with the CFCookie tag:
<cfscript>
// If the cookie doesn't exist, create it.
if ( ! structKeyExists( cookie, "hello" ) ) {
cfcookie(
name = "hello",
value = "world",
preserveCase = true
);
}
// Expire the cookie immediately.
// --
// NOTE: Behind these scenes this is actually sending a "Set-Cookie" header with
// a "Max-Age" value of zero so that the browser knows to flush the cookie from
// the local cache.
cfcookie(
name = "hello",
expires = "now",
preserveCase = true
);
// Check to see if cfcookie() actually deleted the cookie.
writeOutput( "Cookie exists after cfcookie(expires) operation: " );
writeOutput( structKeyExists( cookie, "hello" ) );
</cfscript>
As you can see, rather than using structDelete(), I'm using CFCookie to set an immediate expiration. And, when we run the page, we get the same output:
Cookie exists after cfcookie(expires) operation: YES
Since I'm using the CFCookie tag, this behavior is consistent with the documentation.
In the end, I don't think this is a bug; when you call structDelete(), it's clearing doing something akin to setting "Expires" in the background. As such, it makes sense that the use of structDelete() and the use of CFCookie(expires) should result in very similar behaviors. The fact that the Cookie scope can act like a normal struct and hooks into the "expires" workflow is actually a nice-to-have feature, even if it can be a little confusing at times.
Want to use code from this post? Check out the license.
Reader Comments
OK, I'll bite. How *do* you remove that key from the Cookie scope then?
@JC,
I'm not sure that you can - not within the current request. But, the structDelete() action will cause an "expires" Set-Cookie header to get be sent, which should expire the cookie in the browser. Then, the cookie should be absent from subsequent requests.
@All,
As a quick follow-up, I wanted to look at using preserveCase consistently when both setting and expiring cookies:
www.bennadel.com/blog/2973-use-preservecase-consistently-when-setting-and-expiring-cookies-in-coldfusion.htm
Hi Ben...this is insane. Is it not possible to delete a key from the cookie scope struct? Adding an empty string to a cookie is not my idea of deleting a cookie. It seems to be merely changing its value. Any ideas, on how we can actually delete the darn thing permanently?