Accessing Cookies With The Same Name In Lucee CFML 5.3.6.61
This morning, I took a look at the fact that the first cookie wins in both JavaScript and ColdFusion when multiple cookies are assigned with the same name. As a quick follow-up post, I wanted to see if I could access all of the conflicting / colliding cookies in the HTTP Header data even if the cookie
scope only presents one. And, in both ColdFusion and Lucee CFML, we can access to the HTTP headers using the getHttpRequestData()
function.
To test this, I created a simple Lucee CFML page that sets four cookies with the same name but using various key-casings and domains:
<cfscript>
// With "benben" as lowercase.
cookie[ "benben" ] = {
value: "lowercase for general",
domain: ".local.invisionapp.com",
secure: true,
preserveCase: true,
expires: "never"
};
cookie[ "benben" ] = {
value: "lowercase for specific",
domain: ".projects.local.invisionapp.com",
secure: true,
preserveCase: true,
expires: "never"
};
// With "benben" as uppercase.
cookie[ "BENBEN" ] = {
value: "uppercase for general",
domain: ".local.invisionapp.com",
secure: true,
preserveCase: true,
expires: "never"
};
cookie[ "BENBEN" ] = {
value: "uppercase for specific",
domain: ".projects.local.invisionapp.com",
secure: true,
preserveCase: true,
expires: "never"
};
</cfscript>
Now, in Lucee CFML, the cookie
scope presents the first cookie in the above block with value, lowercase for general
. But, the HTTP Cookie
header will contain all four cookies, looking something like this:
benben=lowercase%20for%20general; benben=lowercase%20for%20specific; BENBEN=uppercase%20for%20general; BENBEN=uppercase%20for%20specific
We can access this string with getHttpRequestData()
. Of course, we'll have to do a little parsing for ourselves:
<cfscript>
// Compare the Lucee-exposed Cookie scope to what's actually in the HTTP headers.
dump( label = "Cookie Scope", var = cookie );
dump( label = "Cookie Headers", var = getCookieHeaders() );
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I parse the HTTP Cookie Header into a collection of name/value pairs.
*/
public array function getCookieHeaders() {
var httpHeaders = getHttpRequestData().headers;
var cookieHeader = ( httpHeaders.cookie ?: "" );
var results = cookieHeader
.listToArray( ";" )
.map(
( pair ) => {
// CAUTION: I don't actually know much about the security rules
// around cookie encoding. As such, I'm going to use the strictest
// parsing rules in canonicalize(), which will throw an error for
// double-encoding and mixed-encoding formats. This may not be what
// is appropriate for cookies.
// --
// If you wanted a more relaxed version, you could just use the
// urlDecode() function for general URL escape sequences.
var sanitizedPair = ( canonicalize( pair, true, true ) ?: "" );
return({
name: sanitizedPair.listFirst( "=" ).trim(),
value: sanitizedPair.listRest( "=" ).trim()
});
}
)
;
return( results );
}
</cfscript>
If we run this ColdFusion code, we get the following output:
As you can see, even though the cookie
scope only shows us the one cookie value, we can still access all of the conflicting / colliding cookies from the underlying HTTP request data. I don't know if I'll ever need to use this; but, it never hurts to know more than I need to in Lucee CFML 5.3.6.61.
Want to use code from this post? Check out the license.
Reader Comments