Monday, October 27, 2014

notes to self: java HttpURLConnection weirdness

We have a suite of external tests we run for one of our adservers that happen to be written in Java and I'm writing a new test to ensure a cookie has been properly placed.

The connection code I ended up making was like this:HttpURLConnection.setFollowRedirects(false);HttpURLConnection connection = (HttpURLConnection) currentUrl.openConnection();connection.connect();
What's odd about that is that we are setting whether to follow redirects on a static class field. Also, empirically it has to be done before the openConnection() on currentUrl (an instance of URL). Frankly it kind of feels like programming via side-effect (as my coworker points out this pretty much breaks any sane threading model).

Update: this stackoverflow question about why is "setFollowRedirects()" a static, class-wide method. It turns out there's an instance-specific "setInstanceFollowRedirects()" that you can call after creation... the page suggests that it would have been less confusing and more in line with the convention used elsewhere if the two were called "setDefaultFollowRedirects()" and "setFollowRedirects()", respectively.

The other weird thing is that while a response might have multiple "set-cookie" lines, some of the convenience functions HttpURLConnection provide assume the field name can be used as a unique key, so that getHeaderField() returns a single String, even if there were multiple lines using. A stack overflow article gave me the following: static String[] getAllValuesForHeaderKey(HttpURLConnection con, String header) { List<String> values = new ArrayList<String>(); int idx = (con.getHeaderFieldKey(0) == null) ? 1 : 0; while (true) { String key = con.getHeaderFieldKey(idx); if (key == null) break; if (header.equalsIgnoreCase(key)) values.add(con.getHeaderField(idx)); ++idx; } return values.toArray(new String[values.size()]); }
Which is roughly the same as getHeaderField() but returns an array of Strings instead.