Thursday, October 07, 2010

HTTPS + Basic Auth: Java vs Ruby

For the past couple of weeks I've been working on automating the process of creating an OVA. I considered various tools for the automation but for various reasons that aren't especially relevant here, I ended up going with rake running on top of JRuby. Net result is that for most of the logic I'm writing I have the option of doing it the Java way or the Ruby way. Almost without fail I found myself preferring the more concise Ruby solutions.

Then I found myself needing to do an HTTP GET with basic authentication over HTTPS and verify the server's SSL certificate. Here's the interesting bits of the rakefile with the Java solution:

require 'java'

java.lang.System.setProperty('', 'mykeystore')
java.lang.System.setProperty('', 'password')

class MyAuthenticator <
def getPasswordAuthentication()'userid','password').toCharArray())

task :testjava do
huc ='').openConnection()
print huc.inputStream.to_io.readlines

It's a bit screwy that I have to replace a global authenticator to supply credentials for a single host, but this is just a rakefile so I didn't feel too bad about cutting corners in MyAuthenticator.

Here's the equivalent Ruby code:

require 'net/https'
require 'uri'

task :testruby do
https ='', 443)
https.use_ssl = true
https.ca_file = 'foo.crt'
https.verify_mode = OpenSSL::SSL::VERIFY_PEER

request ='/abc')
request.basic_auth 'userid', 'password'
response = https.request(request)

print response.body

Open-uri would have improved the Ruby code dramatically but as far as I can tell open-uri has some hardcoded assumptions about using the machine-wide CA certs. Setting the userid/password per request is nice, but Java wins the certificate handling hands-down. Ruby has a marginal LOC lead for a single request, but Java catches up as soon as you make the second HTTP request.

Chalk up a rare win for Java on this one.