I’m writing a script that talks to a third-party via an HTTP POST operation to retrieve a special token. The raw POST data is first hashed through an HMAC version of SHA-256 and the result included with the POST data.
To do this I sent all my data through URLEncodedFormat() first to create my own copy of what the raw POST data should look like, then I hashed the result. The problem is ColdFusion’s URL encoding scheme differs from the third-party. They use JAVA’s URLEncoder.
So a little tinkering and I find I can simply create a URLEncoder object, encode my strings, hash, and be on my merry way. Except I was still getting errors even though the hash was now correct when compared against a supplied PERL script using the same data.
I was now thinking that CFHTTP itself was the problem, that it wasn’t encoding the data exactly as the third party wanted. Well now what? Well I spend a few hours trying to figure out how to play with many various JAVA objects to, eventually, mimic an HTTP POST operation and allow me to control how the POST data is encoded.
After a bit of trial and error it worked against a test script that just dumped form data so I can debug things. So I redirect it to the third party and it fails.
Long story short, I finally find that it’s not CFHTTP that’s the problem, but the third-party’s POST data variable names are case sensitive. So is the hash.
So this bit of work I did trying to mimic a POST operation is all for naught. So I now throw it out here in case someone might find it even slightly useful. NOTE: it’s not production quality as I was just hacking around and I’m sure there are easier ways or more proper ways to do this as I rarely do any development in straight JAVA (and I’m not consistent in my scoping because I got lazy), but.. here you go:
URLObject = CreateObject( "JAVA", "java.net.URL" );
URLObject.init( arguments.site_url );
URLConnection = URLObject.openConnection();
URLConnection.setDoInput( TRUE );
URLConnection.setDoOutput( TRUE );
URLConnection.setUseCaches( FALSE );
URLConnection.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
DataOutputStream = CreateObject( "JAVA", "java.io.DataOutputStream" );
DataOutputStream.init( URLConnection.getOutputStream() );
DataOutputStream.writeBytes( arguments.buffer );
DataOutputStream.flush();
DataOutputStream.close();
InputStreamReader = CreateObject( "JAVA", "java.io.InputStreamReader" );
InputStreamReader.init( URLConnection.getInputStream() );
BufferedReader = CreateObject( "JAVA", "java.io.BufferedReader" );
BufferedReader.init ( InputStreamReader );
local.content = "";
do
{
local.buffer = BufferedReader.readLine();
if ( IsDefined( "local.buffer" ))
{
local.content = local.content & local.buffer & Chr(13) & Chr(10);
}
}
while ( IsDefined( "local.buffer" ) );
BufferedReader.close();
The real interesting piece here is that if you set a variable to the return value of a JAVA method and said method returns a NULL value the variable is deleted. So that’s why I’m using IsDefined
.