Skip to main content
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Brice Green
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Brice Green

Converting HTTP Header Values To UTF-8 In ColdFusion

By
Published in Comments (4)

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:

Screenshot of Page Speed Plus showing that Latin-1 characters were property converted to UTF-8.

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

16,115 Comments

@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 😆

2 Comments

@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

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel
Managed hosting services provided by:
xByte Cloud Logo