Converting HTTP Header Values To UTF-8 In ColdFusion
A few months ago, I discovered that Cloudflare has a "managed transform" rule that'll inject HTTP headers for the location information associated with the visitor's IP address. From the HTTP headers — CF-IPCountry, CF-Region, and CF-IPCity — I can get the two-character country code, state, and city, respectively. What I didn't realize until I looked at the logs is that these header values aren't UTF-8 encoded, they're ISO-8859-1 encoded. As such, I have to explicitly convert them to UTF-8 in my ColdFusion application.
HTTP Headers Have No Standard Encoding
As far as I understand, HTTP headers have no standard encoding. According to ChatGTP, header values are either passed-through as an opaque set of bytes; or, they're interpreted as (Latin-1) ISO-8859-1 due to an historical (but no longer mandated) HTTP/1.1 specification. In the context of an Adobe ColdFusion 2025 application running on a Windows VPS behind IIS, it's possible that IIS is mistakenly decoding the UTF-8 bytes injected by Cloudflare.
Which is to say, what I'm doing in this post may not be generally applicable. HTTP headers should be evaluated and transformed on an as-needed basis.
Converting Between ISO-8859-1 and UTF-8
ColdFusion provides native methods for encoding and decoding character encodings. As such, converting between ISO-8859-1 and UTF-8 is just a matter of decoding the ISO-8859-1 value back into a byte-array and then re-encoding the byte-array into a UTF-8 string.
I had trouble testing this locally with a CFHttp tag; but, luckily the Page Speed Plus website will ping any URL for free from several locations around the world — one of which is São Paulo. This gave me an opportunity to see how the accented character, ã, could be transformed on my ColdFusion server.
To test, I put together the following CFML script. It looks at two HTTP headers injected by Cloudflare — CF-IPCity and CF-Region — and outputs both the original value and the charset-converted value:
<cfscript>
// Get incoming HTTP request headers.
headers = getHttpRequestData( false ).headers;
// Get geographic headers injected by Cloudflare transformer.
ipCity = ( headers[ "CF-IPCity" ] ?: "" );
ipRegion = ( headers[ "CF-Region" ] ?: "" );
writeOutput( "<h1> Cloudflare Charset Conversion </h1>" );
writeDump([
[
original: ipCity,
converted: charsetConvert( ipCity, "iso-8859-1", "utf-8" )
],
[
original: ipRegion,
converted: charsetConvert( ipRegion, "iso-8859-1", "utf-8" )
]
]);
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I convert the given string from one charset to another.
*/
public string function charsetConvert(
required string input,
required string fromEncoding,
required string toEncoding
) {
return charsetEncode( charsetDecode( input, fromEncoding ), toEncoding );
}
</cfscript>
When I deploy this to my IIS server and ping it with Page Speed Plus, here's the result I see from São Paulo:
As you can see in the screenshot, the original HTTP header decoding exposed by ColdFusion's getHttpRequestData() function mangled the accented character in "São Paulo". But, by decoding the value back into bytes and then re-encoding it as UTF-8, I'm able to access the proper string value.
Again, I don't think that you can universally apply this approach to all incoming HTTP headers. I'm applying it here, to Cloudflare's location headers, because they've proven to be problematic in my Adobe ColdFusion 2025 + IIS application context. Your mileage may vary depending on your web server, reverse proxies, and ColdFusion version.
Want to use code from this post? Check out the license.
Reader Comments
These are the changes that I made to Big Sexy Poems to cast the Latin-1 encoding to UTF-8 encoding:
Commit
ec5961You should be able to create a transform response override in Cloudflare to force the header to utf-8.
@Spills,
Oh interesting - a good point to raise. That said, I do think there is something nice about having this code in the source control. Since I'm just a single person, I try to keep as much as I can in the code itself so that I don't have to remember where all this logic is the next time I set up a site.
But, I also acknowledge that I'm only using like 1% of what Cloudflare can do 😆
@Ben Nadel, One thing about Cloudflare is that their API is amazing and you could probably do a whole site setup script using their API.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →