According to the ColdFusion documentation, header values with the same name will be grouped into an array:

The response headers formatted into a structure. Each element key is the header name, such as Content-Type or Status_Code. If there is more than one instance of a header type, the type values are put in an array.

It turns out that this isn't actually true; ColdFusion doesn't put them into an Array - it puts them into a Struct that has index-based keys. So, you can't call arrayToList() or arrayLen() on it; but, you can iterate over the keys and then access the sub-values like they are array indicies.

To explore this behavior, I set up a page that sets two CFHeader values using the same name:

<!--- Notice that we are providing two header entries, both with the name "X-Test." --->

<cfheader name="X-Test" value="first-name=Kim" />

<cfheader name="X-Test" value="last-name=Smith" />

<cfcontent

type="text/plain"

variable="#charsetDecode( 'true', 'utf-8' )#"

/>

As you can see, both CFHeader tags attempt to set an HTTP header with the name "X-Test".

Then, I created a demo page that makes a CFHttp request to consume the above page and examine the headers. In the following code, I'm dumping out the raw response as well as a normalized header response:

<cfscript>

// Get our remote resource that will send back multiple HTTP Headers with the same

// name, but different values.

resource = (

"http://" &

cgi.server_name &

getDirectoryFromPath( cgi.script_name ) &

"get.cfm"

);

resourceRequest = new Http(

method = "get",

url = resource,

getAsBinary = "yes"

);

result = resourceRequest.send().getPrefix();

// Output the raw response.

writeDump(

var = result,

label = "Multi-Header Test"

);

// Output the normalized headers in which each header value is a simple value.

writeDump(

var = getNormalizedHeaders( result.responseHeader ),

label = "Normalized Headers"

);

// ------------------------------------------------------ //

// ------------------------------------------------------ //

/**

* I return a normalized set of headers in which every value is a "simple value".

* if tere are headers with the same value, they are collapsed down into a single

* comma-delimited list.

* ---

* From the spec - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2

* ---

* >>> Multiple message-header fields with the same field-name MAY be present

* >>> in a message if and only if the entire field-value for that header field

* >>> is defined as a comma-separated list [i.e., #(values)]. It MUST be

* >>> possible to combine the multiple header fields into one "field-name:

* >>> field-value" pair, without changing the semantics of the message, by

* >>> appending each subsequent field-value to the first, each separated by a

* >>> comma. The order in which header fields with the same field-name are

* >>> received is therefore significant to the interpretation of the combined

* >>> field value, and thus a proxy MUST NOT change the order of these field

* I return a single, normalized header value that ensures that complex values are

* collapsed down into a single, comma-delimited list.

*

* @output false

*/

public string function getNormalizedHeader( required any value ) {

if ( isSimpleValue( value ) ) {

return( value );

}

// If we get this far, the given header value is complex and need to be collapsed

// down. The ColdFusion documentation states that this value will be an array:

// ---

// "If there is more than one instance of a header type, the type values are put

// in an array."

// ---

// But, it's not. It's actually a FastHashTable; so, we have to convert it from a

// struct to an array so that we can easily collapse it down into a list.

var valuesCollection = [];

for ( var pseudoIndex in value ) {

arrayAppend( valuesCollection, value[ pseudoIndex ] );

}

return( arrayToList( valuesCollection, ", " ) );

}

</cfscript>

When we run the above code, we get the following page output:

I'm normalizing the header values by collapsing like-named headers into a single comma-delimited list. According to the HTTP spec, you should be able to do this; but, some reading that I've done suggests that the effectiveness of this depends on the context in which the headers are being consumed. I'm definitely not an HTTP protocol expert by any stretch of the imagination, so take this all with a grain of salt.

100% of job board revenue is donated to Kiva. Loans that change lives — Find out more »

Reader Comments

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments

Live in the Now

Oops!

Name:

Email:

( I keep this private )

Website:

Comment:

Subscribe to comments.

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please
do not post unrelated questions or
large chunks of code. And, above all, please be nice to each other - we're trying to
have a good conversation here.

I am the co-founder and lead engineer at InVision App, Inc — the world's leading prototyping,
collaboration & workflow platform. I also rock out in JavaScript and ColdFusion 24x7 and I dream about
promise resolving asynchronously.